基于OpenAI的Chatbot开发记录

Chatbot 开发记录

最近ChatGPT非常火,去体验之后确实有被惊艳到,也对OpenAI上的人工智能模型比较感兴趣,于是想着复刻一个ChatGPT,利用官方提供的包和api,可以非常简单地复刻出一个ChatGPT,下面是复盘开发过程的记录。

项目地址:https://github.com/Fangnan700/Chatbot

配置项目

  • 我所使用的开发环境是Ubuntu22.04 + Python3.10 + Pycharm2022.3;

  • 项目后端采用Flask框架,前端采用Bootstrap框架,前后端使用json进行交互。

项目结构:

image-20221217222120806

编写代码

前端:

前端需要的框架文件:

  • jquery-3.6.2.min.js
  • bootstrap.min.js
  • bootstrap.min.css

文件可以到官网直接下载。

index.html

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0" maximum-scale="1.0" user-scalable="0">
    <title>Chatbot.</title>
    <script src="{{ url_for('static', filename='js/bootstrap.min.js') }}"></script>
    <script src="{{ url_for('static', filename='js/jquery-3.6.2.min.js') }}"></script>
    <link rel="icon" href="{{ url_for('static', filename='img/robot.png') }}">
    <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/bootstrap.min.css') }}">
    <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/index.css') }}">
</head>
<body>

<div class="container-fluid">
    <div class="row-cols-auto">
        <div class="main">
            <img src="{{ url_for('static', filename='img/logo.png') }}" width="320px" height="100px">
        </div>
    </div>

    <div class="row-cols-auto">
        <div class="col" id="content">
            <div class="col" id="response"></div>
        </div>
    </div>

     <div class="row" id="loading_frame">
        <div class="spinner-border text-light" role="status">
            <span class="visually-hidden">Loading...</span>
        </div>
    </div>

    <div class="row-cols-auto">
        <div class="col textarea" id="input" contenteditable="true" onfocus="clear_input()">

        </div>
    </div>

    <div class="row-cols-auto" id="btn_group">
        <button class="btn btn-secondary" id="clear_btn" onclick="clear_history()" onmo>清 空</button>
        <button class="btn btn-secondary" id="send_btn" onclick="send()">发 送</button>
    </div>

    <div class="row-cols-auto" id="footer_frame">
        Copyright © 2022
        <a class="link-light" href="https://github.com/Fangnan700">Fang nan.</a>
        All rights reserved.
    </div>

</div>

</body>
<script src="{{ url_for('static', filename='js/index.js') }}"></script>
</html>

index.css

body {
    width: 100%;
    height: 100%;
    background: #333333;
}

.main {
    width: 100%;
    height: 100%;
    text-align: center;
}

#content {
    width: 100%;
    height: auto;
    min-height: 480px;
    margin-top: 20px;
    padding-top: 20px;
    padding-bottom: 80px;
    padding-left: 50px;
    padding-right: 50px;
    background: rgba(0,0,0, 1);
    backdrop-filter: blur(10px);
    border-radius: 15px;
}

#response {
    width: 100%;
    height: auto;
    min-height: 380px;
    color: #ffffff;
}

#loading_frame {
    width: 30px;
    height: 30px;
    margin-top: 20px;
    margin-left: auto;
    margin-right: auto;
    text-align: center;
    visibility: hidden;
}

#input {
    width: 100%;
    height: auto;
    min-height: 50px;
    line-height: 50px;
    margin-top: 20px;
    padding-left: 30px;
    padding-right: 10px;
    border-radius: 15px;
    background: black;
    color: #ffffff;
}

#btn_group {
    margin-top: 20px;
    margin-bottom: 30px;
    text-align: right;
}

#clear_btn {
    width: 100px;
    margin-left: auto;
    margin-right: auto;
    border-radius: 10px;
}

#send_btn {
    width: 100px;
    margin-left: 10px;
    margin-right: auto;
    border-radius: 10px;
}


#footer_frame {
    width: 230px;
    height: 30px;
    line-height: 30px;
    margin-top: 20px;
    margin-left: auto;
    margin-right: auto;
    text-align: center;
    color: #ffffff;
}

index.js


// 获取页面元素并创建全局变量
let loading_frame = document.getElementById("loading_frame");
let _input = document.getElementById("input");
let response = document.getElementById("response");
let clear_btn = document.getElementById("clear_btn");
let send_btn = document.getElementById("send_btn");
let history;

// 设置提示语
response.innerText = "hi~我是Chatbot,你可以把你的问题写在下方,然后发送给我,我会尽力为你解答😆"
_input.innerText = "请把你的问题写在这里"

