目录
- 功能描述
- 准备工作
- 百度智能云账号
- 创建应用
- 编辑应用
- 创建Api秘钥
- Api调用流程
- unity代码
- Unitywebrequest
- 非流式
- 流式
- 注意事项
- Restsharp
功能描述
使用百度千帆AppBuilder平台,通过api调用的方式实现AI大模型对话功能(文字)
准备工作
百度智能云账号
请自行在百度智能云进行创建
百度智能云官网
tips
记得开通大模型的服务(需付费)
创建应用
进入AppBuilder点击创建应用
编辑应用
设置你需要的应用信息,如果有知识库的话需要设置对应的知识库(一个应用目前只能对应一个知识库)
- 设置名字和头像-这个只在网页访问的时候会显示
- 设置角色设定,可以先输入一些关键词,点击优化让ai帮你优化
- 选择知识库
一个应用只能对应一个知识库(20240430)
- 还可以设置你需要的内容
- 右上角设置基模(目前
ERNIE-4.0-8K
比较贵,ERNIE-3.5-8K相对便宜效果也不错,根据实际需求选择即可) - 右下角输入内容预览效果
- 以上内容确定后点击右上角的发布即可
创建Api秘钥
点击右上方的个人中心图标
点击Api秘钥
新增秘钥,点击复制按钮一键复制秘钥
Api调用流程
官方文档
调用流程如下:
- 获取创建的应用的
appid
- 获取
api秘钥
- 先调用新建会话的api,获取
conversation_id
- 根据
conversation_id
调用大模型对话接口正式发起会话
unity代码
Unitywebrequest
非流式
使用非流式的调用方式的话就跟平常的api调用没差,这里就不多做说明了
流式
const string API_KEY = "api秘钥";const string _baseUrl = "https://qianfan.baidubce.com/v2/app/conversation";const string _startConversRoute = "/runs";const string _appId = "appid";RequestBody _reqBody;//实例化的请求体string _temResultTotal = "";string _temAsk = "";private StreamReader streamReader;private MemoryStream responseStream;private string _temConversationID;//临时对话idconst string TAG = "YiyanAppBuilderApiCtr";
///调用接口
///
IEnumerator YiyanAppBuilderStreamIE(string prompt){this._temAsk = prompt;yield return GetConversationID();//调用新建会话接口获取conversationidbyte[] bodyRaw = Data2byte(prompt);//将请求的内容封装在请求体中最后一并转化为字节数据using (UnityWebRequest request = UnityWebRequest.Post($"{_baseUrl}{_startConversRoute}", "")){request.SetRequestHeader("Accept", "application/octet-stream");//改行可加可不加request.SetRequestHeader("Authorization", $"Bearer {API_KEY}");request.SetRequestHeader("Content-Type", "application/json");request.uploadHandler = new UploadHandlerRaw(bodyRaw);//将请求的数据添加如请求中request.SendWebRequest();//发起调用byte[] results = new byte[1024];//try//{ tips 如果追求流式效果,此处不能使用trycatch包裹业务代码,否则实现的效果和非流式一样while (!request.isDone){yield return new WaitForSeconds(0.5f);//添加yield return (填null或者0)都行results = request.downloadHandler.data;this.HandleStreamData(results);//对接受的数据进行处理}if (request.isDone && results != null){//业务逻辑}//}//catch (Exception ex)//{//}}yield return null;}private void HandleStreamData(byte[] results){string line = "";if (results != null){responseStream = new MemoryStream(results);streamReader = new StreamReader(responseStream);while ((line = streamReader.ReadLine()) != null){string _temResult = "";if (line.Length < 6) continue;try{//将字节流数据的头信息(data: )去掉,然后通过json转换得到我们想要的数据if (JObject.Parse(line.Substring(5))["answer"].ToString() == "") continue;Debug.Log(line.Substring(5));_temResult = JObject.Parse(line.Substring(5))["answer"].ToString();}catch (Exception ex){//说明json转换失败,跳过Debug.Log("yiyan transform byte2json fail>>>>" + ex.Message + line.Substring(5));continue;}if (!_temStreamCBList.ContainsKey(_temResult)){//对数据进行过滤,将出现的特殊符号去掉_temResult = _temResult.Replace("\n", "").Replace(" ", "").Replace("\t", "").Replace("\r", "");_temResult = FilterStr(_temResult);if (_temResult == null || _temResult == "") continue;Debug.Log(_temResult);//将流数据转换加入队列,调用循环进行播放和处理this._temResultTotal += _temResult;try{_temStreamCBList.Add(_temResult, _temResult);}catch (Exception ex){Log.Info($"{TAG}>>>ArgumentException: An item with the same key has already been added. Key");continue;}if (_temStreamCBList.Count == 1){//业务逻辑}}}}}/*** 根据apikey和appid获取conversation_id用于开启对话*/IEnumerator GetConversationID(){Dictionary<string, string> form = new Dictionary<string, string>();form.Add("app_id", _reqBody.app_id);string _jsonBody = JsonConvert.SerializeObject(form);byte[] bytes = Encoding.UTF8.GetBytes(_jsonBody);using (UnityWebRequest request = UnityWebRequest.Post(_baseUrl, "")){request.SetRequestHeader("Content-Type", "application/json");request.SetRequestHeader("Authorization", $"Bearer {API_KEY}");request.uploadHandler = new UploadHandlerRaw(bytes);yield return request.SendWebRequest();ResponseBody response = JsonUtility.FromJson<ResponseBody>(request.downloadHandler.text);_temConversationID = response.conversation_id;Debug.Log(_temConversationID);}}private byte[] Data2byte(string prompt){_reqBody.query = prompt;_reqBody.conversation_id = _temConversationID;string body = JsonConvert.SerializeObject(_reqBody);byte[] bodyRaw = Encoding.UTF8.GetBytes(body);return bodyRaw;}public string FilterStr(string str){string pattern = @"\*|\^|\[(\d+)\]"; // 匹配 *、^、[ 和 ] 字符 以及[]里的数字//Regex reg = new Regex("\\s+");string _regResult = Regex.Replace(str, pattern, "");//Debug.Log(_regResult);return _regResult;}#region 请求yiyan-api需要的请求体[Serializable]
class RequestBody
{public string app_id;public string query;public bool stream;public string conversation_id;
}
[Serializable]
class ResponseBody
{public string request_id;public string conversation_id;
}
#endregion
注意事项
截止至20240430也就是今天为止
官方请求后返回的数据中会在最后有关于知识库的下标的数据,如下图
官方的回复是
因此在实际进行调用的时候还需要对最后的数据进行过滤
通过以上流程即可调用成功
Restsharp
该插件可以更便捷的实现调用,不过该插件存在多线程(UI更新不及时)的问题,因此不做该插件实现调用api的内容