python 对接阿里通义千问(源码)

通义千问是阿里云自主研发的超大规模语言模型,能够回答问题、创作文字,还能表达观点、撰写代码。

项目源码:

\www\wwwroot\Python\Ai\tongyiqianwen.py

import os,json,pymysql,re
from openai import OpenAI
from datetime import datetime
from flask import Flask, request, render_template
app = Flask(__name__)
@app.route('/tongyiqianwen')
def tongyiwanxiang():
    # 连接数据库
    conn = pymysql.connect(host='localhost', user='xx', password='xx', database='xx')
    # 创建游标
    cursor = conn.cursor() 
    # 执行SQL语句 新增数据 并返回影响行数
    sql1='SELECT * FROM aichatlist ORDER BY id DESC LIMIT 1;'  
    rows = cursor.execute(sql1)
    # 获取所有结果
    # results = cursor.fetchall()
    # 获取单条结果
    results = cursor.fetchone()
    # print(results);
    # 手动提交
    conn.commit()
    conn.close()
    return render_template('tongyiqianwen.html',res=results)
@app.route('/get_data', methods=['POST'])
def get_data():  
    prompt = request.form.get('prompt')
    client = OpenAI(
        # 若没有配置环境变量,请用百炼API Key将下行替换为:api_key="sk-xxx",
        api_key="sk-xxx",
        base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
    )
    completion = client.chat.completions.create(
        model="qwen-plus", # 模型列表:https://help.aliyun.com/zh/model-studio/getting-started/models
        messages=[
            {'role': 'system', 'content': 'You are a helpful assistant.'},
            {'role': 'user', 'content': prompt}],
         
        )
    res=completion.model_dump_json();
    # print(res);
    res=json.loads(res);
    # print(res);
    # print(res['id']);
    # print(res['usage']);
    question=prompt;
    messagex=message=res['choices'][0]['message']['content'];
    message=re.sub('\*\*(.+)\*\*','<strong>\g<1></strong>',message);
    message=re.sub('(\d+\..+strong>)','<h3>\g<1></h3>',message);
    message=re.sub('- (.+)','<li>\g<1></li>',message);
    message=re.sub('(<li(.*li>\n){1,})','<ul>\g<0></ul>',message);
    message=re.sub('([^<>]+)\n','<p>\g<1></p>',message);
    message=re.sub('([^<>]+)。$','<p>\g<1></p>',message);
    message=re.sub('(#|\n)+','',message);
   
    print(message);
    prompt_tokens=str(res['usage']['prompt_tokens']);
    completion_tokens=str(res['usage']['completion_tokens']);
    # 连接数据库
    conn = pymysql.connect(host='localhost', user='root', password='cjfdm', database='hw')
    # 创建游标
    cursor = conn.cursor() 
    # 获取当前时间
    created_at=datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    # 执行SQL语句 新增数据 并返回影响行数
    sql1='INSERT INTO aichatlist(question, message, prompt_tokens, completion_tokens,created_at) VALUES ("'+question+'", "'+message+'", "'+prompt_tokens+'", "'+completion_tokens+'", "'+created_at+'")'  
    rows = cursor.execute(sql1)
    # 手动提交
    conn.commit()
    conn.close()
    res={'question':question,'message':messagex,'prompt_tokens':prompt_tokens,'completion_tokens':completion_tokens,'created_at':created_at}
    return res;
if __name__ == '__main__':
    #配置SSL证书
    # HTTPS的默认访问端口443。
    # 配置443端口和证书绝对路径。'/ssl/cert.pem'需替换为证书文件绝对路径。'/ssl/cert.key'需替换为证书私钥绝对路径。
    # context = ('/www/server/panel/vhost/cert/wenshengtu/fullchain.pem', '/www/server/panel/vhost/cert/wenshengtu/privkey.pem')
    # app.run(debug=true,host="0.0.0.0", port=442, ssl_context=context)
    app.run(debug=true)

www\wwwroot\Python\Ai\templates\tongyiqianwen.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Flask Frontend</title>
    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
    <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/tongyiqianwen.css') }}">
    <link rel="stylesheet" type="text/css" href="//at.alicdn.com/t/c/font_3273867_9vcq0vxqdo9.css">
