V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  yowot0088  ›  全部回复第 1 页 / 共 1 页
回复总数  2
附上我做的 ws api 的源码

```js
wss.on('connection', ws => {
let isConnected = true

ws.on('message', async e => {
let message = JSON.parse(e.toString())
if(message.type == 'conversation') {
let es = await fetch('https://api.openai.com/v1/chat/completions', {
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + 'YOUR_OPENAI_API_KEY'
},
method: 'POST',
body: JSON.stringify({
model: message.data.model,
messages: message.data.messages,
stream: true
})
})

const reader = es.body.pipeThrough(new TextDecoderStream()).getReader()

let errObj = ''

while(true) {
if(!isConnected) {
process.stdout.write('\n')
break
}
const res = await reader.read()
if(res.done) {
break
}
let chunk = res.value
chunk = chunk.replace(/data: /g, '').split('\n')

chunk.map(item => {
if(item != '[DONE]' && item != '' && item != undefined) {
let json

try {
if(errObj != '') {
item = errObj + item
errObj = ''
}

json = JSON.parse(item)

if(json.choices[0].delta.content == undefined) return
ws.send(JSON.stringify({
type: 'conversation',
data: {
type: 'continue',
text: json.choices[0].delta.content
}
}))
process.stdout.write(json.choices[0].delta.content)
}catch {
errObj = item
return
}

}else if(item == '[DONE]') {
ws.send(JSON.stringify({
type: 'conversation',
data: {
type: 'done',
text: null
}
}))
process.stdout.write('\n')
}
})
}
}
})

ws.onclose = () => {
isConnected = false
}
})
```
我的解决方法是,先判断一个 chunk 里最后的 data: 是否为一个合法的 json ,如果不是,则将下一次最开始接收到的字符串与前一次的非法 json 拼接,可以完美解决
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1785 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 11ms · UTC 16:43 · PVG 00:43 · LAX 09:43 · JFK 12:43
Developed with CodeLauncher
♥ Do have faith in what you're doing.