写个Ai对话小程序SSE

前言

最近捣鼓小程序,突然发现小程序好像没怎么有ai对话,就突然想写一个对话小程序,记录一下走过的坑。

前端:uniapp 后端:express openai-node

后端实现流对话功能

本来后端用的是egg.js,但是我写的时候发现egg时候使用body返回PassThrough数据就会等待全部数据返回后一起返回,具体原因使用for循环就会出现这种情况,使用setTimeout模拟流数据就不会出现这种情况,由于我对egg不是很熟悉就没有研究这是为什么,知道的朋友可以留言告知我为什么下面是egg.js的代码

 ctx.set('Content-Type', 'text/event-stream');
 const PassThrough1 = new PassThrough()
 ctx.body = PassThrough1
 const stream = await openai.chat.completions.create({
     messages: [{role: 'user', content: prompt}],
     model: 'qwen-plus',
     stream: true,
 });
for await (const chunk of stream) {
    try {
        PassThrough1.write(`${JSON.stringify(chunk)}\n\n`)
    }catch (e) {
        console.log(e)
    }
}

随后我又尝试了几次后无法解决就开始改用express,由于现在ChatGPT全面禁用咱们,所以我用的通义千问,虽然还没有node版本的jdk,但是还好支持opneai库只需要修改链接就可以,这样我们只要访问/ai这个接口就会得到流式数据并且渲染他。

const express = require('express')
const {OpenAI} = require('openai')
const app = express()
const port = 3000
const openai = new OpenAI({
    apiKey: '********',
    baseURL: "https://dashscope.aliyuncs.com/compatible-mode/v1",
});
app.get('/ai', async (req, res) => {
    res.writeHead(200, { 'Content-Type': 'text/event-stream' }) // 'tex
    const prompt = req.query.prompt
    const stream = await openai.chat.completions.create({
        messages: [{role: 'user', content: prompt}],
        model: 'qwen-plus',
        stream: true,
    });
    for await (const chunk of stream) {
        // console.log(chunk)
        res.write(`${JSON.stringify(chunk.choices[0]?.delta?.content || '')}`) 
    }
    req.on('close', () => {
        console.log('req close...')
    })

})
app.listen(port, () => {
    console.log(`Example app listening on port ${port}`)
})

uniapp编写小程序

小程序现在并不支持sse,所以我只能用以下方法来进行获取流数据,前端只写了核心代码。

const requestTask = uni.request({
	url: 'http://127.0.0.1:3000/ai',
	timeout: 15000,
	responseType: 'text',
        method: 'GET',
	enableChunked: true,  //配置这里
	data: {
	     prompt: this.content
        },
	success: response => {
	     console.log(response)
	},
	     fail: error => {}
	})
	requestTask.onHeadersReceived(function(res) {
	    console.log(res.header);
	})
  requestTask.onChunkReceived((res)=> {
    //二进制数据转为字符串
    const uint8Array = new Uint8Array(res.data);
    let text = String.fromCharCode.apply(null, uint8Array);
    text = decodeURIComponent(escape(text)).replace(/\"/g, "");
  })

至此一个简单的ai对话就完成了

在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值