</head>
<body style="background: #c9b3b3;">
<div class="ModelChatContent__model-chat-content-left--tzckl" >

    <div class="ModelChatContent__main-content--JQHM5" >
    <div class="ModelChatContent__content-wrap--Rp8vg">
        <div class="ModelChatMainSection__model-chat-main-section--holEo ModelChatContent__model-chat-main-section-view--VrCGm" >
            <div class="ModelChatMainSection__model-experience-item-views--XFGcj ModelChatMainSection__no-scrollbar--eBrkm">
                <div class="ModelExperienceItem__model-experience-item--GBdkr ModelChatMainSection__model-experience-item-view--JDnoY" style="width: 96%; min-width: 650px; max-width: 1000px;">
                    <div class="ModelExperienceModelTopSection__model-experience-model-top-section--mOgNJ">
                        <div class="ModelExperienceModelTopSection__left-content--NvlCK">
                            <div class="ModelToggleBtn__model-toggle-btn--rc1so ModelExperienceModelTopSection__model-toggle-btn-view--RP__C ModelToggleBtn__large--OxDZs">
                                <img class="ModelIcon__small--sfkje" src="https://cdn.zlhdsg.com/wp-content/uploads/2020/12/u27981272662464413594fm26gp0.png">
                                <span class="ModelToggleBtn__model-name--vmALa ModelToggleBtn__overflow-hidden--qQQgh">
                                    <div class="efm_ant-typography efm_ant-typography-ellipsis efm_ant-typography-single-line efm_ant-typography-ellipsis-single-line efm-bl-ellipsis-tip css-o1mf1m">Ai问答</div>
                                </span>
                                <i class="bl-iconfont bl-icon-down-line efm-bl-cursor-pointer efm_ai-ml12 efm-bl-icon"></i>
                            </div>
                        </div>
                        
                    </div>
                    <div class="ModelMsgList__model-msg-list--S7Fat ModelExperienceItem__model-msg-list-view--NJNXh">
                        <div class="react-scroll-to-bottom--css-zrvzy-79elbk CustomScrollToBottom__custom-scroll-to-bottom--JMWum ModelMsgList__scroll-wrap--GsQDf">
                            <div class="react-scroll-to-bottom--css-zrvzy-1n7m0yu">
                                <div>
                                    <div>
                                        <div class="QuestionItem__questionItem--VStKA">
                                            <div class="QuestionItem__questionContent--irh2b" style="align-items: center;">
                                                <img class="ModelIcon__middle--yKSXc efm_ai-mr12" src="https://cdn.zlhdsg.com/wp-content/uploads/2020/12/u27981272662464413594fm26gp0.png">
                                                <div class="QuestionItem__content-container--JU2eM">
                                                    <div class="">
                                                        <div>
                                                            
                                                            <div class="tongyi-ui-markdown MarkdownComponent__custom-markdown--BPepQ TextItem__text-item--zHb6h">
                                                                 
                                                                <p>{{ res[1] }}</p>
                                                            </div>
                                                            
                                                        </div>
                                                    </div>
                                                </div>
                                            </div>
                                        </div>
                                        <div class="AnswerItem__answerItem--O_l9d efm_ai-mb0">
                                            <img class="ModelIcon__middle--yKSXc efm_ai-mr12" src="https://cdn.zlhdsg.com/wp-content/uploads/2020/12/u27981272662464413594fm26gp0.png" style="margin-top: 12px;">
                                                <div class="AnswerItem__containerWrap--xVqan">
                                                    <div class="tongyi-ui-markdown MarkdownComponent__custom-markdown--BPepQ efm_ai-mb6">
                                                                    
                                                             {{ res[2]|safe }}

                                                    
                                                </div>
                                                
                                                 <span style="float: right;">创建时间:<span class="timetime3">{{ res[5] }}</span></span>
                                         </div>
                                    </div>
                                 </div>
                            </div>
                    </div>
        </div>
                </div>
            </div>
        </div>
    </div>
    <center>
    <div class="ModelTextArea__model-textarea--aZ7ej ModelTextArea__no-active--nscA9" style="width: 96%; min-width: 650px; max-width: 1000px;">
       
                <div class="ModelTextArea__gradient-bg--YJoM6">
                    <div class="ModelTextArea__textarea-wrap--OYPVC">
                        <div class="ModelTextArea__file-textarea-wrap--LG7uH">
                            <span class="efm_ant-input-affix-wrapper efm_ant-input-textarea-affix-wrapper efm_ant-input-textarea-show-count css-o1mf1m efm_ant-input-outlined ModelTextArea__custom-textarea--Hpytj" data-count="0 / 6000" style="height: auto;">
                                <textarea placeholder="请输入您想问的问题" class="efm_ant-input css-o1mf1m" style="overflow-y: hidden; resize: none; height: 22px; min-height: 52px; max-height: 52px;width:100%;border: 0px;outline: none;"></textarea><span class="efm_ant-input-suffix"><span class="efm_ant-input-data-count">0 / 6000</span></span></span></div><div class="ModelTextArea__right-section--vwbGL"><div class="ChatBtn__chat-btn--UWCJj ChatBtn__disabled--sy3Uk"><i class="iconfont icon-fasong"></i></div></div></div></div></div>
     </center>                       
