使用go语言、Python脚本搭建一个简单的chatgpt服务网站。
使用go语言、Python脚本搭建一个简单的GPT服务网站
前言
研0在暑假想提升一下自己,自学了go语言编程和机器学习相关学习,但是一味学习理论,终究是枯燥的,于是自己弄点小项目做。
在这之前,建议您需要掌握以下两个技巧,我在这里不赘述了
- 一个openAI账号,并申请了KEY(b站有教程)
- 魔法的method(自己摸索哈~网上应该也有教程嘿嘿~)
现在开始!!!
文章目录
- Python准备
- go服务器与html页面
- 总结与效果展示
一、准备一个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">📝</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

后台服务器输出

后续,我将继续学习,继续完善加强这个小项目,添加更多功能,欢迎关注!!!如果有什么问题,欢迎在评论区发表,一起学习,一起纠错!!!
相关文章:
使用go语言、Python脚本搭建一个简单的chatgpt服务网站。
使用go语言、Python脚本搭建一个简单的GPT服务网站 前言 研0在暑假想提升一下自己,自学了go语言编程和机器学习相关学习,但是一味学习理论,终究是枯燥的,于是自己弄点小项目做。 在这之前,建议您需要掌握以下两个技…...
基于java会议室预约系统设计与实现
摘要 一个企业的发展离不开相关的规定流程。信息化到来的今天在我们的生活当中。离不开各种信息化的支持。比如钉钉会议预约、美团买菜、扫码签到等各种信息化软件。他们涉及我们生活中的方方面面给我们的生活提供了更大的便利性。大到政府、企业办公小到人们的衣食住行都离不开…...
Ubuntu18.04 交叉编译curl-7.61.0
下载 官方网址是:curl 安装依赖库 如果需要curl支持https协议,需要先交叉编译 openssl,编译流程如下: Ubuntu18.04 交叉编译openssl-1.1.1_我是谁??的博客-CSDN博客 解压 # 解压: $tar -xzvf curl-7.61.…...
Android相机-HAL子系统
引言 应用框架要通过拍照预览摄像获得照片或者视频,就需要向相机子系统发出请求, 一个请求对应一组结果 一次可发起多个请求,并且提交请求是非阻塞的,始终按照接收的顺序以队列的形式先进先出地进行顺序处理 一个请求包含了拍摄和拍照配置的所有信息&…...
PostgreSQL-研究学习-介绍与安装
PostgreSQL-预研 是个很厉害的数据库的样子 ψ(*`ー)ψ 官方文档:http://www.postgres.cn/docs/12/ 总的结论和备注 PgSQL 支持对JSON的支持很强大,以及提供了很多数学几何相关的数据类型【例:点,线条,几何…...
【Unity细节】Unity制作汽车时,为什么汽车会被弹飞?为什么汽车会一直抖动?
👨💻个人主页:元宇宙-秩沅 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 本文由 秩沅 原创 😶🌫️收录于专栏:unity细节和bug 😶🌫️优质专栏 ⭐【…...
Android初学之android studio运行java/kotlin程序
第一步骤:File—>New—>New Module,然后弹出一个框,(左边)选择Java or Kotlin Library,(右边)编辑自己的图书馆名、包名、类名,选择Java一个语言,然后F…...
使用自定义 C ++类扩展 TorchScript
使用自定义 C 类扩展 TorchScript 本教程是自定义运算符教程的后续教程,并介绍了我们为将 C 类同时绑定到 TorchScript 和 Python 而构建的 API。 该 API 与 pybind11 非常相似,如果您熟悉该系统,则大多数概念都将转移过来。 在 C 中实现和…...
UITableView自定义TableHeader和TableFooter
UITableView自定义TableHeader和TableFooter 我猜你希望的效果是这样的 我猜你希望的效果是这样的 自定义页眉视图 让我们创建一个文件名 UITableViewHeaderFooterView 的 CustomerHeaderView 子类。 现在让我们创建视图的 Xib 文件并将其命名为 CustomHeaderView。 更改高度标…...
【TA 挖坑03】雾效 | 透光材质 | Impostor | 厚度转球谐
仍旧是记录下半年想要做的东西,很有趣,实现“一团雾效” “面片也有立体感” 等等效果的一些技术上的方法。 仅粗浅记录,保证之后自己填坑的时候看得懂就行! 透光 -> 透光材质ShadingModel 《永劫无间》透光材质的渲染&…...
案例-基于MVC和三层架构实现商品表的增删改查
文章目录 0. 项目介绍1. 环境准备2. 查看所有2.1 编写BrandMapper接口2.2 编写服务类,创建BrandService,用于调用该方法2.5 编写Servlet2.4 编写brand.jsp页面2.5 测试 3.添加3.1 编写BrandMapper接口 添加方法3.2 编写服务3.3 改写Brand.jsp页面&#x…...
Java——一个简单的计算器程序
该代码是一个简单的计算器程序,使用了Java的图形化界面库Swing。具体分析如下: 导入必要的类和包: import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Objects; import javax.…...
自定义滑动到底部触发指令,elementUI实现分页下拉框
在 main.js 中添加 // 自定义滑动到底部指令 Vue.directive(selectLoadMore, {bind(el, binding) {// 获取element-ui定义好的scroll盒子const SELECTWRAP_DOM el.querySelector(.el-select-dropdown .el-select-dropdown__wrap)SELECTWRAP_DOM.addEventListener(scroll, fun…...
【Windows 常用工具系列 10 -- linux ssh登录脚本输入密码】
文章目录 脚本输入SSH登录密码scp 脚本免密传输 脚本输入SSH登录密码 sshpass 是一个用于运行时非交互式ssh密码提供的工具,它允许你直接在命令行中为ssh命令提供密码。这就意味着你可以在脚本中使用ssh命令,而不需要用户交互地输入密码。 一般来说&am…...
C#的索引器
索引器 在 C# 中,索引器(Indexer)是一种特殊的属性,允许通过类的实例像访问数组一样访问对象的元素。索引器允许将类的实例作为集合来使用,可以按照自定义的方式访问类中的元素。 索引器的定义类似于属性,…...
软件配置安装(破解)--- maven下载配置
检查环境是否已有 首先检查一下电脑里有无maven环境,有的话就不用安装了 查看path环境中没有maven,开始准备接下来的重头戏 下载maven 下载bin.zip版 解压mavenxxxbin.zip (建议把解压的文件放在一个文件夹内,命名英文的env…...
python解析小说
前言 在信息爆炸的时代,网络上充斥着大量的小说资源,让人们能够随时随地尽享阅读的乐趣。然而,有些小说网站要求用户付费才能获取完整的内容,这给许多人带来了困扰,尤其是像我这类对金钱概念模糊的人。不过࿰…...
SQL Server 执行报错: “minus“ 附近有语法错误。
sql server 执行带 minus 的语句一直报错,如下图: 找了好久才知道minus是Oracle里面的语法,SQL server 应用 EXCEPT。...
kali linux查看局域网下所有IP,并对指定IP攻击
kali linux查看局域网下所有IP,并对指定IP实施局域网内攻击 首先我们打开我们熟悉的kali linux操作系统,利用指令: ifconfig来确认本机的ip地址 确认了本机的ip地址之后,利用一下的指令查看局域网下所有ip: fping -g 本机IP地址…...
基于QCC_BES 平台的LMS自适应滤波算法实现
+我V hezkz17进数字音频系统研究开发交流答疑群(课题组) LMS算法是最小均方(Least Mean Square)算法的缩写。它是一种自适应滤波算法,常用于信号处理、系统辨识和自适应滤波等领域。 LMS算法的目标是通过对输入信号和期望输出信号之间的误差进行最小化,来调整滤波器的权重…...
【网络】每天掌握一个Linux命令 - iftop
在Linux系统中,iftop是网络管理的得力助手,能实时监控网络流量、连接情况等,帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...
超短脉冲激光自聚焦效应
前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应,这是一种非线性光学现象,主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场,对材料产生非线性响应,可能…...
Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...
招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
Golang——9、反射和文件操作
反射和文件操作 1、反射1.1、reflect.TypeOf()获取任意值的类型对象1.2、reflect.ValueOf()1.3、结构体反射 2、文件操作2.1、os.Open()打开文件2.2、方式一:使用Read()读取文件2.3、方式二:bufio读取文件2.4、方式三:os.ReadFile读取2.5、写…...
Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?
Pod IP 的本质与特性 Pod IP 的定位 纯端点地址:Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址(如 10.244.1.2)无特殊名称:在 Kubernetes 中,它通常被称为 “Pod IP” 或 “容器 IP”生命周期:与 Pod …...
算法打卡第18天
从中序与后序遍历序列构造二叉树 (力扣106题) 给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。 示例 1: 输入:inorder [9,3,15,20,7…...
