import { type CoreMessage, type LanguageModelV1, embed, generateText, streamText, } from "ai"; import { openai } from "@ai-sdk/openai"; import { logger } from "~/services/logger.service"; import { createOllama, type OllamaProvider } from "ollama-ai-provider"; import { anthropic } from "@ai-sdk/anthropic"; import { google } from "@ai-sdk/google"; import { createAmazonBedrock } from "@ai-sdk/amazon-bedrock"; import { fromNodeProviderChain } from "@aws-sdk/credential-providers"; export async function makeModelCall( stream: boolean, messages: CoreMessage[], onFinish: (text: string, model: string) => void, options?: any, ) { let modelInstance: LanguageModelV1 | undefined; let model = process.env.MODEL as any; const ollamaUrl = process.env.OLLAMA_URL; let ollama: OllamaProvider | undefined; if (ollamaUrl) { ollama = createOllama({ baseURL: ollamaUrl, }); } const bedrock = createAmazonBedrock({ region: process.env.AWS_REGION || 'us-east-1', credentialProvider: fromNodeProviderChain(), }); const generateTextOptions: any = {} model = 'us.amazon.nova-premier-v1:0' switch (model) { case "gpt-4.1-2025-04-14": case "gpt-4.1-mini-2025-04-14": case "gpt-5-mini-2025-08-07": case "gpt-5-2025-08-07": case "gpt-4.1-nano-2025-04-14": modelInstance = openai(model, { ...options }); generateTextOptions.temperature = 1 break; case "claude-3-7-sonnet-20250219": case "claude-3-opus-20240229": case "claude-3-5-haiku-20241022": modelInstance = anthropic(model, { ...options }); break; case "gemini-2.5-flash-preview-04-17": case "gemini-2.5-pro-preview-03-25": case "gemini-2.0-flash": case "gemini-2.0-flash-lite": modelInstance = google(model, { ...options }); break; case "us.meta.llama3-3-70b-instruct-v1:0": case "us.deepseek.r1-v1:0": case "qwen.qwen3-32b-v1:0": case "openai.gpt-oss-120b-1:0": case "us.mistral.pixtral-large-2502-v1:0": case "us.amazon.nova-premier-v1:0": modelInstance = bedrock(`${model}`); break; default: if (ollama) { modelInstance = ollama(model); } logger.warn(`Unsupported model type: ${model}`); break; } if (!modelInstance) { throw new Error(`Unsupported model type: ${model}`); } if (stream) { return streamText({ model: modelInstance, messages, ...generateTextOptions, onFinish: async ({ text }) => { onFinish(text, model); }, }); } const { text, response } = await generateText({ model: modelInstance, messages, ...generateTextOptions, }); onFinish(text, model); return text; } /** * Determines if the current model is proprietary (OpenAI, Anthropic, Google, Grok) * or open source (accessed via Bedrock, Ollama, etc.) */ export function isProprietaryModel(): boolean { const model = process.env.MODEL; if (!model) return false; // Proprietary model patterns const proprietaryPatterns = [ /^gpt-/, // OpenAI models /^claude-/, // Anthropic models /^gemini-/, // Google models /^grok-/, // xAI models ]; return proprietaryPatterns.some(pattern => pattern.test(model)); } export async function getEmbedding(text: string) { const ollamaUrl = process.env.OLLAMA_URL; // Default to using Ollama const model = process.env.EMBEDDING_MODEL; if (model === "text-embedding-3-small") { // Use OpenAI embedding model when explicitly requested const { embedding } = await embed({ model: openai.embedding("text-embedding-3-small"), value: text, }); return embedding; } const ollama = createOllama({ baseURL: ollamaUrl, }); const { embedding } = await embed({ model: ollama.embedding(model as string), value: text, }); return embedding; }