Spaces:
Sleeping
Sleeping
| // eslint-disable-next-line @typescript-eslint/ban-ts-comment | |
| // @ts-nocheck – TODO: Provider proper types | |
| import { convertToCoreMessages, streamText as _streamText } from 'ai'; | |
| import { getModel } from '~/lib/.server/llm/model'; | |
| import { MAX_TOKENS } from './constants'; | |
| import { getSystemPrompt } from './prompts'; | |
| import { DEFAULT_MODEL, DEFAULT_PROVIDER, MODEL_LIST, MODEL_REGEX, PROVIDER_REGEX } from '~/utils/constants'; | |
| interface ToolResult<Name extends string, Args, Result> { | |
| toolCallId: string; | |
| toolName: Name; | |
| args: Args; | |
| result: Result; | |
| } | |
| interface Message { | |
| role: 'user' | 'assistant'; | |
| content: string; | |
| toolInvocations?: ToolResult<string, unknown, unknown>[]; | |
| model?: string; | |
| } | |
| export type Messages = Message[]; | |
| export type StreamingOptions = Omit<Parameters<typeof _streamText>[0], 'model'>; | |
| function extractPropertiesFromMessage(message: Message): { model: string; provider: string; content: string } { | |
| const textContent = Array.isArray(message.content) | |
| ? message.content.find((item) => item.type === 'text')?.text || '' | |
| : message.content; | |
| const modelMatch = textContent.match(MODEL_REGEX); | |
| const providerMatch = textContent.match(PROVIDER_REGEX); | |
| /* | |
| * Extract model | |
| * const modelMatch = message.content.match(MODEL_REGEX); | |
| */ | |
| const model = modelMatch ? modelMatch[1] : DEFAULT_MODEL; | |
| /* | |
| * Extract provider | |
| * const providerMatch = message.content.match(PROVIDER_REGEX); | |
| */ | |
| const provider = providerMatch ? providerMatch[1] : DEFAULT_PROVIDER; | |
| const cleanedContent = Array.isArray(message.content) | |
| ? message.content.map((item) => { | |
| if (item.type === 'text') { | |
| return { | |
| type: 'text', | |
| text: item.text?.replace(MODEL_REGEX, '').replace(PROVIDER_REGEX, ''), | |
| }; | |
| } | |
| return item; // Preserve image_url and other types as is | |
| }) | |
| : textContent.replace(MODEL_REGEX, '').replace(PROVIDER_REGEX, ''); | |
| return { model, provider, content: cleanedContent }; | |
| } | |
| export function streamText(messages: Messages, env: Env, options?: StreamingOptions, apiKeys?: Record<string, string>) { | |
| let currentModel = DEFAULT_MODEL; | |
| let currentProvider = DEFAULT_PROVIDER; | |
| const processedMessages = messages.map((message) => { | |
| if (message.role === 'user') { | |
| const { model, provider, content } = extractPropertiesFromMessage(message); | |
| if (MODEL_LIST.find((m) => m.name === model)) { | |
| currentModel = model; | |
| } | |
| currentProvider = provider; | |
| return { ...message, content }; | |
| } | |
| return message; | |
| }); | |
| const modelDetails = MODEL_LIST.find((m) => m.name === currentModel); | |
| const dynamicMaxTokens = modelDetails && modelDetails.maxTokenAllowed ? modelDetails.maxTokenAllowed : MAX_TOKENS; | |
| return _streamText({ | |
| ...options, | |
| model: getModel(currentProvider, currentModel, env, apiKeys), | |
| system: getSystemPrompt(), | |
| maxTokens: dynamicMaxTokens, | |
| messages: convertToCoreMessages(processedMessages), | |
| }); | |
| } | |