使用docker部署Python-Flask实现ChatGPT的使用

首先说下背景:

  自从申请ChatGPT到现在也有个把月了,余额一直还很多,想想三月下旬就过期了,还是计划把里面的18美刀用掉,于是结合着之前做的Django简单cv一个"简易网站"。

简单说一下实现原理:

  先写界面,计划半天,由于没有VUE上云的经验,还是用最基础的超文本标记语言吧(主要是简单轻松,哈)HTML+css

  后台用Flask,解释器Python3.9,官网给好的框架可轻松实现一个简易网站的搭建

  部署的时候用docker,写好Dockerfile,直接在容器里面把环境码好了

一、创建环境

1、flask插件
2、Python依赖的模块  openAI, Flask, render_template, request, flash, jsonify

 二、代码部分

2.1、功能代码

# -*- coding:utf-8 -*-
# !/usr/bin/python3
#####################################################################
# Author : zhoujt
# Tel : 186xxxxxxxx
# Date : 2023-02-14
# FileName : openaigpt.py
# Description: web requests
#####################################################################
import json
import time
import openai
import requests
from flask import Flask, render_template, request, flash, jsonify
import re

app = Flask(__name__)
app.secret_key = 'security-guard'


def zhoujt_chatgpt(userinfo):
    # 获取当前时间
    now = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
    result = '[%s]  %s\n' % (now, userinfo)

    headers = {
        'Content-Type': 'application/json'
    }

    # msg_info = result
    msg_info = str(result).replace("\n", "")

    payload = {
        "msgtype": "text",
        "text": {
            "content": msg_info
        }
    }
    zhou = requests.post("https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=4478aey3dea-2c8e-4d6e-acc7-1c1n3n39ty47",
                      data=json.dumps(payload), headers=headers)
# 这里一定要关闭请求,否则请求会逐渐增加 zhou.close() # Answer the last piece of information def answer_meg(question): openai.api_key = "sk-tPYjaksdhf23e3ccJ4uSaT3BlbkFJ2U40tFsz9EzmhfuqeyY87Z" completion = openai.Completion.create( engine="text-davinci-003", prompt=question, max_tokens=1024, temperature=1 ) an_info = completion.choices[0].text return an_info # 路由 @app.route('/', methods=['GET', 'POST']) def index(): if request.method == 'POST': ip_req = request.form.get('requestivr') print(ip_req) try: shell = answer_meg(question=ip_req) print(shell) shell = list(shell) resultsh = "".join(shell) flash(u'Q: %s\t' % ip_req) flash(u'%s\n' % resultsh) zhoujt_chatgpt(userinfo=ip_req) zhoujt_chatgpt(userinfo=resultsh) except Exception as e: flash(u'Q: %s\t\t' % ip_req) flash(u'\t抱歉,ChatGPT负载过高,请稍后重试\t%s' % e) zhoujt_chatgpt(userinfo=e) return render_template('send.html') if __name__ == '__main__': app.run(host='0.0.0.0',port=6666, debug=True)

 2.2、前端页面

<!DOCTYPE html>
<html>
<head>
    <title>ChatGPT</title>
    <link href="https://files.cnblogs.com/files/security-guard/Porsche.ico" rel="shortcut icon">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <link href="../static/style.css" rel="stylesheet" type="text/css" media="all"/>
</head>
<body>
<div class="null"></div>
<div class="null"></div>
<!-- main -->
<form method="post">
    <input class="text" type="text" name="requestivr" placeholder="What would you like to ask ChatGPT?" required="">
    <input type="submit" value="submit">
    <div class="wthree-text">
        <div class="clear"></div>
        <div style="text-align: center;">
            <div class="w3copyright-zhoujt">
                {% for message in get_flashed_messages() %}<br>
                    {{ message }}<br>
                {% endfor %}
            </div>
        </div>
    </div>
</form>

<!-- copyright -->
<div class="w3copyright-agile">
    <p>Please input your requests<a href="" title="#"></a></p>
    <p>This link is for entertainment only and not for commercial use<a href="" title="#"></a></p>
</div>
</div>
</body>
</html>

 2.3、css调试代码

可见有两个 @media 其功能是为了区分手机端和PC端

