用了个把月的ChatGPT,真觉得挺方便的,查资料什么的都能直接出结果,只是每次要用的时候,还需要登录官网比较麻烦,正好最近提供了3.5版本的接口,就想着能不能直接装到自己的手机上,这样就方便很多了。
于是趁这两天不怎么忙,抽空研究了一下,也踩了几个坑,总算是用上了,下面把相关的步骤分享出来,希望对大家有所帮助。
这里需要几个前置条件:
1、机场。这是必须的,当然能上ChatGPT,这个不是问题。
2、有一定编程基础。不用很熟练,能写Hello就差不多了。
3、有一台群晖nas。之所以选群晖是因为它有全平台的Chat聊天客户端,并且有对外的接口,这样就不需要再写一个客户端,方便省事,当然你也可以接到自己的系统里。
下面开始正文
一、代码部分
因为ChatGPT接口已经不能直接访问了,所以要将ChatGPT的接口通过代理映射成本地的接口,这样做的好处就是只需要设置一次代理,就可以在所有终端直接调用,免去了配置上的麻烦。
1、编写GPT接口调用方法
打开OpenAI官网,找到接口调用示例代码
通过这个示例可以看出,调用接口需要传入两个参数,model以及messages,messages是一个数组,数组内的每组数据需要两个参数 role 和 content,然后在请求头添加 Content-Type: application/json 以及Bearer认证就行。根据这些信息,编写一个接口请求方法,我用的是.NET6,别的语言大同小异。
static async Task<ChatModel> SendRequest(string apiUrl, string apiKey, string inputText) { var requestBody = new { model = apiModel, temperature = apiTemperature, messages = new[] { new { role = 'user', content = inputText } } }; var requestBodyJson = JsonConvert.SerializeObject(requestBody); var requestContent = new StringContent(requestBodyJson, Encoding.UTF8, 'application/json'); //设置代理 var webProxy = new WebProxy { Address = new Uri($'socks5://{proxyAddress}:{proxyPort}') }; var proxyHttpClientHandler = new HttpClientHandler { Proxy = webProxy, UseProxy = true }; HttpClient httpClient; httpClient = new HttpClient(proxyHttpClientHandler); // 发送API请求 httpClient.DefaultRequestHeaders.Add('Authorization', $'Bearer {apiKey}'); var response = await httpClient.PostAsync(apiUrl, requestContent); var responseContent = await response.Content.ReadAsStringAsync(); // 解析API响应并返回输出文本 var responseObject = JsonConvert.DeserializeObject<ChatModel>(responseContent); return responseObject ?? new ChatModel(); }
这里解释一下,如果不对HttpClient设置代理,他就会走直连的形式,而且还不会走本地代理,我就在这上面折腾了好久,调试的时候明明可以用的,但是部署之后就不行了,还以为是代理出了问题,后面才想起需要这样设置。这一步需要特别注意,这是调用GPT接口的关键。
ChatModel实体类,根据GPT接口返回的字段来写就行。这样就拥有了一个可以访问GPT接口的方法,然后再写一个接口来调用这个方法。
因为我是要接到我的群晖Chat上面,所以这个接口需要根据群晖Chat的要求来编写,如果你是要接到自己的系统里面就按自己的需求来写就行。
2、编写Chat机器人调用接口
打开群晖的帮助文档,找到 Synology Chat -> 在Synology Chat中使用整合功能 -> 机器人。
根据文档说明可以知道需要写一个接收的接口跟一个传出方法才能跟他对接上,我也试过只写一个对接传出的接口,发现是不行的,因为机器人的传出不像webhook传出一样能接收响应,所以还要专门写一个方法来将消息发送到群晖Chat。
接收的接口需要接收6 个参数,还是编写一个实体类来接收。
public class MessageModel { public string token { get; set; } public string user_id { get; set; } public string username { get; set; } public string post_id { get; set; } public string timestamp { get; set; } public string text { get; set; } }
有了实体类就可以通过接口来接收群晖Chat传过来的参数,然后调用前面写的访问GPT接口方法,并得到返回数据responseModel,再调用SendToRobot方法将需要的结果发送到Chat上面。
[HttpPost]public async Task Post([FromForm] MessageModel model) { ChatModel responseModel = await SendRequest(apiUrl,apiKey, model.text); await SendToRobot(chatUrl, model.user_id, responseModel.choices[0].message.content); }private async Task SendToRobot (string chatUrl ,string user_id, string msg) { var requestBody = new { text = msg, user_ids = '[]' }; var requestBodyJson = 'payload=' + JsonConvert.SerializeObject(requestBody); requestBodyJson = requestBodyJson.Replace('\'[]\'', '[' + user_id + ']'); var requestContent = new StringContent(requestBodyJson, Encoding.UTF8, 'application/json'); using var httpClient = new HttpClient(); var response = await httpClient.PostAsync(chatUrl, requestContent); var responseContent = await response.Content.ReadAsStringAsync(); }
关于SendToRobot这个方法,看一下官方的文档说明
您可以通过 POST request 中的 payload 参数来分配接收者和消息。例如:
payload={'text': 'First line of message to post in the channel.\nAlso you can have a second line of message.', 'user_ids': [5] }
文档里说了,通过payload参数来分配接收者的消息,所以在发送过去的数据里面要包含user_ids,还有就是text消息内容了,最少要包含这两个字段。
这里有两个坑
第一是payload作为参数,是不能放到json里面进行格式化的,不然会读取不了,只能对payload的值进行json格式化。
第二是参数user_ids的值 [5] 不是字符串形式的,类似于数字值的形式,在最终发送的数据里不能加引号。
由于本人才疏学浅,不知道这个是什么写法,所以在这这两个坑上面也折腾了好长时间。
到这里编程的部分就结束了,接下来就是把程序部署到服务器上。
二、部署部分
为了方便省事,我这里选择把项目直接部署到群晖Docker上,Docker部署也很简单,这里大概说一下操作步骤。
右击项目文件,选择 添加Docker支持 ,目标OS为linux
添加了Docker支持后,直接把整个项目文件上传到群晖的文件夹里面,这里要注意,是上传项目文件,而不是上传发布后的文件。
上传完成后使用终端连接群晖,获取root权限,并定位到刚刚上传的项目文件夹里,运行以下命令:
Docker build -t chatgpt .
稍等一会,看到界面有提示如下成功的字样就可以了,如果遇到中途发布失败,再运行一次命令就好。
关闭终端,进入群晖后台Docker管理界面,找到刚刚发布的chatgpt映像,点击启动,在端口设置那里把本地端口填上,避免重启的时候端口改变。
至此,部署的工作就完成了,然后就是配置Chat的机器人。
原文链接:http://www.360doc.com/content/23/0312/21/1071717391_1071717391.shtml