in src/lib/server/endpoints/openai/openAIChatToTextGenerationStream.ts [54:133]
for await (const completion of completionStream) {
const { choices } = completion;
const content = choices[0]?.delta?.content ?? "";
const last = choices[0]?.finish_reason === "stop" || choices[0]?.finish_reason === "length";
// if the last token is a stop and the tool buffer is not empty, yield it as a generated_text
if (choices[0]?.finish_reason === "stop" && toolBuffer.length > 0) {
yield {
token: {
id: tokenId++,
special: true,
logprob: 0,
text: "",
},
generated_text: toolBuffer,
details: null,
} as TextGenerationStreamOutput;
break;
}
// weird bug where the parameters are streamed in like this
if (choices[0]?.delta?.tool_calls) {
const calls = Array.isArray(choices[0].delta.tool_calls)
? choices[0].delta.tool_calls
: [choices[0].delta.tool_calls];
if (
calls.length === 1 &&
calls[0].index === 0 &&
calls[0].id === "" &&
calls[0].type === "function" &&
!!calls[0].function &&
calls[0].function.name === null
) {
toolBuffer += calls[0].function.arguments;
continue;
}
}
if (content) {
generatedText = generatedText + content;
}
const output: TextGenerationStreamOutput = {
token: {
id: tokenId++,
text: content ?? "",
logprob: 0,
special: last,
},
generated_text: last ? generatedText : null,
details: null,
};
yield output;
const tools = completion.choices[0]?.delta?.tool_calls || [];
for (const tool of tools) {
if (tool.id) {
if (!tool.function?.name) {
throw new Error("Tool call without function name");
}
const toolCallWithParameters: ToolCallWithParameters = {
toolCall: {
name: tool.function.name,
parameters: {},
toolId: tool.id,
},
parameterJsonString: "",
};
toolCalls.push(toolCallWithParameters);
}
if (toolCalls.length > 0 && tool.function?.arguments) {
toolCalls[toolCalls.length - 1].parameterJsonString += tool.function.arguments;
}
}
if (choices[0]?.finish_reason === "tool_calls") {
yield prepareToolCalls(toolCalls, tokenId++);
}
}