@media only screen and (max-width: 767px) {
    input[type="text"] {
        outline: none;
        padding: 1em;
        width: 88%;
        margin: 2em 1em auto;
        text-align: center;
        border-radius: 10px;
    }


    input[type="submit"] {
        font-size: 1em;
        color: #fff;
        background: #007bff;
        outline: none;
        border: none;
        cursor: pointer;
        padding: 1em;
        -webkit-appearance: none;
        width: 88%;
        margin: 2em 1em auto;
        border-radius: 10px;
    }

    input[type="submit"]:hover {
        background: #0000FF;
        -webkit-transform: translateY(8px);
        -ms-transform: translateY(8px);
        -o-transform: translateY(8px);
        transform: translateY(8px);
        -webkit-box-shadow: 0 3px 3px 0 rgba(0, 0, 0, 0.58);
        -moz-box-shadow: 0 3px 3px 0 rgba(0, 0, 0, 0.58);
        box-shadow: 0 3px 3px 0 rgba(0, 0, 0, 0.58);
        -webkit-transition: .5s all;
        -moz-transition: .5s all;
        -o-transition: .5s all;
        transition: .5s all;
    }

    .clear {
        clear: both;
    }

    .w3copyright-agile {
        margin: 2em 0 1em;
        text-align: center;
    }

    /*两个最下面提示黑白*/
    .w3copyright-agile p {
        font-size: 1em;
        color: #0f6a18;
        line-height: 1.8em;
        /*background: #007bff;*/
    }

    .w3copyright-agile p a {
        color: #9e3a18;
    }

    .w3copyright-agile p a:hover {
        color: #343a40;
        transition: 0.5s all;
        -webkit-transition: 0.5s all;
        -moz-transition: 0.5s all;
        -o-transition: 0.5s all;
        -ms-transition: 0.5s all;
    }

    .w3copyright-zhoujt {
        outline: none;
        padding: 1em;
        width: 85%;
        margin: 2em 1em auto;
        text-align: center;
        border-radius: 10px;
    }
}

@media only screen and (min-width: 768px) {
    input[type="text"] {
        font-size: 1em;
        margin: 1em 35%;
        padding: 1em;
        width: 28%;
        border-radius: 10px;
    }

    input[type="submit"] {
        font-size: 1em;
        color: #fff;
        background: #007bff;
        outline: none;
        border: none;
        cursor: pointer;
        padding: 1em;
        -webkit-appearance: none;
        width: 30%;
        margin: 2em 35%;
        border-radius: 10px;
    }

    input[type="submit"]:hover {
        background: #0000FF;
        -webkit-transform: translateY(8px);
        -ms-transform: translateY(8px);
        -o-transform: translateY(8px);
        transform: translateY(8px);
        -webkit-box-shadow: 0 3px 3px 0 rgba(0, 0, 0, 0.58);
        -moz-box-shadow: 0 3px 3px 0 rgba(0, 0, 0, 0.58);
        box-shadow: 0 3px 3px 0 rgba(0, 0, 0, 0.58);
        -webkit-transition: .5s all;
        -moz-transition: .5s all;
        -o-transition: .5s all;
        transition: .5s all;
    }

    .clear {
        clear: both;
    }

    .w3copyright-agile {
        margin: 2em 0 1em;
        text-align: center;
    }

    /*两个最下面提示黑白*/
    .w3copyright-agile p {
        font-size: 1em;
        color: #343a40;
        line-height: 1.8em;
    }

    .w3copyright-agile p a {
        color: #343a40;
    }

    .w3copyright-agile p a:hover {
        color: #343a40;
        transition: 0.5s all;
        -webkit-transition: 0.5s all;
        -moz-transition: 0.5s all;
        -o-transition: 0.5s all;
        -ms-transition: 0.5s all;
    }
}

 2.4、打包代码

目录结构
[root@Huawei ~/chatgpt/chatGPT]# tree ./ ./ |-- app.py |-- Dockerfile |-- __pycache__ | `-- prod.cpython-39.pyc |-- requirements.txt |-- static | `-- style.css `-- templates `-- send.html 3 directories, 7 files

 三、部署项目

3.1、传统方式部署

安装虚拟环境  pip3  install virtualenv
创建虚拟环境  virtualenv win_adduser
进入虚拟环境  source /data/csweb/bin/activate
退出虚拟环境  deactivate
[root@windowsop-tx-9208 bin]# source /data/csweb/bin/activate
(csgpt) [root@windowsop-tx-9208 bin]# 
将Python3和pip3安装到此虚拟环境
(csgpt) [root@Huawei ~/chatgpt]# which python3
/data/wds/bin/python3
(csgpt) [root@Huawei ~/chatgpt]# which pip3
/data/wds/bin/pip3
(csgpt) [root@Huawei ~/chatgpt]# 
虚拟环境安装所需的包
pip3 install -r requirement.txt
创建虚拟环境启动的服务
[root@Huawei ~/chatgpt]# cat /etc/systemd/system/csgpt_test.service
[Unit]
Description=csgpt test environment
After=syslog.target network.target

