书接上回
在我的小程序接入三个免费功能后(没看过的可以看看这篇# 因为我也不想打工,所以跟着做了小程序),我决定整点高级功能,免得小程序没什么亮点。正愁有啥功能不需要后端实现呢。叮~一阵悦耳的手机短信提示声,将我从天马行空的想象之中拉回了现实。星火大模型API公测啦!!!真是瞌睡送枕头,人工智能虽迟但到,命运的羁绊让我再次考虑把人工智能并入我的小程序中。
申请
API是要申请的,走这个链接讯飞星火认知大模型开放能力,进入这个页面后点击“API测试申请”这个按钮,跳转到它的工单填报。
里面的工单信息,建议是如实填写。公司名如果没有可以填写无,APPID需要提前创建,不知道如何使用的可以点击他下面的“创建应用即可获取APPID”。
实名认证后,它的工单审核非常之快。大概两个小时就搞定了(有人更快,还没见过第二天才给过)。
然后就可以在自己的控制台里面看到有两个星火大模型,分别是1.5与2.0版本的,每个版本都送2000000token,一年时间,这点token,流量不大的话明年都用不完。
开发
搞定了API的申请,就可以开始开发了。文档如下# 星火认知大模型Web文档,一开始不知道小程序有demo,我看了很久的python代码想复现,有点异想天开了,建议大家下载他的小程序demo进行查看。
主要流程如下:
确认请求类型
你需要1.5模型就请求v1.5,需要2.0模型就请求v2,文档说的很明白,是个websocket链接。
接口鉴权
可以先看看它提供的鉴权文档
这里我讲一下小程序的修改与使用
星火提供的小程序demo的鉴权函数是这么写的
getWebSocketUrl: function getWebSocketUrl() {
var _this2 = this;
return new Promise(function (resolve, reject) {
// 请求地址根据语种不同变化 https://spark-api.xf-yun.com/v1.1/chat
var url = "wss://spark-api.xf-yun.com/v1.1/chat";
var host = "spark-api.xf-yun.com";
var apiKeyName = "api_key";
var date = new Date().toGMTString();
var algorithm = "hmac-sha256";
var headers = "host date request-line";
var signatureOrigin = "host: ".concat(host, "\ndate: ").concat(date, "\nGET /v1.1/chat HTTP/1.1");
var signatureSha = _cryptoJs.default.HmacSHA256(signatureOrigin, _this2.APISecret);
var signature = _cryptoJs.default.enc.Base64.stringify(signatureSha);
var authorizationOrigin = "".concat(apiKeyName, "=\"").concat(_this2.APIKey, "\", algorithm=\"").concat(algorithm, "\", headers=\"").concat(headers, "\", signature=\"").concat(signature, "\"");
var authorization = base64.encode(authorizationOrigin);
url = "".concat(url, "?authorization=").concat(authorization, "&date=").concat(encodeURI(date), "&host=").concat(host);
// console.log(url)
resolve(url); // 主要是返回地址
});
}
主要难点(也不算难点,百度就行,我这边直接提供结果)就是hmac-sha256获取签名和btoa编码 hmac-sha256算法你需要下载crypto-js,你只需要在小程序项目下打开终端窗口,输入如下代码:
npm install crypto-js
安装完成要记得构建npm:工具–>构建npm,然后引用
const CryptoJS = require('crypto-js');
btoa编码可以用这段代码封装一下
function weBtoa(string) {
var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
string = String(string);
var bitmap, a, b, c, result = "",
i = 0,
rest = string.length % 3;
for (; i < string.length;) {
if ((a = string.charCodeAt(i++)) > 255 ||
(b = string.charCodeAt(i++)) > 255 ||
(c = string.charCodeAt(i++)) > 255)
throw new TypeError("Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.");
bitmap = (a << 16) | (b << 8) | c;
result += b64.charAt(bitmap >> 18 & 63) + b64.charAt(bitmap >> 12 & 63) +
b64.charAt(bitmap >> 6 & 63) + b64.charAt(bitmap & 63);
}
return rest ? result.slice(0, rest - 3) + "===".substring(rest) : result;
};
以上代码是我在微信小程序社区一位大佬提供的回复中找到的,大家可以看一下大佬git
然后完整代码如下:
//鉴权
getWebsocketUrl() {
return new Promise((resolve, reject) => {
const CryptoJS = require('crypto-js');
var url = "wss://spark-api.xf-yun.com/v1.1/chat";
var host = "spark-api.xf-yun.com";
var apiKeyName = "api_key";
var date = new Date().toGMTString();
// var date = 'Fri, 05 May 2023 10:43:39 GMT';
var algorithm = "hmac-sha256";
var headers = "host date request-line";
var signatureOrigin = "host: ".concat(host, "\ndate: ").concat(date, "\nGET /v1.1/chat HTTP/1.1");
var signatureSha = CryptoJS.HmacSHA256(signatureOrigin, '{APISecret}');
var signature = CryptoJS.enc.Base64.stringify(signatureSha);
var authorizationOrigin = "".concat(apiKeyName, "=\"").concat('{APIKey}', "\", algorithm=\"").concat(algorithm, "\", headers=\"").concat(headers, "\", signature=\"").concat(signature, "\"");
var authorization = weBtoa(authorizationOrigin);
url = "".concat(url, "?authorization=").concat(authorization, "&date=").concat(encodeURI(date), "&host=").concat(host);
resolve(url)
})
function weBtoa(string) {
var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
string = String(string);
var bitmap, a, b, c, result = "",
i = 0,
rest = string.length % 3;
for (; i < string.length;) {
if ((a = string.charCodeAt(i++)) > 255 ||
(b = string.charCodeAt(i++)) > 255 ||
(c = string.charCodeAt(i++)) > 255)
throw new TypeError("Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.");
bitmap = (a << 16) | (b << 8) | c;
result += b64.charAt(bitmap >> 18 & 63) + b64.charAt(bitmap >> 12 & 63) +
b64.charAt(bitmap >> 6 & 63) + b64.charAt(bitmap & 63);
}
return rest ? result.slice(0, rest - 3) + "===".substring(rest) : result;
};
},
这个时候返回的url就是最终的websocket链接。代码中的APISecret和APIKey填入自己控制台显示的APISecret和APIKey
接口请求
请求就简单了,websocket一连,直接无敌
代码如下:
connectWebsocket(){
this.getWebsocketUrl().then(res => {
wx.connectSocket({
url: res,
method: "GET",
header: {
'content-type': 'application/json'
},
protocols: ['protocol1'],
success(res) {
console.log('连接成功', res)
},
fail(err) {
console.log(err)
}
});
wx.onSocketOpen(function () {
console.log('WebSocket 已连接')
wx.hideLoading()
})
wx.onSocketMessage(function (res) {
console.log('收到服务器内容:')
console.log(res.data)
})
wx.onSocketError(function (res) {
console.log(res)
})
wx.onSocketClose((res) => {
console.log(res)
})
}).catch(err=>{
})
},
以上是链接websocket,发送可以这么写
var params = {
"header": {
"app_id": "{APPID}"
},
"parameter": {
"chat": {
"domain": "general",
"temperature": 0.5,
"max_tokens": 1024
}
},
"payload": {
"message": {
"text": this.data.chatList
}
}
}
wx.sendSocketMessage({
data: JSON.stringify(params)
})
APPID填写自己的,chatList按照文档的格式填写然后参数详见文档吧,理论上我的操作已经完成了,就可以开始使用大模型了,但是我暂时不清楚为什么我的小程序开发工具不能运行,我都是使用真机测试,真机是可以运行的。离谱的是星火提供的demo可以完全在模拟器上跑起来。大家可以试试,找到问题可以教教我,还有有什么不清楚的也可以在评论中评论。
提醒一下,请求完后websocket就会断掉,需要重新链接,上下文联系可以用chatList填入上次对话内容来实现,文档也是这么讲的。
总结
真的是好用,可能怀疑我是广告,可是他的好处真的很明显,某些方面可能比不上chatgpt,但是他的响应很快,也不会被小程序封掉,我觉得V2差不多有gpt2.99999999的能力甚至某些交互可以达到3.5。星火v2.0好像还支持图片,大家搞一搞,然后教教我。大家也可以去我的小程序体验一波,看一看成品。