使用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算法的目标是通过对输入信号和期望输出信号之间的误差进行最小化,来调整滤波器的权重…...
大疆飞卡30运载无人机技术分享
大疆飞卡30是大疆公司面向运输领域推出的一款专业运载无人机。它采用了优秀的设计,装备了多种先进传感器,以解决运输中的难题。以下我们来了解一下其主要特点: 【应用领域】 飞卡30适用于山地救灾、农业化肥施用、工程材料运送等交通不便的山区应用,也适用于海岛联通等运输链…...
单片机的串口通信
今天,完整地总结一下普中科技的单片机的串口通信的硬件与编程,记录一下以后如果需要也比较方便捡起来。 单片机的串口部分的电路图。开发板上集成了 1 个串口通信电路,是 USB 转串口模块,它既可下载程序也可实现串口通信功能。 对…...
【C/C++】STL学习所得
文章目录 STL 框架核心组成部分STL 序列容器分类STL 容器适配器分类STL 迭代器分类STL 中一些易混淆知识点一些重要的简述 STL 框架核心组成部分 算法容器迭代器适配器空间配置器访函数 STL 序列容器分类 vectorqueuelistarrayforward_list STL 容器适配器分类 stack 栈qu…...
leetcode几个数组题
数组理论基础 数组是存放在连续内存空间上的相同类型数据的集合 因为数组的在内存空间的地址是连续的,所以我们在删除或者增添元素的时候,就难免要移动其他元素的地址 二分查找 移除元素 有序数组的平方 209.长度最小的子数组...
【LeetCode】模拟实现FILE以及认识缓冲区
模拟实现FILE以及认识缓冲区 刷新缓冲逻辑图自定义实现如何强制刷新内核缓冲区例子 刷新缓冲逻辑图 自定义实现 mystdio.h #pragma once #include <stdio.h>#define NUM 1024 #define BUFF_NOME 0x1 #define BUFF_LINE 0x2 #define BUFF_ALL 0x4typedef struct _MY_FIL…...
【Terraform学习】使用 Terraform 将 EC2 实例作为 Web 服务器启动(Terraform-AWS最佳实战学习)
使用 Terraform 将 EC2 实例作为 Web 服务器启动 实验步骤 前提条件 安装 Terraform: 地址 下载仓库代码模版 本实验代码位于 task_ec2 文件夹中。 变量文件 variables.tf 在上面的代码中,您将声明,aws_access_key,aws_secr…...
WebGL 变量uniform、gl.getUniformLocation、gl.uniform4f及其同族函数相关
目录 uniform变量命名规范 获取 uniform 变量的存储地址 gl.getUniformLocation 向uniform变量赋值 gl.uniform4f 编辑 gl.uniform4f()的同族函数 demo:点击webgl坐标系的四个象限绘制各自不同颜色的点 uniform变量命名规范 var FSHADER_SOURCE uniform vec4…...
【Visual Studio】生成.i文件
环境 VS版本:VS2013 问题 如何生成.i预编译文件? 步骤 1、打开VS项目属性,打开C/C\预处理器页面,【预处理到文件】选择是,开启。 2、生成文件如下。 3、正常编译需要关闭此选项。...
本地生活服务平台加盟哪家公司好?
本地生活的竞争从年初的火热到现在,已经进入了下半场,随着优胜劣汰的筛选,那么直到现在,想做本地生活服务平台加盟,哪家公司比较好呢,应该如何选择呢? 首先我们得弄懂,我们加盟本地…...
css-grid使用
文章目录 grid概念容器和项目网格轨道:网格单元网格线 使用分配item空间大小对于子元素的意义 行列指定隐式和显示网格默认排列 grid容器属性grid-template-rows: 100px 100px 200px;grid-template-columns: 100px 100px 100px;grid-auto-rows: 200pxgrid-column-ga…...
网站模板下载模板下载安装/什么是网络营销渠道
在myeclipse中deploy:选择了一个工程,添加一个新的deploy工程时,不能正常出现deploy Location,可能的原因是没有在mymatadata中添加context-root"/",另外webrootdir属性也要设置正确。一个常见的配置如下&am…...
网站中文域名好不好/seo石家庄
1. 需求 目前我们开发的TCP服务端程序只能服务于一个客户端,如何开发一个多任务版的TCP服务端程序能够服务于多个客户端呢? 完成多任务,可以使用线程,比进程更加节省内存资源。 2. 具体实现步骤 编写一个TCP服务端程序,循环等…...
郑州网站建设时一定需要注意的六点/网站出售
涉及到链表的面试题: 如果有链表编号的参数,先明确链表的编号是从0开始还是从1开始如果输入有编号、个数这样的参数时,使用unsigned int ,这样最多只需要判断其不等于0即可两个指针可以做很多事,例如先把他们间隔固定,最后一个到结尾时,第一个指针就指向倒数第n个结点了…...
wordpress 不显示ip/什么是sem推广
现在这个年代,你要是不懂高并发,你都不好意思说自己是搞互联网的! 一、什么是并发,什么是高并发 并发,两个及以上的行为一起发生,比如你一边吃饭一边看电视 高并发,多个行为(至于是多少&…...
南京专业网站设计公司价格/宣传推广策略
循环是为了执行重复的动作forwhileuntil1、for循环语法:for 变量 in 变量列表do循环体;done# cat for1.sh #!/bin/bashfor i in seq 5doecho $idonein后面接列表 for i in 1 2 3 4 5 seq 10for i in {1..10}插曲 ---------------------------------------seq 10 …...
wordpress flash加载插件/百度刷自己网站的关键词
最近跟我的一些读者交流,有一位读者的经历让我记忆深刻:“有一次和大学同学聚会,和几个在BAT的同学聊了聊技术,发现自己在创业公司这几年,完全是吃老本的状态,没有什么机会精进技术,同样是工作了…...