</div>

<div class="LawTip__law-tip--Mlgtn efm_ai-mt12 efm_ai-mb24">服务生成的所有内容均由人工智能模型生成,其生成内容的准确性和完整性无法保证,不代表我们的态度或观点</div>
</div> 
</div>
<script>

    $(document).ready(function() {
        
        $('.efm_ant-input').bind('input propertychange', function() {
            areat=$(this).val();
            $(".efm_ant-input-data-count").text(areat.length+" / 6000");
            if(areat.length<1){
                $(".ChatBtn__disabled--sy3Uk").attr('disabled','disabled');
                $(".ChatBtn__disabled--sy3Uk").css('cursor','not-allowed');
                $(".ChatBtn__disabled--sy3Uk").css('background','#c3c4d5');
                
            }
            check();
        });
        function check(){
            prompt=$(".efm_ant-input").val();
            if(prompt){
                
                $(".ChatBtn__disabled--sy3Uk").css('cursor','pointer');
                $(".ChatBtn__disabled--sy3Uk").css('background','linear-gradient(47deg, #615ced, #3e2fa7 176%)');
                $(".ChatBtn__disabled--sy3Uk").removeAttr('disabled');
            }
        }
        
        $(".ChatBtn__disabled--sy3Uk").click(function(){
            prompt=$(".efm_ant-input").val();
            $(".TextItem__text-item--zHb6h").text(prompt);
            $(this).attr('disabled','disabled');
            $(".efm_ant-btn-primary").css('background','rgb(98, 74, 255,0.3)');
            $(".ChatBtn__disabled--sy3Uk").css('cursor','not-allowed');
            $(".ChatBtn__disabled--sy3Uk").css('background','#c3c4d5');
            // $(".efm_ai-mb6").css('display','none');
            
             $(".efm_ai-mb6").html("");
            sendali(prompt);
        })
        function sendali(prompt){
            data={
                    'prompt':prompt,
                };   
            $.ajax({
                url: '/get_data',
                type: 'post',
                data:data,
                dataType: 'json',
                success: function(data) {
                    // console.log(data);
                    // 处理返回的数据
                    $(".ChatBtn__disabled--sy3Uk").css('cursor','pointer');
                    $(".ChatBtn__disabled--sy3Uk").css('background','linear-gradient(47deg, #615ced, #3e2fa7 176%)');
                    $(".ChatBtn__disabled--sy3Uk").removeAttr('disabled');
                    // $(".efm_ai-mb6").html(data.message);
                    // typeWriter("efm_ai-mb6",data.message);
                   
                    
                    $(".timetime3").text(data.created_at);
                    var regex = /.+[\n|(。|!)$]/g;
                    var match = data.message.match(regex); 
                    console.log(match);
                    typeWriter(match,0,0);
                    
                    
                    
                },
                error: function(error) {
                    console.error(error);
                }
            });
        }
       
       
        // var counter = 0;
        // function showCharacter(classx,htmlContent) {
        //     console.log(htmlContent);
        //     // console.log(htmlContent.length);
        //     // console.log(counter);
        //     if (counter < htmlContent.length) {
        //         console.log(counter);
        //         counter=counter+1;
        //         $('.'+classx).append(htmlContent.charAt(counter));
        //         setTimeout(function(){
        //             showCharacter(classx,htmlContent);
        //         },2000); // 每0.2秒显示一个字符
        //     }
        // }
        
        function typeWriter(match,index,counter,level=".efm_ai-mb6",level2="",level3="",liv=0,liv2=0,status=1,status2=1) {
            console.log(level);
            console.log(index);
            console.log(status);
            console.log(status2);
            if(match.length>index){
                var classx="index_"+index;
                var htmlContent = "";
                
                if(!containsString(match[index],'[\#|\*]')){
                    level=".efm_ai-mb6";
                    $(level).append('<p class="'+classx+'"></p>');
                    htmlContent = match[index].replace(/\n/g, "");
                    index++;
                    status=1;
                    status2=1;
                    console.log(htmlContent);
                    // console.log(classx);
                }else if(containsString(match[index],'\#\#\#')&&status===1){
                    level=".efm_ai-mb6";
                    $(level).append('<h3 class="'+classx+'"></h3>');
                    level="."+classx;
                    htmlContent = match[index].replace(/\#\#\#/g, "").replace(/\*\*.+\*\*/g, "");
                    console.log(htmlContent);
                    status=2;
                    status2=1;
                    // console.log(classx);
                }else if(containsString(match[index],'\#\#\#')&&status===2){
                    classx=classx+"_1";
                    $(level).append('<strong class="'+classx+'"></strong>');
                    level=".efm_ai-mb6";
                    htmlContent = match[index].replace(/[\#\#\#|\*\*|\n]/g, "").replace(/\d\./g, "");
                    index++;
                    status=1;
                    status2=1;
                    console.log(htmlContent);
                    // console.log(classx);
                }else if(containsString(match[index],'\-')&&level===".efm_ai-mb6"&&status2===1){
                    liv++;
                    var ulindex="ul_"+liv;
                    var liindex="li_"+liv+"_"+liv2;
                    var strongindex="strong_"+liv+"_"+liv2;
                    
                    $(level).append('<ul class="'+ulindex+'"><li class="'+liindex+'"><strong class="'+strongindex+'"></strong></li></ul>');
                    classx=strongindex;
                    console.log(classx);
                    level="."+classx;
                    level2="."+liindex;
                    level3="."+ulindex;
                    // htmlContent = match[index].replace(/[-|\*\*|\n]/g, "").replace(/:.+/g, "");
                    var reg = /\*\*(.+?)\*\*/;
                    var htmlContent=match[index].match(reg)[1];
                    // console.log(htmlContent);
                    status2=1;
                    status=1;
                    // console.log(htmlContent);
                    // console.log(classx);
                }else if(containsString(match[index],'\-')&&level!==".efm_ai-mb6"&&status2===1){
                    
                    var ulindex="ul_"+liv;
                    var liindex="li_"+liv+"_"+liv2;
                    var strongindex="strong_"+liv+"_"+liv2;
                    classx=liindex;
                    // console.log(classx);
                    level="."+ulindex;
                    level3="";
                    level2="."+ulindex;
                    htmlContent = match[index].replace(/-/g, "").replace(/\*\*.+\*\*/g, "");
                    
                    // console.log(htmlContent);
                    index++;
                    liv2++;
                    status2=2;
                    status=1;
                    // console.log(classx);
                }else if(containsString(match[index],'\-')&&level!==".efm_ai-mb6"&&status2===2){
                    
                    var ulindex="ul_"+liv;
                    var liindex="li_"+liv+"_"+liv2;
                    var strongindex="strong_"+liv+"_"+liv2;
                    $(level).append('<li class="'+liindex+'"><strong class="'+strongindex+'"></strong></li>');
                    classx=strongindex;
                    // console.log(classx);
                    level="."+classx;
                    level2="."+liindex;
                    level3="."+ulindex;
                    var reg = /\*\*(.+?)\*\*/;
                    var htmlContent=match[index].match(reg)[1];
                    status2=1;
                    status=1;
                    // console.log("zxczxc1");
                    // console.log(htmlContent);
                    // console.log(classx);
                    
                    // console.log(classx);
                }else{
                    $(level).append('<p class="'+classx+'"></p>');
                    level=".efm_ai-mb6";
                    htmlContent = match[index].replace(/\n/g, "");
                    index++;
                    // console.log(htmlContent);
                    // console.log(classx);
                }
                
                
                
                
                
                var intervalId=setInterval(function() {
                    // console.log(counter);
                    // console.log(htmlContent.length);
                    if (counter < htmlContent.length) {
                        $('.'+classx).append(htmlContent.charAt(counter));
                        counter++;
                    }else{
                        clearInterval(intervalId);
                        typeWriter(match,index,0,level,level2,level3,liv,liv2,status,status2);
                    }
                }, 30); // 每100毫秒添加一个字符
            }
            
        }
        
        function containsString(str, search) {
          const regex = new RegExp(search, 'i'); // 'i' 表示不区分大小写
          return regex.test(str);
        }
        function getValueBetweenSymbols(str, startSymbol, endSymbol) {
            const regex = new RegExp(startSymbol + '(.*?)' + endSymbol, 'g');
            const match = str.match(regex);
            console.log(match);
            return match ? match[1] : null;
        }
   
    });    
</script>
 
</body>
</html>

www\wwwroot\Python\Ai\static\css\tongyiqianwen.css

成品项目