AI时代,万物皆可AI,当然,我就说说,我有点跟不上潮流。
业务需要,现在要将讯飞的星火大模型接入微信小程序,下面记录一下我在接入全过程中遇到的坑。
一:首先下载官方示例:
下载地址:
下载完成之后,使用微信开发者工具打开,配置上你自己申请的APPID、APPKEY、APPSECRET之后,即可成功运行项目。
但是有一个小小的问题,这个小程序的示例代码好像不是原生小程序的代码,好像是uniapp开发的小程序,也可能是我孤陋寡闻了,反正,我没这么写过……
倒也无所谓,有示例能借鉴就可以。问题不大,下边是我借鉴代码过程中踩得坑。我这里只使用发文字的功能做测试。
一:鉴权部分代码
1:安装CryptoJS
鉴权部分代码加密需要使用到CryptoJS加密库,我得项目中本来是引用了的,但是在这里不好用,后来我一琢磨,是不是可以使用npm安装一下呢?
npm install crypto-js
安装完成要记得构建npm:工具–>构建npm,详情请移步《小程序(二)使用npm安装weui》
在项目中引用:
const CryptoJS = require('crypto-js');
2:安装base64
鉴权部分代码还需要使用到base64库,上边的CryptoJS库都能使用npm安装,base64库我觉得也可以啊。
npm install base-64
还是一样,安装完成要记得构建npm:工具–>构建npm
在项目中引用:
const base64 = require('base-64');
完整的鉴权部分代码:
/**
* @name: 鉴权
* @author: camellia
*/
getWebSocketUrl()
{
const CryptoJS = require('crypto-js');
const base64 = require('base-64');
var self = this;
var httpUrlHost = self.data.httpUrl.substring(8, 28);
var httpUrlPath = self.data.httpUrl.substring(28);
var url = "wss://" + httpUrlHost + httpUrlPath;
console.log(url)
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 ").concat(httpUrlPath, " HTTP/1.1");
var signatureSha = CryptoJS.HmacSHA256(signatureOrigin, self.data.APISecret);
var signature = CryptoJS.enc.Base64.stringify(signatureSha);
var authorizationOrigin = "".concat(apiKeyName, "="").concat(self.data.APIKey, "", algorithm="").concat(algorithm, "", headers="").concat(headers, "", signature="").concat(signature, """);
// var authorization = self.weBtoa(authorizationOrigin);
var authorization = base64.encode(authorizationOrigin);
url = "".concat(url, "?authorization=").concat(authorization, "&date=").concat(encodeURI(date), "&host=").concat(host);
console.log(url)
return url; // 主要是返回地址
},
后来,我在github的一位大佬的代码仓库里边发现了一个base64函数,刚好也可以完美适配鉴权中的使用。这样你就可以不用配置npm了,多一种选择吧,建议使用npm构建。代码如下:
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;
},
使用base64函数的完整代码如下:
/**
* @name: 鉴权
* @author: camellia
*/
getWebSocketUrl()
{
const CryptoJS = require('crypto-js');
// const base64 = require('base-64');
var self = this;
var httpUrlHost = self.data.httpUrl.substring(8, 28);
var httpUrlPath = self.data.httpUrl.substring(28);
var url = "wss://" + httpUrlHost + httpUrlPath;
console.log(url)
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 ").concat(httpUrlPath, " HTTP/1.1");
var signatureSha = CryptoJS.HmacSHA256(signatureOrigin, self.data.APISecret);
var signature = CryptoJS.enc.Base64.stringify(signatureSha);
var authorizationOrigin = "".concat(apiKeyName, "="").concat(self.data.APIKey, "", algorithm="").concat(algorithm, "", headers="").concat(headers, "", signature="").concat(signature, """);
var authorization = self.weBtoa(authorizationOrigin);
// var authorization = base64.encode(authorizationOrigin);
url = "".concat(url, "?authorization=").concat(authorization, "&date=").concat(encodeURI(date), "&host=").concat(host);
console.log(url)
return url; // 主要是返回地址
},
二:链接webscoket部分的代码
/**
* 创建WebSocket连接
*/
onWorker: function () {
const self = this;
// 发送消息参数
var params = {
"header": {
"app_id": self.data.APPID
},
"parameter": {
"chat": {
"domain": "general",
"temperature": 0.5,
"max_tokens": 1024
}
},
"payload": {
"message": {
"text": self.data.historyTextList
}
}
}
// 根据文档要求 历史对话添加参数
self.data.historyTextList.push({
"role": "user",
"content": self.data.TEXT
});
// 获取webscoket 链接地址
let url = this.getWebSocketUrl();
console.log(url);
// 初始化
wx.connectSocket({
url: url,
success(res) {
console.log('success', res);
utils.vantToast('加载中……', 0, true);
},
fail(res) {
console.log('fail', res)
}
})
// 连接成功
wx.onSocketOpen(function (res) {
console.log("webscoket 链接成功!");
console.log(res);
console.log(params);
wx.sendSocketMessage({
// data: JSON.stringify({ type: 'message', data: '这是一条测试消息' }),
data: JSON.stringify(params)
})
})
// 接收数据
wx.onSocketMessage(function (data) {
console.log(data);
// var objData = JSON.parse(data.data); // 注意这里有时会报错
// console.log(objData);
})
// 连接失败
wx.onSocketError(function () {
console.log('websocket连接失败!');
})
// 断开连接
wx.onSocketClose(function (res) {
console.log('WebSocket 已关闭!')
})
},//*/
具体功能,代码中都有注释。
最后,放一下完整的js代码:
// 公共函数库
const utils = require("../../utils/util.js");
Page({
/**
* 页面的初始数据
*/
data: {
httpUrl: 'https://spark-api.xf-yun.com/v3.5/chat',
TEXT: '你好,我的名字叫大王',
// 地址必须填写,代表着大模型的版本号!!!!!!!!!!!!!!!!
modelDomain: '',
// V1.1-V3.5动态获取,高于以上版本手动指定
APPID: xxxxxx,
// 控制台获取填写
APISecret: xxxxxxxxxxxxxxxxxxxx,
APIKey: xxxxxxxxxxxxxxxxxxxx,
sparkResult: '',
historyTextList: [],
// 历史会话信息,由于最大token12000,可以结合实际使用,进行移出
tempRes: '' // 临时答复保存
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
var self = this;
// self.connectWebsocket();
self.onWorker();
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {},
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;
},
/**
* @name: 鉴权
* @author: camellia
*/
getWebSocketUrl()
{
const CryptoJS = require('crypto-js');
// const base64 = require('base-64');
var self = this;
var httpUrlHost = self.data.httpUrl.substring(8, 28);
var httpUrlPath = self.data.httpUrl.substring(28);
var url = "wss://" + httpUrlHost + httpUrlPath;
console.log(url)
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 ").concat(httpUrlPath, " HTTP/1.1");
var signatureSha = CryptoJS.HmacSHA256(signatureOrigin, self.data.APISecret);
var signature = CryptoJS.enc.Base64.stringify(signatureSha);
var authorizationOrigin = "".concat(apiKeyName, "="").concat(self.data.APIKey, "", algorithm="").concat(algorithm, "", headers="").concat(headers, "", signature="").concat(signature, """);
var authorization = self.weBtoa(authorizationOrigin);
// var authorization = base64.encode(authorizationOrigin);
url = "".concat(url, "?authorization=").concat(authorization, "&date=").concat(encodeURI(date), "&host=").concat(host);
console.log(url)
return url; // 主要是返回地址
},
/**
* 创建WebSocket连接
*/
onWorker: function () {
const self = this;
// 发送消息参数
var params = {
"header": {
"app_id": self.data.APPID
},
"parameter": {
"chat": {
"domain": "general",
"temperature": 0.5,
"max_tokens": 1024
}
},
"payload": {
"message": {
"text": self.data.historyTextList
}
}
}
// 根据文档要求 历史对话添加参数
self.data.historyTextList.push({
"role": "user",
"content": self.data.TEXT
});
// 获取webscoket 链接地址
let url = this.getWebSocketUrl();
console.log(url);
// 初始化
wx.connectSocket({
url: url,
success(res) {
console.log('success', res);
utils.vantToast('加载中……', 0, true);
},
fail(res) {
console.log('fail', res)
}
})
// 连接成功
wx.onSocketOpen(function (res) {
console.log("webscoket 链接成功!");
console.log(res);
console.log(params);
wx.sendSocketMessage({
// data: JSON.stringify({ type: 'message', data: '这是一条测试消息' }),
data: JSON.stringify(params)
})
})
// 接收数据
wx.onSocketMessage(function (data) {
console.log(data);
// var objData = JSON.parse(data.data); // 注意这里有时会报错
// console.log(objData);
})
// 连接失败
wx.onSocketError(function () {
console.log('websocket连接失败!');
})
// 断开连接
wx.onSocketClose(function (res) {
console.log('WebSocket 已关闭!')
})
},//*/
})
以上就是微信小程序纯前端接入星火大模型完整代码
有好的建议,请在下方输入你的评论。