uniapp通过SSE方式接入AI大模型的流式输出
·
前言:由于SSE部分使用了别人的插件,在这里仅提供思路来处理SSE
1.SSE部分思路:
1.1 APP: APP原生本身并不支持SSE的链接,所以这里需要通过取巧的方式,也就是我前面文章提到过的,renderjs来实现,通过renderjs来模拟浏览器环境,实现SSE的链接
1.2 微信小程序:微信小程序本身支持sse的方式链接,所以可以直接调用
uni.request({
url: url,
method,
header: {
Accept: 'text/event-stream',
...headers,
},
data: body,
enableChunked: true,
responseType: 'arraybuffer',
success: (res) => {},
fail: (error) => {
this.$emit("onInnerError", error)
},
complete: () => {
this.$emit("onInnerFinish")
},
});
2.解析部分
const parseSSEData = (data) => {
try {
const parsed = JSON.parse(data)
// 检查是否直接返回了 reasoning_content
const directReasoning = parsed.choices?.[0]?.delta?.reasoning_content
if (directReasoning) {
return {
id: parsed.id,
created: parsed.created,
model: parsed.model,
reasoning_content: directReasoning,
content: parsed.choices?.[0]?.delta?.content || ''
}
}
const content = parsed.choices?.[0]?.delta?.content || ''
// 处理 think 标签包裹的情况
if (content.includes('<think>')) {
isInThinkTag.value = true
const startIndex = content.indexOf('<think>') + '<think>'.length
return {
id: parsed.id,
created: parsed.created,
model: parsed.model,
reasoning_content: content.substring(startIndex),
content: content.substring(0, content.indexOf('<think>'))
}
}
if (content.includes('</think>')) {
isInThinkTag.value = false
const endIndex = content.indexOf('</think>')
return {
id: parsed.id,
created: parsed.created,
model: parsed.model,
reasoning_content: content.substring(0, endIndex),
content: content.substring(endIndex + '</think>'.length)
}
}
// 根据状态决定内容归属
return {
id: parsed.id,
created: parsed.created,
model: parsed.model,
reasoning_content: isInThinkTag.value ? content : '',
content: isInThinkTag.value ? '' : content
}
} catch (e) {
console.error('解析JSON失败:', e)
return null
}
}
通过计算属性获取解析内容分类,做展示
// 计算推理过程(思考链)
const reasoningChain = computed(() => {
return messages.value
.filter(m => m.parsed?.reasoning_content)
.map(m => m.parsed.reasoning_content)
.join('')
})
// 计算最终答案
const finalAnswer = computed(() => {
const rawContent = messages.value
.filter(m => m.parsed?.content)
.map(m => m.parsed.content)
.join('')
return rawContent
// return marked.parse(rawContent)
})
这里需要注意,在微信小程序marked这个插件可以用来解析marketdown,但是在APP这个插件会报错,这里大家可以自行寻找插件来进行解析marketdown
更多推荐
所有评论(0)