[Service]
User=root
Group=root
Type=simple
Restart=always
WorkingDirectory=/data/csgpt   # 工作目录
ExecStart=/data/csgpt/bin/python3 app.py runserver 0.0.0.0:6666  # 启动命令
ExecStop=/bin/kill -15 $MAINPID  # 安全模式杀进程
StandardOutput=syslog
StandardError=syslog
#SyslogIdentifier=csgpt.com
SyslogFacility=local0
SyslogLevel=info

[Install]
WantedBy=multi-user.target
[root@Huawei ~/chatgpt]# 

 3.2、docker部署

docker部署方便的很,下载docker就成,力荐docker

3.2.1、写好Dockerfile,用于构建编译

[root@Huawei ~/chatgpt/chatGPT]# cat Dockerfile 
FROM python:3.9
WORKDIR /root/chatgpt/chatGPT
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt -i https://pypi.douban.com/simple/
COPY . .
CMD [ "python", "./prod.py" ]
[root@Huawei ~/chatgpt/chatGPT]#

 3.2.2、打包上传运行

# docker构建镜像
docker build -t chatgpt:1.3 .
# 查看镜像
[root@Huawei ~/chatgpt/chatGPT]# docker images 
REPOSITORY                                TAG                 IMAGE ID            CREATED             SIZE
chatgpt                                   1.3                 933455e34545        26 hours ago        932 MB
# 测试环境
docker run -it --rm -p 8888:6666 chatgpt:0.1
# 生产环境
docker run -d -p 8888:6666 --name chatgpt2.3 chatgpt:1.3
    #   -d :使容器在后台运行
    #   -p :端口映射,即访问本机的前者(8888)相当于访问docker容器中的后者(6666)
# 查看容器
[root@Huawei ~/chatgpt/chatGPT]# docker ps
CONTAINER ID        IMAGE               COMMAND              CREATED             STATUS              PORTS                    NAMES
aef043d82ddd        chatgpt:1.3         "python ./prod.py"   26 hours ago        Up 26 hours         0.0.0.0:6201->8888/tcp   chatgpt2.3
# docker查看镜像日志
docker logs -f --since 30m aef043d82ddd
# 删除测试后无用的容器
docker ps -a | grep chatgpt1. | awk -F ' ' '{print $13}' | xargs docker rm
# 停止类似Java的其他服务
docker ps | grep java | awk -F ' ' '{print $NF}' | xargs docker stop
# 进入docker镜像环境
docker run -it chatgpt2.3 /bin/bash
docker exec -it e621d1e639b1 bash # 运行中的容器
# docker查看镜像日志
docker logs -f --since 30m aef043d82ddd

 四、查看效果

 

 

 

 

 除了机器人,整个这个还算是不错的

完活收工~

中间遇到的问题:

1、请求数过多导致的,请求完后要关闭请求,close

requests.exceptions.ConnectionError: HTTPSConnectionPool(host='qyapi.weixin.qq.com', port=443): Max retries exceeded with url: /cgi-bin/webhook/send?key=4d4effea-2c8e-4d6e-acc7-1c1b8d8ecb47 (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x7f1796e65eb0>: Failed to establish a new connection: [Errno -3] Temporary failure in name resolution'))

he debugger caught an exception in your WSGI application. You can now look at the traceback which led to the error.

To switch between the interactive traceback and the plaintext one, you can click on the "Traceback" headline. From the text traceback you can also create a paste of it. For code execution mouse-over the frame you want to debug and click on the console icon on the right side.

You can execute arbitrary Python code in the stack frames and there are some extra helpers available for introspection:

  • dump() shows all variables in the frame
  • dump(obj) dumps all that's known about the object

2、证书问题

移除ssl认证  verify=False

response = requests.get(url, headers=headers,verify=False)
print(response)

# 但是可能会出现 InsecureRequestWarning 警告,
# 虽然不影响代码采集但是看着不舒服,可以加上下面两行:
import urllib3
urllib3.disable_warnings()

 

 

posted @ 2023-02-16 14:12  Security  阅读(1469)  评论(0编辑  收藏  举报
小布的个人空间 京ICP备2023021324号-1