前言:由于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

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