// 发送请求
function send() {
    send_btn.blur();
    loading_frame.style.visibility = "visible";
    let value = _input.innerText;
    history = document.getElementById("response").innerText;
    response.innerText = history + "\n\nQ:\n\n" + value;
    let data = {"content": value};
    $.ajax({
        url: "/send",
        type: "post",
        contentType: 'application/json',
        data: JSON.stringify(data),
        success: function (result) {
            history = document.getElementById("response").innerText;
            response.innerText = history + "\n\nA:" + result;
            loading_frame.style.visibility = "hidden";
        },
        error: function () {
            loading_frame.style.visibility = "hidden";
            response.innerText = "好像出了点问题哦,稍后再试试吧~";
        }
    })
}

// 清除历史内容
function clear_input() {
    _input.innerText = "";
}

function clear_history() {
    clear_btn.blur();
    _input.innerText = "";
    response.innerText = "";
}

后端:

后端使用Python+Flask实现,同时需要引入几个包:

  • openai(OpenAI官方提供的包,可以非常方便地发送请求)
  • dotenv(用于读取环境变量,OpenAI的api-key将在环境变量文件中设置)

以上两个包可以直接用pip进行安装。

在项目根目录创建.flaskenv文件并写入配置:

FLASK_APP=app
FLASK_ENV=development
OPENAI_API_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

其中OPENAI_API_KEY填写的是从OpenAI官网申请到的api-key,申请网址:

https://beta.openai.com/api

app.py

from flask import *
import os
import openai

app = Flask(__name__)
openai.api_key = os.environ.get('OPENAI_API_KEY')


@app.route('/', methods=('GET', 'POST'))
def index():
    return render_template('index.html')


@app.route('/send', methods=('GET', 'POST'))
def send():
    # 解析前端发送的数据
    recv = request.json
    data = recv['content']
    
    # 核心代码,用于向OpenAI的服务器发送请求数据
    response = openai.Completion.create(
        model="text-davinci-003",	# 选择要使用的模型
        prompt=data + '.',			# 请求的数据,即向模型输入的语句,需要以"."结尾
        temperature=0.8,			# 参数,范围0~1,数值越大输出的数据更独特,数值越小输出更准确
        n=1,						# 为每个提示生成多少结果,默认为1
        max_tokens=2048				# 单次输出的最大令牌数,大多数模型支持的最大值为2048
    )
    return response.choices[0].text # 从服务器返回的数据中取出想要的结果


if __name__ == '__main__':
    app.run()

部署项目

这里推荐使用境外的服务器,国内可以通过http请求访问到,将输入的内容发送到服务器,再由服务器转发到OpenAI的服务器上,由此可以在不使用科学上网的情况下,实现与AI机器人的交互。

为了便于在服务器上启动项目,我使用shell脚本来完成项目的启动:

run.sh

#! /bin/bash
./venv/bin/python -m flask run --host 0.0.0.0 --port 80

编写好的脚本放在项目根目录下。

将项目连同虚拟环境一起打包,上传到服务器:

scp Chatbot.zip username@host:/path

上传完成后解压:

unzip Chatbot.zip

进入项目文件下并给脚本赋予权限:

cd Chatbot
chmod +x run.sh

开放80端口:

ufw allow 80

在后台不中断地启动项目:

setsid ./run.sh &

这么启动在ssh连接断开后项目不会停止。

1

至此,通过服务器的公网IP就可以访问到项目了,如果访问不到,就要到服务器的管理面板查看端口是否开放。

2

在不使用vpn的情况下也能正常使用:

3

手机端也能正常使用:

1EE60F238611E931B3ABCE4FCA1A182F

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
很好,我可以为您提供一些指导。 首先,您需要选择一个前端框架,例如React、Vue等。这些框架可以帮助您更轻松地构建动态交互式页面。 接下来,您需要确定您想要实现的功能,例如输入框、按钮、对话框等。您可以使用HTML和CSS来创建这些元素,并使用JavaScript来实现它们的交互。 例如,您可以创建一个输入框,让用户输入文本,并使用按钮触发一个函数来处理用户输入。该函数可以将用户输入发送到后端API,并从API获取响应。响应可以显示在页面上的对话框中,让用户与AI进行交互。 以下是一个简单的示例代码: ```javascript import React, { useState } from 'react'; import axios from 'axios'; function Chatbot() { const [input, setInput] = useState(''); const [response, setResponse] = useState(''); const handleSubmit = async (e) => { e.preventDefault(); const res = await axios.post('/api/chatbot', { input }); setResponse(res.data.response); setInput(''); } return ( <div> <h1>Chatbot</h1> <form onSubmit={handleSubmit}> <input type="text" value={input} onChange={(e) => setInput(e.target.value)} /> <button type="submit">Send</button> </form> {response && <div>{response}</div>} </div> ); } export default Chatbot; ``` 在这个示例中,我们使用React构建了一个简单的聊天机器人页面。当用户提交表单时,我们将其输入发送到后端API,并将响应显示在页面上。当然,这只是一个很简单的例子,您可以根据自己的需求进行修改和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YV_LING

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值