typescript - tRPC stream API válasz az OpenAI-tól a React klienshez
Jelenleg azon dolgozom, hogyan lehetne a openai-node csomagot beépíteni a Next.js alkalmazásomba. Az OpenAI kiegészítések hosszú generálási ideje miatt szeretném kihasználni a streaminget (ami a csomagon belül általában nem támogatott, lásd itt). De van egy megoldásom, ami hibátlanul működik, az alábbi kódban:
const response = await openai.createChatCompletion({
messages: [
{
role: 'user',
content: 'hello there!'
}
],
model: 'gpt-3.5-turbo',
temperature: 0.85,
stream: true
}, { responseType: 'stream' })
let activeRole = '';
response.data.on('data', (data: Buffer) => {
const lines = data.toString().split('\n').filter(line => line.trim() !== '');
lines.forEach(( line, idx, arr ) => {
const message = line.replace(/^data: /, '');
if(message === '[DONE]') return
const parsed:OpenAIStreamChunk = JSON.parse(message);
if(parsed.choices[0].finish_reason == 'stop') return
activeRole = parsed.choices[0].delta.role ?? activeRole
const chunk = {
role: activeRole,
content: parsed.choices[0].delta.content ?? 'EMPTY'
}
console.log(chunk)
})
});
Most azt szeretném, ha a fenti kódot arra használnám, hogy az áramlást az API útvonalamról a front-endemre továbbítsam (hogy az áramlást ott feldolgozzák). Az alkalmazásomban a tRPC-t használom, és eddig így hoztam létre:
// Backend code:
import { Readable } from 'stream';
import { initOpenAI } from 'lib/ai';
export const analysisRouter = router({
generate: authenticatedProcedure
.input(z.object({
}))
.mutation( async ({ ctx, input }) => {
const stream = new Readable({ objectMode: true})
const openai = initOpenAI()
const result = await openai.createChatCompletion({
messages: [
{
role: 'user',
content: 'hello there!'
}
],
model: 'gpt-3.5-turbo',
temperature: 0.85,
stream: true
}, { responseType: 'stream' })
let activeRole = '';
result.data.on('data', (data: Buffer) => {
const lines = data.toString().split('\n').filter(line => line.trim() !== '');
for(const line of lines) {
const message = line.replace(/^data: /, '');
if(message === '[DONE]') return
const parsed:OpenAIStreamChunk = JSON.parse(message);
if(parsed.choices[0].finish_reason == 'stop') return
activeRole = parsed.choices[0].delta.role ?? activeRole
if(parsed.choices[0].delta.content) {
stream.push({
role: activeRole,
content: parsed.choices[0].delta.content
})
}
}
});
return stream
})
})
// Front-end code, that reads the stream (this is in React)
useEffect(() => {
(async () => {
const stream = await trpc.analysis.generate.mutate({ type: 'lesson'})
stream.on('data', (data) => { console.log(data) })
})()
}, [])
Kivéve, hogy a fenti kód valójában nem működik megfelelően. A kliensoldali stream eseményei üresek, és a stream.on nem ismerhető fel érvényes függvényként. Tudom, hogy ez a tRPC kód technikailag nem egy stream, de valaki rá tud mutatni az egyértelmű hibára? Mit kell módosítanom ahhoz, hogy a tRPC-n keresztüli streamelést támogassa? Egyáltalán lehetséges ez?
Előre is köszönöm.
Válasz #1
2024. április 13-tól a tRPC csak json-t támogat.
Tegnap feltettem ezt a kérdést egy magcsapattagának egy csevegésben.
Van egy vita erről a témáról, de nem világos, hogy a tRPC támogatni fogja-e a streamelést.
Válasz #2
2024. július 30-tól a szerver HTTP streaming válaszát most már támogatja ez a PR: https://github.com/trpc/trpc/pull/5700.
Dokumentáció: https://trpc.io/docs/client/links/httpBatchStreamLink#generators