使用UnityWebRequest发送OpenAI api请求

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

ChatGPT已经爆火了一段时间了,我想这里结合我的主业Unity来做一个对OpenAI提供的API进行一个HttpRequest,顺便再把我碰到的坑也描述一次来让看到文章的各位不要再踩一次。

一、前期准备

1.注册账号

具体的流程B站可以找到一大堆,主要是要科学上网和虚拟号码,虚拟号这个我用的SMS-Activate的德国号,科学上网这个就各凭本事吧,有了这俩之后注册流程只是走个流程而已。
小TIPS,OpenAI不是全球各地区都开放,先用魔法试试能不能登再去买虚拟号,有些虚拟号是有时间限制的。

2.获取密钥

①注册完成后打开openai.com,点上面的Developers–API reference,
OpenAI首页
②右上角 Log in 登陆你的账号 或者 Sign up注册账号。
在这里插入图片描述
③还是右上角,进用户中心
在这里插入图片描述
④左侧Setting分页可以看自己的ORG_ID,API Keys可以创建自己的密钥用来进行http request
在这里插入图片描述
⑤运行环境,这篇教程需要用到的只有Unity,OpenAI的API reference里面提供了三种不同的请求方法,这里就不多赘述了。

二、代码实现

1.观察结构

在这里插入图片描述
官方提供的curl请求如上图所示,这次教程我们要做的就是在unity中用UnityWebRequest来把上面的结构给构造出来并发送请求即可。
结构很简单,两个请求头,一段json参数,对于请求头我们直接用UnityWebRequest中提供的SetRequestHeader(string)即可,而json参数就更简单了,手动输入正确的格式都能正确请求。
接下来就将它们都实现出来。

2.代码实现

using UnityEngine.Networking;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

public static void SendRequest(string content, Action<AsyncOperation> OnResponse)
{
        JObject sendDataRoot = new JObject();
        JArray messageArray = new JArray();

        JObject message = new JObject();
        message["role"] = "user";
        message["content"] = content;
        messageArray.Add(message);

        sendDataRoot["model"] = "gpt-3.5-turbo";//这里有不同的模型可以选择,可以去api页面去看
        sendDataRoot["messages"] = messageArray;

        var sendData = JsonConvert.SerializeObject(sendDataRoot);

        request = UnityWebRequest.Post("https://api.openai.com/v1/chat/completions", sendData);
        request.SetRequestHeader("Content-Type", "application/json");
        request.SetRequestHeader("Authorization", "Bearer 你的密钥");

        byte[] bodyRaw = Encoding.UTF8.GetBytes(sendData);
        request.uploadHandler = new UploadHandlerRaw(bodyRaw);

        var handle = request.SendWebRequest();
        handle.completed += OnResponse;
    }

上面的代码实现的功能就是将官方提供的Curl用UnityWebRequest发送出去,并接受一个异步操作的回调参数,在请求回来的时候会自动触发。注意这只是一个最基础的版本,每次只会把content参数作为一个独立的请求发送,后面会说强调这个的原因。

其中我进行了替换uploadhandler的操作,如下

	string sendData = "你的Json参数";
	byte[] bodyRaw = Encoding.UTF8.GetBytes(sendData);
    request.uploadHandler = new UploadHandlerRaw(bodyRaw);

做这一步的原因是因为在测试过程中,默认的uploadhandler发出去的数据经常会带一个奇怪的‘%’字符头,我也没深究,只是网上搜索了之后用替换uploadhandler的方式解决了。

三、踩过的坑

1.历史记录

在chat.openai.com用过 ChatGpt的人都知道我们和AI的对话是可以进行上下文联系的,比如你说拼写个ABCD,然后说把上一句的CD去掉,AI会正常回复你个AB。而在API Request方式中最大的槽点就是每次请求他是没有上下文的,按照上面的例子,第二次请求会回复你:“我没上下文功能,你说的上一句是什么?”

对于这个问题,官方暂时没有给解决方案,我们只能自己用别的方式给它一个模拟的上下文,论坛有论几种方式,下面是说的比较多的两种:

  1. 每次问问题和接收答案的时候提炼关键字,并拼接到下一次问答中。
  2. 暴力一点,将问答记录原封不动记录下来,在请求中,message是一个json对象数组,每一个对象都由role和content组成,其中的role有 user和assistant 两种,分别代表用户和AI,我们要做的是在收发的时候将所有信息都记录下来,下一次再给AI发回去。

但这样又引出两个新问题,最大长度和价格。chat api的使用是按Token收费,gpt3.5-turbo模型1000tokens收费为0.002$,大约等于750个英文单词。chat api每次请求的参数长度最大为2Ktokens即2048个token,那么就限制了我们模拟上下文的最大长度,而请求的返回也是限制在2Ktokens,那我们的最大长度更有限了。与此同时因为发送的参数长度增加,也会导致每次消耗占用的tokens增加,本来简单问一句只要几十甚至十几token,加上历史记录,极限一点需要将近两千的Tokens,是原本的百倍。

2.其他模型

对于程序开发来说,我们该代码的需求openai提供了对应的codex模型,具体为code-davinci-edit-001,看名字应该是 davinci 模型下的一个分支,然而在官网的playground中使用的时候,它代码生成的位置比较奇葩,经常生成局部方法,还需要在IDE中手动移动到想要放的位置。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值