使用go语言、Python脚本搭建一个简单的chatgpt服务网站。

使用go语言、Python脚本搭建一个简单的GPT服务网站

前言

研0在暑假想提升一下自己,自学了go语言编程和机器学习相关学习,但是一味学习理论,终究是枯燥的,于是自己弄点小项目做。

在这之前,建议您需要掌握以下两个技巧,我在这里不赘述了

  1. 一个openAI账号,并申请了KEY(b站有教程)
  2. 魔法的method(自己摸索哈~网上应该也有教程嘿嘿~)

现在开始!!!

文章目录

  1. Python准备
  2. go服务器与html页面
  3. 总结与效果展示

一、准备一个Python脚本

第一步:利用pip下载OpenAi依赖包

pip install openai

第二步:将openai的操作封装成一个类,OpenAi.py

import openaiclass OpenAi:def __init__(self, key):"""传入一个key:param key: 你申请的key"""openai.api_key = key # 这里设置keyself.model_name = "gpt-3.5-turbo"  # 使用默认chatgpt3.5模型self.role = "user"  # 使用user的角色,此外还有system等角色,可以自己改着来玩玩def submit(self, question):"""这个方法向gpt发送你想发给gpt的message, 返回一个response对象,是json格式的"""response = openai.ChatCompletion.create(model=self.model_name,  # 使用ChatGPT引擎messages=[{"role": "user", "content": question},],temperature=0,# stream=True  # this time, we set stream=True)return response

第三步:编写Python脚本 testGPT2.py,注意修改自己的key

import os, sys
# 这里我们导入刚才封装的类
import OpenAI as opdef main():# 接受命令行参数args = sys.argv[1:]message = " ".join(args)open_ai_object = op.OpenAi("把你申请的key复制到这里来")response = open_ai_object.submit(message)# 取出gpt的回答gpt_answer = response["choices"][0]["message"]["content"]# 以utf-8的形式输出到命令行,避免中文乱码,后续go语言将会读取print(gpt_answer.encode('utf-8'))if __name__ == '__main__':main()

第四步:测试一下下,启动cmd,cd到testgpt2.py的目录下

python testgpt2.py 你是谁啊?
python testgpt2.py who are you?

在这里插入图片描述
可以发现当询问中文时,脚本会返回中文的utf-8编码,询问英文的时候,会返回英文内容。
运行成功!!!!!!

小结:截至目前,python脚本准备好了,我们接下来使用go搭建一个简单的服务器。

二、搭建一个go服务器和一个html页面,注意修改自己的路径

这里需要准备一个服务器代码和一个html页面,这里直接提供给大家。
初学go!可能有漏洞,欢迎大家指正!

server.go

package mainimport ("bytes""encoding/json""fmt""io""net/http""os""os/exec""strings"
)var count int = 0func main() {// 注册处理函数http.HandleFunc("/data", askForGpt)http.HandleFunc("/", helloHandler)// 启动服务器,监听在指定的端口port := 8080fmt.Printf("Server started at :%d\n", port)err := http.ListenAndServe(fmt.Sprintf(":%d", port), nil)if err != nil {fmt.Println("Error:0", err)}
}const (// 这里大家改成自己html页面的路径即可HTML_PATH = "C:\\Users\\45191\\Desktop\\test8.html"
)// 这个函数调用后会向前端返回一个html页面
func helloHandler(w http.ResponseWriter, r *http.Request) {countUsers()responseHtmlContent := readHtmlFileAll(HTML_PATH)// 向客户端发送响应fmt.Fprint(w, responseHtmlContent)
}// 服务器读取本地html页面
func readHtmlFileAll(path string) string {// 打开文件file, err := os.Open(path)if err != nil {fmt.Printf("Error: %v\n", err)return "ERROR"}defer file.Close()// 读取文件内容content, err := io.ReadAll(file)if err != nil {fmt.Println("Error:", err)return "Error"}return string(content)
}// 简单地统计一下多少个用户访问
func countUsers() {count++fmt.Printf("第%d个用户访问服务器!\n", count)
}// 这个函数负责从前端发来的请求中解析出用户要问gpt的问题,然后执行python脚本,
// 将答案返回
func askForGpt(w http.ResponseWriter, r *http.Request) {countUsers()// 读取 POST 请求的内容body, err := io.ReadAll(r.Body)if err != nil {http.Error(w, "Error reading request body", http.StatusInternalServerError)return}defer r.Body.Close()question := parseJson(body)answer := execPythonScript(question)answerJsonObject := ResponseData{Answer: answer,}data, err := json.Marshal(answerJsonObject)fmt.Fprint(w, string(data))
}// 定义一个接受json数据的内容,用来接受前端发来的json格式数据
type RequestData struct {Content string `json:"content"`
}// 定义一个reponse数据
type ResponseData struct {Answer string `json:"answer"`
}// 解析json格式数据
func parseJson(body []byte) string {var requestData RequestDataerr := json.Unmarshal(body, &requestData)if err != nil {fmt.Printf("Error parseJson: %v", err)}fmt.Printf("requestData: %v\n", requestData)return requestData.Content
}const (// 这里大家改成自己的python脚本路径即可SCRIPT_PATH = "D:\\pyprojects\\MachineLearning\\testGPT2.py"
)// 运行python脚本的函数
func execPythonScript(question string) string {// 定义要运行的Python参数scriptArgs := []string{question}// 创建一个Command对象运行Python脚本cmd := exec.Command("python", append([]string{SCRIPT_PATH}, scriptArgs...)...)fmt.Println(cmd)var stdout, stderr bytes.Buffer// 设置命令的输出和错误输出cmd.Stdout = &stdoutcmd.Stderr = &stderr// 执行命令等待完成err := cmd.Run()if err != nil {fmt.Println("Error running Python script: ", err)return ""}fmt.Println("Python script completed")// 从python脚本的输出中获得答案rawString := strings.TrimSpace(stdout.String())[2:]rawString = rawString[:len(rawString)-1]s := strings.ReplaceAll(rawString, "\\n", "\n")return s
}

