UNPKG

@lobehub/chat

Version:

Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.

61 lines (52 loc) 1.92 kB
import { ChatResponse } from 'ollama/browser'; import { ChatStreamCallbacks } from '@/libs/model-runtime'; import { nanoid } from '@/utils/uuid'; import { StreamContext, StreamProtocolChunk, createCallbacksTransformer, createSSEProtocolTransformer, generateToolCallId, } from './protocol'; const transformOllamaStream = (chunk: ChatResponse, stack: StreamContext): StreamProtocolChunk => { // maybe need another structure to add support for multiple choices if (chunk.done && !chunk.message.content) { return { data: 'finished', id: stack.id, type: 'stop' }; } if (chunk.message.tool_calls && chunk.message.tool_calls.length > 0) { return { data: chunk.message.tool_calls.map((value, index) => ({ function: { arguments: JSON.stringify(value.function?.arguments) ?? '{}', name: value.function?.name ?? null, }, id: generateToolCallId(index, value.function?.name), index: index, type: 'function', })), id: stack.id, type: 'tool_calls', }; } // 判断是否有 <think> 或 </think> 标签,更新 thinkingInContent 状态 if (chunk.message.content.includes('<think>')) { stack.thinkingInContent = true; } else if (chunk.message.content.includes('</think>')) { stack.thinkingInContent = false; } // 清除 <think> 及 </think> 标签,并根据当前思考模式确定返回类型 return { data: chunk.message.content.replaceAll(/<\/?think>/g, ''), id: stack.id, type: stack?.thinkingInContent ? 'reasoning' : 'text', }; }; export const OllamaStream = ( res: ReadableStream<ChatResponse>, cb?: ChatStreamCallbacks, ): ReadableStream<string> => { const streamStack: StreamContext = { id: 'chat_' + nanoid() }; return res .pipeThrough(createSSEProtocolTransformer(transformOllamaStream, streamStack)) .pipeThrough(createCallbacksTransformer(cb)); };