提交 e1ed915c 编写于 作者: DCloud_JSON's avatar DCloud_JSON

1.0.5添加注释

上级 aa6c0d3d
## 1.0.5(2023-05-11)
- 新增代码注释
## 1.0.4(2023-05-10) ## 1.0.4(2023-05-10)
- 修复 uni-ai默认服务商,检测到内容涉及违规后 内容会返回一部分或卡住的问题(HBuilderX3.8.2起或连接云端云函数支持) - 修复 uni-ai默认服务商,检测到内容涉及违规后 内容会返回一部分或卡住的问题(HBuilderX3.8.2起或连接云端云函数支持)
- 修复 web-pc端当回车键敲得较快时 发送的内容不正确的问题 - 修复 web-pc端当回车键敲得较快时 发送的内容不正确的问题
......
...@@ -16,18 +16,19 @@ ...@@ -16,18 +16,19 @@
return {} return {}
}, },
props: { props: {
// 广告位唯一标识
adpid: { adpid: {
type: String, type: String,
default(){ default(){
return '1053355918' return ''
} }
}, },
}, },
computed: { computed: {
// 回调URL // 回调URL
urlCallback() { urlCallback() {
// 拿到当前用户的id值
let uid = uniCloud.getCurrentUserInfo().uid let uid = uniCloud.getCurrentUserInfo().uid
return { return {
userId: uid, userId: uid,
extra: JSON.stringify({ extra: JSON.stringify({
...@@ -85,7 +86,7 @@ ...@@ -85,7 +86,7 @@
}, },
onAdClose(e) { onAdClose(e) {
console.log('onAdClose', e) console.log('onAdClose', e)
this.$emit('onAdClose',e) this.$emit('onAdClose',e) // 触发onAdClose事件
}, },
onAdError(e) { onAdError(e) {
console.log('onAdError', e) console.log('onAdError', e)
......
...@@ -12,18 +12,23 @@ ...@@ -12,18 +12,23 @@
</template> </template>
<script> <script>
// 引入markdown-it库
import MarkdownIt from '@/lib/markdown-it.min.js'; import MarkdownIt from '@/lib/markdown-it.min.js';
// hljs是由 Highlight.js 经兼容性修改后的文件,请勿直接升级。否则会造成uni-app-vue3-Android下有兼容问题 // hljs是由 Highlight.js 经兼容性修改后的文件,请勿直接升级。否则会造成uni-app-vue3-Android下有兼容问题
import hljs from "@/lib/highlight/highlight-uni.min.js"; import hljs from "@/lib/highlight/highlight-uni.min.js";
// 引入html-parser.js库
import parseHtml from '@/lib/html-parser.js'; import parseHtml from '@/lib/html-parser.js';
// console.log('hljs--',hljs); // console.log('hljs--',hljs);
// console.log('hljs--',hljs.getLanguage('js')); // console.log('hljs--',hljs.getLanguage('js'));
// 初始化 MarkdownIt库
const markdownIt = MarkdownIt({ const markdownIt = MarkdownIt({
// 在源码中启用 HTML 标签
html: true, html: true,
// 如果结果以 <pre ... 开头内部包装器则会跳过
highlight: function(str, lang) { highlight: function(str, lang) {
// if (lang && hljs.getLanguage(lang)) { // if (lang && hljs.getLanguage(lang)) {
// console.error('lang', lang) // console.error('lang', lang)
...@@ -49,7 +54,9 @@ ...@@ -49,7 +54,9 @@
name: "msg", name: "msg",
data() { data() {
return { return {
// 悬浮的复制按钮的左边距
left: "-100px", left: "-100px",
// 悬浮的复制按钮的上边距
top: "-100px" top: "-100px"
}; };
}, },
...@@ -58,32 +65,37 @@ ...@@ -58,32 +65,37 @@
// web端限制不选中文字时出现系统右键菜单 // web端限制不选中文字时出现系统右键菜单
let richTextBox = this.$refs['rich-text-box'] let richTextBox = this.$refs['rich-text-box']
if (richTextBox) { if (richTextBox) {
// 监听鼠标右键事件
richTextBox.$el.addEventListener('contextmenu', (e) => { richTextBox.$el.addEventListener('contextmenu', (e) => {
// 判断是否选中了文字内容,如果没有则限制系统默认行为(禁止弹出右键菜单)
if (!document.getSelection().toString()) { if (!document.getSelection().toString()) {
// console.log(e); // console.log(e);
// 设置悬浮的复制按钮的坐标值
this.top = e.y + 'px' this.top = e.y + 'px'
this.left = e.x + 'px' this.left = e.x + 'px'
// console.log(e.x); // console.log(e.x);
// console.log(e.y); // console.log(e.y);
// 禁止系统默认行为(禁止弹出右键菜单)
e.preventDefault() e.preventDefault()
} }
}) })
} }
// 监听全局点击事件,隐藏悬浮的复制按钮的坐标
document.addEventListener('click', () => { document.addEventListener('click', () => {
this.left = "-100px" this.left = "-100px"
}) })
// #endif // #endif
}, },
props: { props: {
// 传入的markdown内容
md: { md: {
type: String, type: String,
default () { default () {
return '' return ''
} }
}, },
// 是否显示鼠标闪烁的效果
showCursor: { showCursor: {
type: [Boolean, Number], type: [Boolean, Number],
default () { default () {
...@@ -92,7 +104,9 @@ ...@@ -92,7 +104,9 @@
} }
}, },
computed: { computed: {
// 修改转换结果的html值 用于正确给界面增加鼠标闪烁的效果
html() { html() {
// 判断markdown中代码块标识符的数量是否为偶数
if(this.md.split("```").length%2){ if(this.md.split("```").length%2){
return markdownIt.render(this.md + ' \n <span class="cursor">|</span>'); return markdownIt.render(this.md + ' \n <span class="cursor">|</span>');
}else{ }else{
...@@ -102,16 +116,19 @@ ...@@ -102,16 +116,19 @@
nodes() { nodes() {
// return this.html // return this.html
// console.log('parseHtml(this.html)',parseHtml(this.html)); // console.log('parseHtml(this.html)',parseHtml(this.html));
// HTML String 类型转换 避免内部转换导致的性能下降。
return parseHtml(this.html) return parseHtml(this.html)
} }
}, },
methods: { methods: {
// #ifdef H5 // #ifdef H5
// 复制文本内容到系统剪切板
copy() { copy() {
uni.setClipboardData({ uni.setClipboardData({
data: this.md, data: this.md,
showToast: false, showToast: false,
}) })
// 设置悬浮的复制按钮的坐标值,使其隐藏
this.left = "-100px" this.left = "-100px"
} }
// #endif // #endif
......
{ {
"id": "uni-ai-chat", "id": "uni-ai-chat",
"name": "uni-ai-chat", "name": "uni-ai-chat",
"version": "1.0.3", "version": "1.0.5",
"description": "基于uni-ai的聊天示例项目,支持流式、支持前文总结,云端一体", "description": "基于uni-ai的聊天示例项目,支持流式、支持前文总结,云端一体",
"main": "main.js", "main": "main.js",
"scripts": { "scripts": {
......
此差异已折叠。
// 云对象教程: https://uniapp.dcloud.net.cn/uniCloud/cloud-obj // 云对象教程: https://uniapp.dcloud.net.cn/uniCloud/cloud-obj
// jsdoc语法提示教程:https://ask.dcloud.net.cn/docs/#//ask.dcloud.net.cn/article/129 // jsdoc语法提示教程:https://ask.dcloud.net.cn/docs/#//ask.dcloud.net.cn/article/129
// 引入utils模块中的safeRequire和checkContentSecurityEnable函数
const {safeRequire, checkContentSecurityEnable} = require('./utils') const {safeRequire, checkContentSecurityEnable} = require('./utils')
// 引入uni-config-center模块,并创建config对象
const createConfig = safeRequire('uni-config-center') const createConfig = safeRequire('uni-config-center')
const config = createConfig({ const config = createConfig({
pluginId: 'uni-ai-chat' pluginId: 'uni-ai-chat'
}).config() }).config()
// 引入uniCloud.database()方法,并创建db对象
const db = uniCloud.database(); const db = uniCloud.database();
// 创建userscollection对象
const userscollection = db.collection('uni-id-users') const userscollection = db.collection('uni-id-users')
// 引入uni-id-common模块
const uniIdCommon = require('uni-id-common') const uniIdCommon = require('uni-id-common')
module.exports = { module.exports = {
_before:async function() { _before:async function() {
// 这里是云函数的前置方法,你可以在这里加入你需要逻辑,比如: // 这里是云函数的前置方法,你可以在这里加入你需要逻辑
/*
例如:使用uni-id-pages(链接地址:https://ext.dcloud.net.cn/plugin?id=8577)搭建账户体系。
然后再使用uni-id-common的uniIdCommon.checkToken判断用户端身份,验证不通过你可以直接`throw new Error(“token无效”)`抛出异常拦截访问。
如果验证通过了可以获得用户id,可以记录每一个用户id的调用次数来限制,调用多少次后必须充值(推荐用uni-pay,下载地址:https://ext.dcloud.net.cn/plugin?id=1835)
或者看一个激励视频广告(详情:https://uniapp.dcloud.net.cn/uni-ad/ad-rewarded-video.html)后才能继续使用
*** 激励视频是造富神器。行业经常出现几个人的团队,月收入百万的奇迹。 ***
*/
// 判断否调用量本云对象的send方法
if(this.getMethodName() == 'send'){ if(this.getMethodName() == 'send'){
// 从配置中心获取是否需要销毁积分 // 从配置中心获取是否需要销毁积分
if(config.spentScore){ if(config.spentScore){
...@@ -33,6 +33,7 @@ module.exports = { ...@@ -33,6 +33,7 @@ module.exports = {
this.uniIdCommon = uniIdCommon.createInstance({ this.uniIdCommon = uniIdCommon.createInstance({
clientInfo: this.clientInfo clientInfo: this.clientInfo
}) })
// 校验token(用户身份令牌)是否有效,并获得用户的_id
let res = await this.uniIdCommon.checkToken(this.clientInfo.uniIdToken) let res = await this.uniIdCommon.checkToken(this.clientInfo.uniIdToken)
if (res.errCode) { if (res.errCode) {
// 如果token校验出错,则抛出错误 // 如果token校验出错,则抛出错误
...@@ -44,9 +45,12 @@ module.exports = { ...@@ -44,9 +45,12 @@ module.exports = {
/* 判断剩余多少积分:拒绝对话、扣除配置的积分数 */ /* 判断剩余多少积分:拒绝对话、扣除配置的积分数 */
let {data:[{score}]} = await userscollection.doc(this.current_uid).field({'score':1}).get() let {data:[{score}]} = await userscollection.doc(this.current_uid).field({'score':1}).get()
console.log('score----',score); console.log('score----',score);
if(score == 0 || score < 0){ //并发的情况下可能花超过 // 如果积分数小于等于0 则抛出错误提醒客户端
// 注意需要判断小于0 因为特殊的情况下可能花超过
if(score == 0 || score < 0){
throw "insufficientScore" throw "insufficientScore"
} }
// 扣除对应的积分值
await userscollection.doc(this.current_uid) await userscollection.doc(this.current_uid)
.update({ .update({
score:db.command.inc(-1 * config.spentScore) score:db.command.inc(-1 * config.spentScore)
...@@ -56,13 +60,18 @@ module.exports = { ...@@ -56,13 +60,18 @@ module.exports = {
// 从配置中心获取内容安全配置 // 从配置中心获取内容安全配置
console.log('config.contentSecurity',config.contentSecurity); console.log('config.contentSecurity',config.contentSecurity);
if (config.contentSecurity) { if (config.contentSecurity) {
// 引入uni-sec-check模块
const UniSecCheck = safeRequire('uni-sec-check') const UniSecCheck = safeRequire('uni-sec-check')
// 创建uniSecCheck对象
const uniSecCheck = new UniSecCheck({ const uniSecCheck = new UniSecCheck({
provider: 'mp-weixin', provider: 'mp-weixin',
requestId: this.getUniCloudRequestId() requestId: this.getUniCloudRequestId()
}) })
// 定义文本安全检测函数
this.textSecCheck = async (content)=>{ this.textSecCheck = async (content)=>{
// 获取sseChannel
let {sseChannel} = this.getParams()[0]||{} let {sseChannel} = this.getParams()[0]||{}
// 如果存在sseChannel,则抛出错误
if(sseChannel){ if(sseChannel){
throw { throw {
errSubject: 'uni-ai-chat', errSubject: 'uni-ai-chat',
...@@ -72,12 +81,17 @@ module.exports = { ...@@ -72,12 +81,17 @@ module.exports = {
} }
// 检测文本 // 检测文本
const checkRes = await uniSecCheck.textSecCheck({ const checkRes = await uniSecCheck.textSecCheck({
// 文本内容,不可超过500KB
content, content,
// 微信小程序端 开放的唯一用户标识符
// openid, // openid,
// 场景值(1 资料;2 评论;3 论坛;4 社交日志)
scene:4, scene:4,
version:1 //后续:支持微信登录后,微信小程序端 改用模式2 详情:https://uniapp.dcloud.net.cn/uniCloud/uni-sec-check.html#%E4%BD%BF%E7%94%A8%E5%89%8D%E5%BF%85%E7%9C%8B // 接口版本号,可选1或2,但1的检测能力很弱 支持微信登录的项目,微信小程序端 可改用模式2 详情:https://uniapp.dcloud.net.cn/uniCloud/uni-sec-check.html#%E4%BD%BF%E7%94%A8%E5%89%8D%E5%BF%85%E7%9C%8B
version:1
}) })
console.log('checkRes检测文本',checkRes); console.log('checkRes检测文本',checkRes);
// 如果检测到风险内容,则抛出错误
if (checkRes.errCode === uniSecCheck.ErrorCode.RISK_CONTENT) { if (checkRes.errCode === uniSecCheck.ErrorCode.RISK_CONTENT) {
console.error({ console.error({
errCode: checkRes.errCode, errCode: checkRes.errCode,
...@@ -85,6 +99,7 @@ module.exports = { ...@@ -85,6 +99,7 @@ module.exports = {
result: checkRes.result result: checkRes.result
}); });
throw "uni-sec-check:illegalData" throw "uni-sec-check:illegalData"
// 如果检测出错,则抛出错误
} else if (checkRes.errCode) { } else if (checkRes.errCode) {
console.log(`其他原因导致此文件未完成自动审核(错误码:${checkRes.errCode},错误信息:${checkRes.errMsg}),需要人工审核`); console.log(`其他原因导致此文件未完成自动审核(错误码:${checkRes.errCode},错误信息:${checkRes.errMsg}),需要人工审核`);
console.error({ console.error({
...@@ -96,17 +111,25 @@ module.exports = { ...@@ -96,17 +111,25 @@ module.exports = {
} }
} }
// 获取messages参数
let {messages} = this.getParams()[0]||{"messages":[]} let {messages} = this.getParams()[0]||{"messages":[]}
// 将messages中的content拼接成字符串
let contentString = messages.map(i=>i.content).join(' ') let contentString = messages.map(i=>i.content).join(' ')
console.log('contentString',contentString); console.log('contentString',contentString);
// 对contentString进行文本安全检测
await this.textSecCheck(contentString) await this.textSecCheck(contentString)
} }
} }
}, },
async _after(error, result) { async _after(error, result) {
// 打印错误和结果
console.log('_after',{error,result}); console.log('_after',{error,result});
// 如果有错误
if(error){ if(error){
// 如果是内容安全检测错误
if(error.errCode == "60004" || error == "uni-sec-check:illegalData" ) { if(error.errCode == "60004" || error == "uni-sec-check:illegalData" ) {
// 返回一个包含敏感内容提示和标记的响应体
return { return {
"data": { "data": {
"reply": "内容涉及敏感", "reply": "内容涉及敏感",
...@@ -115,20 +138,29 @@ module.exports = { ...@@ -115,20 +138,29 @@ module.exports = {
"errCode": 0 "errCode": 0
} }
}else if(error.errCode && error.errMsg) { }else if(error.errCode && error.errMsg) {
// 如果是符合响应体规范的错误
// 符合响应体规范的错误,直接返回 // 符合响应体规范的错误,直接返回
return error return error
} }
// 如果是积分不足错误
else if(error == 'insufficientScore'){ else if(error == 'insufficientScore'){
// 设置回复内容
let reply = "积分不足,请看完激励视频广告后再试" let reply = "积分不足,请看完激励视频广告后再试"
// 获取sseChannel
let {sseChannel} = this.getParams()[0]||{} let {sseChannel} = this.getParams()[0]||{}
// 如果存在sseChannel
if(sseChannel){ if(sseChannel){
// 反序列化sseChannel
const channel = uniCloud.deserializeSSEChannel(sseChannel) const channel = uniCloud.deserializeSSEChannel(sseChannel)
// 向sseChannel写入回复内容
await channel.write(reply) await channel.write(reply)
// 结束sseChannel
await channel.end({ await channel.end({
"insufficientScore":true "insufficientScore":true
}) })
}else{ }else{
// 如果不存在sseChannel 返回一个包含回复内容和标记的响应体
return { return {
"data": { "data": {
reply, reply,
...@@ -138,14 +170,18 @@ module.exports = { ...@@ -138,14 +170,18 @@ module.exports = {
} }
} }
}else{ }else{
// 如果是其他错误
throw error // 直接抛出异常 throw error // 直接抛出异常
} }
} }
// 如果是send方法且开启了内容安全检测
if (this.getMethodName() == 'send' && config.contentSecurity) { if (this.getMethodName() == 'send' && config.contentSecurity) {
try{ try{
// 对回复内容进行文本安全检测
await this.textSecCheck(result.data.reply) await this.textSecCheck(result.data.reply)
}catch(e){ }catch(e){
// 如果检测到敏感内容 返回一个包含敏感内容提示和标记的响应体
return { return {
"data": { "data": {
"reply": "内容涉及敏感", "reply": "内容涉及敏感",
...@@ -155,12 +191,19 @@ module.exports = { ...@@ -155,12 +191,19 @@ module.exports = {
} }
} }
} }
// 返回处理后的结果
return result return result
}, },
// 发送消息
async send({ async send({
// 消息内容
messages, messages,
// sse渠道对象
sseChannel sseChannel
}) { }) {
// 初次调试时,可不从客户端获取数据,直接使用下面写死在云函数里的数据 // 初次调试时,可不从客户端获取数据,直接使用下面写死在云函数里的数据
// messages = [{ // messages = [{
// role: 'user', // role: 'user',
...@@ -168,91 +211,123 @@ module.exports = { ...@@ -168,91 +211,123 @@ module.exports = {
// }] // }]
// 校验客户端提交的参数 // 校验客户端提交的参数
// 检查消息是否符合规范
let res = checkMessages(messages) let res = checkMessages(messages)
if (res.errCode) { if (res.errCode) {
throw new Error(res.errMsg) throw new Error(res.errMsg)
} }
// 向uni-ai发送消息 // 向uni-ai发送消息
// 调用chatCompletion函数,传入messages、sseChannel、llm参数
let {llm,chatCompletionOptions} = config let {llm,chatCompletionOptions} = config
return await chatCompletion({ return await chatCompletion({
messages, //消息内容 messages, //消息内容
sseChannel, //sse渠道对象 sseChannel, //sse渠道对象
llm llm
}) })
// chatCompletion函数:对话完成
async function chatCompletion({ async function chatCompletion({
// 消息列表
messages, messages,
// 是否需要总结
summarize = false, summarize = false,
// sse渠道对象
sseChannel = false, sseChannel = false,
// 语言模型
llm llm
}) { }) {
// 获取语言模型管理器
const llmManager = uniCloud.ai.getLLMManager(llm) const llmManager = uniCloud.ai.getLLMManager(llm)
// 调用chatCompletion方法,传入参数
let res = await llmManager.chatCompletion({ let res = await llmManager.chatCompletion({
...chatCompletionOptions, ...chatCompletionOptions,
messages, messages,
stream: sseChannel !== false stream: sseChannel !== false
}) })
// 如果存在sseChannel
if (sseChannel) { if (sseChannel) {
let reply = "" let reply = ""
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
// 反序列化sseChannel
const channel = uniCloud.deserializeSSEChannel(sseChannel) const channel = uniCloud.deserializeSSEChannel(sseChannel)
// 判断如果是open-ai按字返回,否则按行返回 // 判断如果是open-ai按字返回,否则按行返回
if(llm && llm.provider && llm.provider == "openai"){ if(llm && llm.provider && llm.provider == "openai"){
// 按字返回
res.on('message', async (message) => { res.on('message', async (message) => {
reply += message reply += message
await channel.write(message) await channel.write(message)
// console.log('---message----', message) // console.log('---message----', message)
}) })
}else{ }else{
// 按行返回
res.on('line', async (line) => { res.on('line', async (line) => {
await channel.write(reply? ("\n\n " + line) : line) await channel.write(reply? ("\n\n " + line) : line)
reply += line reply += line
// console.log('---line----', line) // console.log('---line----', line)
}) })
} }
// 结束返回
res.on('end', async () => { res.on('end', async () => {
// console.log('---end----',reply) // console.log('---end----',reply)
// 将回复内容添加到消息列表中
messages.push({ messages.push({
"content": reply, "content": reply,
"role": "assistant" "role": "assistant"
}) })
// 计算消息总长度
let totalTokens = messages.map(i => i.content).join('').length; let totalTokens = messages.map(i => i.content).join('').length;
// console.log('totalTokens',totalTokens); // console.log('totalTokens',totalTokens);
// 如果不需要总结且消息总长度超过500
if (!summarize && totalTokens > 500) { if (!summarize && totalTokens > 500) {
// 获取总结
let replySummarize = await getSummarize(messages) let replySummarize = await getSummarize(messages)
// console.log('replySummarize',replySummarize) // console.log('replySummarize',replySummarize)
// 结束sseChannel并返回总结
await channel.end({ await channel.end({
summarize: replySummarize summarize: replySummarize
}) })
} else { } else {
// 结束sseChannel
await channel.end() await channel.end()
} }
// 返回处理结果
resolve({ resolve({
errCode: 0 errCode: 0
}) })
}) })
// 返回错误
res.on('error', (err) => { res.on('error', (err) => {
console.error('---error----', err) console.error('---error----', err)
reject(err) reject(err)
}) })
}) })
} else { } else {
// 如果不需要总结
if (summarize == false) { if (summarize == false) {
// 将回复内容添加到消息列表中
messages.push({ messages.push({
"content": res.reply, "content": res.reply,
"role": "assistant" "role": "assistant"
}) })
// 计算消息总长度
let totalTokens = messages.map(i => i.content).join('').length; let totalTokens = messages.map(i => i.content).join('').length;
// 如果消息总长度超过500
if (totalTokens > 500) { if (totalTokens > 500) {
// 获取总结
let replySummarize = await getSummarize(messages) let replySummarize = await getSummarize(messages)
// 将总结添加到返回结果中
res.summarize = replySummarize res.summarize = replySummarize
} }
} }
// 如果存在错误
if(res.errCode){ if(res.errCode){
// 抛出错误
throw res throw res
} }
// 返回处理结果
return { return {
data:res, data:res,
errCode: 0 errCode: 0
...@@ -260,46 +335,73 @@ module.exports = { ...@@ -260,46 +335,73 @@ module.exports = {
} }
} }
//获总结 //获总结
async function getSummarize(messages) { async function getSummarize(messages) {
messages.push({ messages.push({
"content": "请简要总结上述全部对话", "content": "请简要总结上述全部对话",
"role": "user" "role": "user"
}) })
// 获取总结不需要再总结summarize和stream // 调用chatCompletion函数,传入messages、summarize、stream、sseChannel参数
let res = await chatCompletion({ let res = await chatCompletion({
// 消息内容
messages, messages,
// 是否需要总结
summarize: true, summarize: true,
// 是否需要流式返回
stream: false, stream: false,
// sse渠道对象
sseChannel: false sseChannel: false
}) })
// 返回总结的文字内容
return res.reply return res.reply
} }
/**
* 校验消息内容是否符合规范
* @param {Array} messages - 消息列表
* @returns {Object} - 返回校验结果
*/
function checkMessages(messages) { function checkMessages(messages) {
try { try {
// 如果messages未定义
if (messages === undefined) { if (messages === undefined) {
// 抛出异常
throw "messages为必传参数" throw "messages为必传参数"
// 如果messages不是数组
} else if (!Array.isArray(messages)) { } else if (!Array.isArray(messages)) {
// 抛出异常
throw "参数messages的值类型必须是[object,object...]" throw "参数messages的值类型必须是[object,object...]"
} else { } else {
// 否则 遍历messages
messages.forEach(item => { messages.forEach(item => {
// 如果item不是对象
if (typeof item != 'object') { if (typeof item != 'object') {
// 抛出异常
throw "参数messages的值类型必须是[object,object...]" throw "参数messages的值类型必须是[object,object...]"
} }
// 定义itemRoleArr数组
let itemRoleArr = ["assistant", "user", "system"] let itemRoleArr = ["assistant", "user", "system"]
// 如果item的role属性不在itemRoleArr数组中
if (!itemRoleArr.includes(item.role)) { if (!itemRoleArr.includes(item.role)) {
// 抛出异常
throw "参数messages[{role}]的值只能是:" + itemRoleArr.join('') throw "参数messages[{role}]的值只能是:" + itemRoleArr.join('')
} }
// 如果item的content属性不是字符串
if (typeof item.content != 'string') { if (typeof item.content != 'string') {
// 抛出异常
throw "参数messages[{content}]的值类型必须是字符串" throw "参数messages[{content}]的值类型必须是字符串"
} }
}) })
} }
// 返回校验结果
return { return {
errCode: 0, errCode: 0,
} }
// 捕获异常
} catch (errMsg) { } catch (errMsg) {
// 返回异常信息
return { return {
errSubject: 'ai-demo', errSubject: 'ai-demo',
errCode: 'param-error', errCode: 'param-error',
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册