Skip to content

Commit 747614c

Browse files
committed
dev: integrate stream normalization for OpenAI
1 parent 437467e commit 747614c

File tree

1 file changed

+45
-18
lines changed

1 file changed

+45
-18
lines changed

src/backend/src/modules/puterai/OpenAICompletionService.js

+45-18
Original file line numberDiff line numberDiff line change
@@ -312,17 +312,15 @@ class OpenAICompletionService extends BaseService {
312312
if ( stream ) {
313313
let usage_promise = new TeePromise();
314314

315-
const entire = [];
316-
const stream = new PassThrough();
317-
const retval = new TypedValue({
318-
$: 'stream',
319-
content_type: 'application/x-ndjson',
320-
chunked: true,
321-
}, stream);
322-
(async () => {
315+
const init_chat_stream = async ({ chatStream }) => {
316+
const message = chatStream.message();
317+
let textblock = message.contentBlock({ type: 'text' });
318+
let toolblock = null;
319+
let mode = 'text';
320+
const tool_call_blocks = [];
321+
323322
for await ( const chunk of completion ) {
324-
// console.log('CHUNK', chunk, JSON.stringify(chunk?.choices?.[0]?.delta ?? null));
325-
entire.push(chunk);
323+
console.log('CHUNK', chunk, JSON.stringify(chunk?.choices?.[0]?.delta ?? null));
326324
if ( chunk.usage ) {
327325
usage_promise.resolve({
328326
input_tokens: chunk.usage.prompt_tokens,
@@ -331,18 +329,47 @@ class OpenAICompletionService extends BaseService {
331329
continue;
332330
}
333331
if ( chunk.choices.length < 1 ) continue;
334-
if ( nou(chunk.choices[0].delta.content) ) continue;
335-
const str = JSON.stringify({
336-
text: chunk.choices[0].delta.content
337-
});
338-
stream.write(str + '\n');
332+
333+
const choice = chunk.choices[0];
334+
335+
if ( ! nou(choice.delta.content) ) {
336+
if ( mode === 'tool' ) {
337+
toolblock.end();
338+
mode = 'text';
339+
textblock = message.contentBlock({ type: 'text' });
340+
}
341+
textblock.addText(choice.delta.content);
342+
continue;
343+
}
344+
345+
if ( ! nou(choice.delta.tool_calls) ) {
346+
if ( mode === 'text' ) {
347+
mode = 'tool';
348+
textblock.end();
349+
}
350+
for ( const tool_call of choice.delta.tool_calls ) {
351+
if ( ! tool_call_blocks[tool_call.index] ) {
352+
toolblock = message.contentBlock({
353+
type: 'tool_use',
354+
id: tool_call.function.name,
355+
});
356+
tool_call_blocks[tool_call.index] = toolblock;
357+
} else {
358+
toolblock = tool_call_blocks[tool_call.index];
359+
}
360+
toolblock.addPartialJSON(tool_call.function.arguments);
361+
}
362+
}
339363
}
340-
stream.end();
341-
})();
364+
365+
if ( mode === 'text' ) textblock.end();
366+
if ( mode === 'tool' ) toolblock.end();
367+
message.end();
368+
};
342369

343370
return new TypedValue({ $: 'ai-chat-intermediate' }, {
344371
stream: true,
345-
response: retval,
372+
init_chat_stream,
346373
usage_promise: usage_promise,
347374
});
348375
return retval;

0 commit comments

Comments
 (0)