test8.html

偷偷告诉大家这个代码大部分是我叫gpt帮我写的,哈哈哈哈,毕竟搞不来前端,我只是改了少量内容,比如js部分代码。

<!DOCTYPE html>
<html>
<head><title>精美左右布局页面</title><style>body {font-family: Arial, sans-serif;margin: 0;padding: 0;background-color: #f5f5f5;}.container {display: flex;justify-content: space-between;align-items: stretch;height: 100vh;background-color: #fff;box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);border-radius: 5px;margin: 20px auto;overflow: hidden;}.left {width: 40%;padding: 20px;padding-right: 30px;background-color: #f8f8f8;}.right {flex: 1;padding: 20px;padding-left: 30px;background-color: #fff;overflow: auto;border-left: 1px solid #ddd;}h1, h2 {margin: 0 0 10px;color: #333;}input[type="text"] {width: 100%;padding: 10px;margin-bottom: 15px;border: 1px solid #ccc;border-radius: 5px;font-size: 16px;box-sizing: border-box;}button {padding: 10px 20px;background-color: #007bff;color: #fff;border: none;border-radius: 5px;cursor: pointer;}pre {white-space: pre-wrap;word-wrap: break-word;}.history-icon {font-size: 20px;cursor: pointer;}</style>
</head>
<body><div class="container"><div class="left"><h2>输入问题:</h2><input type="text" id="question" name="question"><button onclick="getAnswer()">获取答案</button><details><summary><span class="history-icon">&#x1F4DD;</span> 查看历史问题</summary><ul><li>历史问题 1</li><li>历史问题 2</li><li>历史问题 3</li><!-- 在这里添加更多历史问题 --></ul></details></div><div class="right"><h2>答案:</h2><pre id="answer"></pre></div></div><script>function getAnswer() {// 获取输入框内容var questionInput = document.getElementById("question");var answerPre = document.getElementById("answer");// 构造 POST 请求的数据var data = {content: questionInput.value};// 发送 POST 请求fetch("http://localhost:8080/data", {method: "POST",headers: {"Content-Type": "application/json"},body: JSON.stringify(data)}).then(response => response.json()).then(data => {// 将 UTF-8 编码的字节序列转换为 Uint8Arrayvar byteString = data.answervar decodedString = decodeUtf8(byteString)answerPre.textContent = decodedString}).catch(error => {});}// 自己写的utf-8格式转文本函数function decodeUtf8(byteString){var resStr = ""var subStr = ""var count = 0for (var i = 0;i<byteString.length-1;){if (byteString[i] == '\\' && byteString[i+1] == 'x'){subStr += byteString.substr(i+2,2)i = i + 4count ++if (count == 3){resStr += hexToUtf8String(subStr)subStr = ""count = 0}} else {resStr += byteString[i]i ++}   }return resStr}function hexToUtf8String(hex) {const bytes = [];for (let i = 0; i < hex.length; i += 2) {bytes.push(parseInt(hex.substr(i, 2), 16));}return new TextDecoder().decode(new Uint8Array(bytes));}</script>
</body>
</html>

三、总结与效果展示

通过以上步骤,就已经实现了本题目的简单的要求,下面进行效果展示。

前端页面输出,访问127.0.0.1:8080

在这里插入图片描述

后台服务器输出

在这里插入图片描述

后续,我将继续学习,继续完善加强这个小项目,添加更多功能,欢迎关注!!!如果有什么问题,欢迎在评论区发表,一起学习,一起纠错!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/84723.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

QtWidgets和QtQuick融合(QML与C++融合)

先放一个界面效果吧&#xff01; 说明&#xff1a;该演示程序为一个App管理程序&#xff0c;可以将多个App进行吸入管理。 &#xff08;动画中的RedRect为一个带有QSplashScreen的独立应用程序&#xff09; 左侧边栏用的是QQuickView进行.qml文件的加载&#xff08;即QtQuick…

D.OASIS City 和 Warrix 在The Sandbox 庆祝 Rise of the 10th Legend十周年

D.OASIS 首次展示了变革性娱乐 D.OASIS City&#xff0c;正如它与 WARRIX 一起承诺的那样。WARRIX 是获得泰国国家队球衣生产授权的标志性运动服装品牌。 这款激动人心的游戏冒险游戏于今天推出&#xff0c;让用户能够投入 D.OASIS City x WARRIX&#xff1a;Rise of the 10th…

微信小程序的社区老年人 高校大学生体检信息管理系统

社区老年人体检信息管理系统的系统项目的概述设计分析&#xff0c;主要内容有平台的具体分析&#xff0c;进行数据库的是设计&#xff0c;数据采用mysql数据库&#xff0c;并且对于系统的设计采用比较人性化的操作设计&#xff0c;对于系统出现的错误信息可以及时做出处理及反馈…

攻防世界-Web_php_unserialize

原题 解题思路 注释说了flag存在f14g.php中&#xff0c;但是在wakeup函数中&#xff0c;会把传入的文件名变成index.php。看wp知道&#xff0c;如果被反序列话的字符串其中对应的对象的属性个数发生变化时&#xff0c;会导致反序列化失败而同时使得__wakeup 失效&#xff08;CV…

用AI + Milvus Cloud搭建着装搭配推荐系统教程

以下函数定义了如何将图像转换为向量并插入到 Milvus Cloud 向量数据库中。代码会循环遍历所有图像。(注意:如果需要开启 Milvus Cloud 全新特性动态 Schema,需要修改代码。) 查询向量数据库 以下代码演示了如何使用输入图像查询 Milvus Cloud 向量数据库,以检索和上传…

excel文本函数篇2

本期主要介绍LEN、FIND、SEARCH以及后面加B的情况&#xff1a; &#xff08;1&#xff09;后缀没有B&#xff1a;一个字节代表一个中文字符 &#xff08;2&#xff09;后缀有B&#xff1a;两个字节代表一个中文字符 1、LEN(text)&#xff1a;返回文本字符串中的字符个数 2、…

Java8新特性之——Stream API

文章目录 一、简介二、操作分类创建流通过集合通过数组通过Stream的of()方法 中间操作无状态有状态 结束操作非短路操作短路操作 一、简介 JDK 8 引入了 Stream API&#xff0c;它是用于处理集合数据的功能强大的库。Stream API 提供了一种更为简洁、灵活和函数式的方式来进行…

Jupyter Notebook 配置根目录

注&#xff1a;本文是在 Windows 10 上配置 Jupyter Notebook 打开的默认根目录&#xff0c;Linux 同。 步骤一&#xff1a;创建 Jupyter Notebook 配置文件 使用以下命令创建 Jupyter Notebook 配置文件&#xff08;如果尚未创建&#xff09;&#xff1a; jupyter notebook …

​LeetCode解法汇总5-正则表达式匹配​

目录链接&#xff1a; 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目&#xff1a; https://github.com/September26/java-algorithms 原题链接&#xff1a; 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 描述&#xff1a; 给你一棵…

单片机学习-蜂鸣器如何发出声音

硬件电路 软件编写 ①发出声音 #include "reg52.h" typedef unsigned int u16; // 重新定义 类型 typedef unsigned char u8; // 重新定义 类型sbit BEEP P2^5; //定义 P2第五个管教 为BEEP // 延时函数 void delay_time(u16 times) {while(times--); } vo…

【已解决】Docker启动MySQL容器失败:STATUS:‘ Exited (1) 2 minutes ago ‘,远程连接MySQL连不上问题

先查看正在运行的容器 # 查看正在运行的容器 docker ps # 查看所有的docker容器 docker ps -a 这个时候如果显示的是up状态&#xff0c;那就是启动成功了。 状态为exited&#xff0c;所以没有启动成功。 问题所在 好像是权限的问题 在docker run时额外加上参数 --privileged…

优维产品最佳实践第5期:什么是持续集成?

谈到到DevOps&#xff0c;持续交付流水线是绕不开的一个话题&#xff0c;相对于其他实践&#xff0c;通过流水线来实现快速高质量的交付价值是相对能快速见效的&#xff0c;特别对于开发测试人员&#xff0c;能够获得实实在在的收益。 本期EasyOps产品使用最佳实践&#xff0c…