mirror of
				https://github.com/TriliumNext/Notes.git
				synced 2025-10-31 13:01:31 +08:00 
			
		
		
		
	try using a new ProviderOptions approach
This commit is contained in:
		
							parent
							
								
									4f812cd2ce
								
							
						
					
					
						commit
						1dfbabc1d1
					
				| @ -2,6 +2,9 @@ import options from '../../options.js'; | |||||||
| import { BaseAIService } from '../base_ai_service.js'; | import { BaseAIService } from '../base_ai_service.js'; | ||||||
| import type { ChatCompletionOptions, ChatResponse, Message } from '../ai_interface.js'; | import type { ChatCompletionOptions, ChatResponse, Message } from '../ai_interface.js'; | ||||||
| import { PROVIDER_CONSTANTS } from '../constants/provider_constants.js'; | import { PROVIDER_CONSTANTS } from '../constants/provider_constants.js'; | ||||||
|  | import type { AnthropicOptions } from './provider_options.js'; | ||||||
|  | import { getAnthropicOptions } from './providers.js'; | ||||||
|  | import log from '../../log.js'; | ||||||
| 
 | 
 | ||||||
| interface AnthropicMessage { | interface AnthropicMessage { | ||||||
|     role: string; |     role: string; | ||||||
| @ -22,42 +25,67 @@ export class AnthropicService extends BaseAIService { | |||||||
|             throw new Error('Anthropic service is not available. Check API key and AI settings.'); |             throw new Error('Anthropic service is not available. Check API key and AI settings.'); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         const apiKey = options.getOption('anthropicApiKey'); |         // Get provider-specific options from the central provider manager
 | ||||||
|         const baseUrl = options.getOption('anthropicBaseUrl') || PROVIDER_CONSTANTS.ANTHROPIC.BASE_URL; |         const providerOptions = getAnthropicOptions(opts); | ||||||
|         const model = opts.model || options.getOption('anthropicDefaultModel') || PROVIDER_CONSTANTS.ANTHROPIC.DEFAULT_MODEL; |  | ||||||
| 
 | 
 | ||||||
|         const temperature = opts.temperature !== undefined |         // Log provider metadata if available
 | ||||||
|             ? opts.temperature |         if (providerOptions.providerMetadata) { | ||||||
|             : parseFloat(options.getOption('aiTemperature') || '0.7'); |             log.info(`Using model ${providerOptions.model} from provider ${providerOptions.providerMetadata.provider}`); | ||||||
| 
 | 
 | ||||||
|         const systemPrompt = this.getSystemPrompt(opts.systemPrompt || options.getOption('aiSystemPrompt')); |             // Log capabilities if available
 | ||||||
|  |             const capabilities = providerOptions.providerMetadata.capabilities; | ||||||
|  |             if (capabilities) { | ||||||
|  |                 log.info(`Model capabilities: ${JSON.stringify(capabilities)}`); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         const systemPrompt = this.getSystemPrompt(providerOptions.systemPrompt || options.getOption('aiSystemPrompt')); | ||||||
| 
 | 
 | ||||||
|         // Format for Anthropic's API
 |         // Format for Anthropic's API
 | ||||||
|         const formattedMessages = this.formatMessages(messages, systemPrompt); |         const formattedMessages = this.formatMessages(messages, systemPrompt); | ||||||
| 
 | 
 | ||||||
|  |         // Store the formatted messages in the provider options for future reference
 | ||||||
|  |         providerOptions.formattedMessages = formattedMessages; | ||||||
|  | 
 | ||||||
|         try { |         try { | ||||||
|             // Ensure base URL doesn't already include '/v1' and build the complete endpoint
 |             // Ensure base URL doesn't already include '/v1' and build the complete endpoint
 | ||||||
|             const cleanBaseUrl = baseUrl.replace(/\/+$/, '').replace(/\/v1$/, ''); |             const cleanBaseUrl = providerOptions.baseUrl.replace(/\/+$/, '').replace(/\/v1$/, ''); | ||||||
|             const endpoint = `${cleanBaseUrl}/v1/messages`; |             const endpoint = `${cleanBaseUrl}/v1/messages`; | ||||||
| 
 | 
 | ||||||
|             console.log(`Anthropic API endpoint: ${endpoint}`); |             console.log(`Anthropic API endpoint: ${endpoint}`); | ||||||
|             console.log(`Using model: ${model}`); |             console.log(`Using model: ${providerOptions.model}`); | ||||||
|  | 
 | ||||||
|  |             // Create request body directly from provider options
 | ||||||
|  |             const requestBody: any = { | ||||||
|  |                 model: providerOptions.model, | ||||||
|  |                 messages: formattedMessages.messages, | ||||||
|  |                 system: formattedMessages.system, | ||||||
|  |             }; | ||||||
|  | 
 | ||||||
|  |             // Extract API parameters from provider options
 | ||||||
|  |             const apiParams = { | ||||||
|  |                 temperature: providerOptions.temperature, | ||||||
|  |                 max_tokens: providerOptions.max_tokens, | ||||||
|  |                 stream: providerOptions.stream, | ||||||
|  |                 top_p: providerOptions.top_p | ||||||
|  |             }; | ||||||
|  | 
 | ||||||
|  |             // Merge API parameters, filtering out undefined values
 | ||||||
|  |             Object.entries(apiParams).forEach(([key, value]) => { | ||||||
|  |                 if (value !== undefined) { | ||||||
|  |                     requestBody[key] = value; | ||||||
|  |                 } | ||||||
|  |             }); | ||||||
| 
 | 
 | ||||||
|             const response = await fetch(endpoint, { |             const response = await fetch(endpoint, { | ||||||
|                 method: 'POST', |                 method: 'POST', | ||||||
|                 headers: { |                 headers: { | ||||||
|                     'Content-Type': 'application/json', |                     'Content-Type': 'application/json', | ||||||
|                     'X-Api-Key': apiKey, |                     'X-Api-Key': providerOptions.apiKey, | ||||||
|                     'anthropic-version': PROVIDER_CONSTANTS.ANTHROPIC.API_VERSION, |                     'anthropic-version': providerOptions.apiVersion || PROVIDER_CONSTANTS.ANTHROPIC.API_VERSION, | ||||||
|                     'anthropic-beta': PROVIDER_CONSTANTS.ANTHROPIC.BETA_VERSION |                     'anthropic-beta': providerOptions.betaVersion || PROVIDER_CONSTANTS.ANTHROPIC.BETA_VERSION | ||||||
|                 }, |                 }, | ||||||
|                 body: JSON.stringify({ |                 body: JSON.stringify(requestBody) | ||||||
|                     model, |  | ||||||
|                     messages: formattedMessages.messages, |  | ||||||
|                     system: formattedMessages.system, |  | ||||||
|                     temperature, |  | ||||||
|                     max_tokens: opts.maxTokens || 4000, |  | ||||||
|                 }) |  | ||||||
|             }); |             }); | ||||||
| 
 | 
 | ||||||
|             if (!response.ok) { |             if (!response.ok) { | ||||||
|  | |||||||
| @ -6,6 +6,8 @@ import { OllamaMessageFormatter } from '../formatters/ollama_formatter.js'; | |||||||
| import log from '../../log.js'; | import log from '../../log.js'; | ||||||
| import type { ToolCall } from '../tools/tool_interfaces.js'; | import type { ToolCall } from '../tools/tool_interfaces.js'; | ||||||
| import toolRegistry from '../tools/tool_registry.js'; | import toolRegistry from '../tools/tool_registry.js'; | ||||||
|  | import type { OllamaOptions } from './provider_options.js'; | ||||||
|  | import { getOllamaOptions } from './providers.js'; | ||||||
| 
 | 
 | ||||||
| interface OllamaFunctionArguments { | interface OllamaFunctionArguments { | ||||||
|     [key: string]: any; |     [key: string]: any; | ||||||
| @ -65,32 +67,33 @@ export class OllamaService extends BaseAIService { | |||||||
|             throw new Error('Ollama service is not available. Check API URL in settings.'); |             throw new Error('Ollama service is not available. Check API URL in settings.'); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         const apiBase = options.getOption('ollamaBaseUrl'); |         // Get provider-specific options from the central provider manager
 | ||||||
|  |         const providerOptions = await getOllamaOptions(opts); | ||||||
| 
 | 
 | ||||||
|         // Get the model name and strip the "ollama:" prefix if it exists
 |         // Log provider metadata if available
 | ||||||
|         let model = opts.model || options.getOption('ollamaDefaultModel') || 'llama3'; |         if (providerOptions.providerMetadata) { | ||||||
|         if (model.startsWith('ollama:')) { |             log.info(`Using model ${providerOptions.model} from provider ${providerOptions.providerMetadata.provider}`); | ||||||
|             model = model.substring(7); // Remove the "ollama:" prefix
 | 
 | ||||||
|             log.info(`Stripped 'ollama:' prefix from model name, using: ${model}`); |             // Log capabilities if available
 | ||||||
|  |             const capabilities = providerOptions.providerMetadata.capabilities; | ||||||
|  |             if (capabilities) { | ||||||
|  |                 log.info(`Model capabilities: ${JSON.stringify(capabilities)}`); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         const temperature = opts.temperature !== undefined |         const systemPrompt = this.getSystemPrompt(providerOptions.systemPrompt || options.getOption('aiSystemPrompt')); | ||||||
|             ? opts.temperature |  | ||||||
|             : parseFloat(options.getOption('aiTemperature') || '0.7'); |  | ||||||
| 
 |  | ||||||
|         const systemPrompt = this.getSystemPrompt(opts.systemPrompt || options.getOption('aiSystemPrompt')); |  | ||||||
| 
 | 
 | ||||||
|         try { |         try { | ||||||
|             // Check if we should add tool execution feedback
 |             // Check if we should add tool execution feedback
 | ||||||
|             if (opts.toolExecutionStatus && Array.isArray(opts.toolExecutionStatus) && opts.toolExecutionStatus.length > 0) { |             if (providerOptions.toolExecutionStatus && Array.isArray(providerOptions.toolExecutionStatus) && providerOptions.toolExecutionStatus.length > 0) { | ||||||
|                 log.info(`Adding tool execution feedback to messages`); |                 log.info(`Adding tool execution feedback to messages`); | ||||||
|                 messages = this.addToolExecutionFeedback(messages, opts.toolExecutionStatus); |                 messages = this.addToolExecutionFeedback(messages, providerOptions.toolExecutionStatus); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             // Determine whether to use the formatter or send messages directly
 |             // Determine whether to use the formatter or send messages directly
 | ||||||
|             let messagesToSend: Message[]; |             let messagesToSend: Message[]; | ||||||
| 
 | 
 | ||||||
|             if (opts.bypassFormatter) { |             if (providerOptions.bypassFormatter) { | ||||||
|                 // Bypass the formatter entirely - use messages as is
 |                 // Bypass the formatter entirely - use messages as is
 | ||||||
|                 messagesToSend = [...messages]; |                 messagesToSend = [...messages]; | ||||||
|                 log.info(`Bypassing formatter for Ollama request with ${messages.length} messages`); |                 log.info(`Bypassing formatter for Ollama request with ${messages.length} messages`); | ||||||
| @ -100,69 +103,58 @@ export class OllamaService extends BaseAIService { | |||||||
|                     messages, |                     messages, | ||||||
|                     systemPrompt, |                     systemPrompt, | ||||||
|                     undefined, // context
 |                     undefined, // context
 | ||||||
|                     opts.preserveSystemPrompt |                     providerOptions.preserveSystemPrompt | ||||||
|                 ); |                 ); | ||||||
|                 log.info(`Sending to Ollama with formatted messages: ${messagesToSend.length}`); |                 log.info(`Sending to Ollama with formatted messages: ${messagesToSend.length}`); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             // Check if this is a request that expects JSON response
 |             // Build request body base
 | ||||||
|             const expectsJsonResponse = opts.expectsJsonResponse || false; |  | ||||||
| 
 |  | ||||||
|             // Build request body
 |  | ||||||
|             const requestBody: any = { |             const requestBody: any = { | ||||||
|                 model, |                 model: providerOptions.model, | ||||||
|                 messages: messagesToSend, |                 messages: messagesToSend | ||||||
|                 options: { |  | ||||||
|                     temperature, |  | ||||||
|                     // Add num_ctx parameter based on model capabilities
 |  | ||||||
|                     num_ctx: await this.getModelContextWindowTokens(model), |  | ||||||
|                     // Add response_format for requests that expect JSON
 |  | ||||||
|                     ...(expectsJsonResponse ? { response_format: { type: "json_object" } } : {}) |  | ||||||
|                 }, |  | ||||||
|                 stream: false |  | ||||||
|             }; |             }; | ||||||
| 
 | 
 | ||||||
|             // Add tools if enabled - put them at the top level for Ollama
 |  | ||||||
|             if (opts.enableTools !== false) { |  | ||||||
|                 // Get tools from registry if not provided in options
 |  | ||||||
|                 if (!opts.tools || opts.tools.length === 0) { |  | ||||||
|                     try { |  | ||||||
|                         // Get tool definitions from registry
 |  | ||||||
|                         const tools = toolRegistry.getAllToolDefinitions(); |  | ||||||
|                         requestBody.tools = tools; |  | ||||||
|                         log.info(`Adding ${tools.length} tools to request`); |  | ||||||
| 
 | 
 | ||||||
|                         // If no tools found, reinitialize
 |             log.info(`Stream: ${providerOptions.stream}`); | ||||||
|                         if (tools.length === 0) { |             // Stream is a top-level option
 | ||||||
|                             log.info('No tools found in registry, re-initializing...'); |             if (providerOptions.stream !== undefined) { | ||||||
|                             try { |                 requestBody.stream = providerOptions.stream; | ||||||
|                                 const toolInitializer = await import('../tools/tool_initializer.js'); |  | ||||||
|                                 await toolInitializer.default.initializeTools(); |  | ||||||
| 
 |  | ||||||
|                                 // Try again
 |  | ||||||
|                                 requestBody.tools = toolRegistry.getAllToolDefinitions(); |  | ||||||
|                                 log.info(`After re-initialization: ${requestBody.tools.length} tools available`); |  | ||||||
|                             } catch (err: any) { |  | ||||||
|                                 log.error(`Failed to re-initialize tools: ${err.message}`); |  | ||||||
|                             } |  | ||||||
|                         } |  | ||||||
|                     } catch (error: any) { |  | ||||||
|                         log.error(`Error getting tools: ${error.message || String(error)}`); |  | ||||||
|                         // Create default empty tools array if we couldn't load the tools
 |  | ||||||
|                         requestBody.tools = []; |  | ||||||
|                     } |  | ||||||
|                 } else { |  | ||||||
|                     requestBody.tools = opts.tools; |  | ||||||
|                 } |  | ||||||
|                 log.info(`Adding ${requestBody.tools.length} tools to Ollama request`); |  | ||||||
|             } else { |  | ||||||
|                 log.info('Tools are explicitly disabled for this request'); |  | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             // Log key request details
 |             // Add options object if provided
 | ||||||
|  |             if (providerOptions.options) { | ||||||
|  |                 requestBody.options = { ...providerOptions.options }; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             // Add tools if enabled
 | ||||||
|  |             if (providerOptions.enableTools !== false) { | ||||||
|  |                 // Use provided tools or get from registry
 | ||||||
|  |                 try { | ||||||
|  |                     requestBody.tools = providerOptions.tools && providerOptions.tools.length > 0 | ||||||
|  |                         ? providerOptions.tools | ||||||
|  |                         : toolRegistry.getAllToolDefinitions(); | ||||||
|  | 
 | ||||||
|  |                     // Handle empty tools array
 | ||||||
|  |                     if (requestBody.tools.length === 0) { | ||||||
|  |                         log.info('No tools found, attempting to initialize tools...'); | ||||||
|  |                         const toolInitializer = await import('../tools/tool_initializer.js'); | ||||||
|  |                         await toolInitializer.default.initializeTools(); | ||||||
|  |                         requestBody.tools = toolRegistry.getAllToolDefinitions(); | ||||||
|  |                         log.info(`After initialization: ${requestBody.tools.length} tools available`); | ||||||
|  |                     } | ||||||
|  |                 } catch (error: any) { | ||||||
|  |                     log.error(`Error preparing tools: ${error.message || String(error)}`); | ||||||
|  |                     requestBody.tools = []; // Empty fallback
 | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             // Log request details
 | ||||||
|             log.info(`========== OLLAMA API REQUEST ==========`); |             log.info(`========== OLLAMA API REQUEST ==========`); | ||||||
|             log.info(`Model: ${requestBody.model}, Messages: ${requestBody.messages.length}, Tools: ${requestBody.tools ? requestBody.tools.length : 0}`); |             log.info(`Model: ${requestBody.model}, Messages: ${requestBody.messages.length}, Tools: ${requestBody.tools ? requestBody.tools.length : 0}`); | ||||||
|             log.info(`Temperature: ${temperature}, Stream: ${requestBody.stream}, JSON response expected: ${expectsJsonResponse}`); |             log.info(`Stream: ${requestBody.stream || false}, JSON response expected: ${providerOptions.expectsJsonResponse}`); | ||||||
|  |             if (requestBody.options) { | ||||||
|  |                 log.info(`Options: ${JSON.stringify(requestBody.options)}`); | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|             // Check message structure and log detailed information about each message
 |             // Check message structure and log detailed information about each message
 | ||||||
|             requestBody.messages.forEach((msg: any, index: number) => { |             requestBody.messages.forEach((msg: any, index: number) => { | ||||||
| @ -222,26 +214,13 @@ export class OllamaService extends BaseAIService { | |||||||
|             log.info(`========== FULL OLLAMA REQUEST ==========`); |             log.info(`========== FULL OLLAMA REQUEST ==========`); | ||||||
| 
 | 
 | ||||||
|             // Log request in manageable chunks
 |             // Log request in manageable chunks
 | ||||||
|             const maxChunkSize = 4000; |             log.info(`Full request: ${requestStr}`); | ||||||
|             if (requestStr.length > maxChunkSize) { |  | ||||||
|                 let i = 0; |  | ||||||
|                 while (i < requestStr.length) { |  | ||||||
|                     const chunk = requestStr.substring(i, i + maxChunkSize); |  | ||||||
|                     log.info(`Request part ${Math.floor(i/maxChunkSize) + 1}/${Math.ceil(requestStr.length/maxChunkSize)}: ${chunk}`); |  | ||||||
|                     i += maxChunkSize; |  | ||||||
|                 } |  | ||||||
|             } else { |  | ||||||
|                 log.info(`Full request: ${requestStr}`); |  | ||||||
|             } |  | ||||||
|             log.info(`========== END FULL OLLAMA REQUEST ==========`); |             log.info(`========== END FULL OLLAMA REQUEST ==========`); | ||||||
|             log.info(`========== END OLLAMA REQUEST ==========`); |  | ||||||
| 
 | 
 | ||||||
|             // Make API request
 |             // Send the request
 | ||||||
|             const response = await fetch(`${apiBase}/api/chat`, { |             const response = await fetch(`${providerOptions.baseUrl}/api/chat`, { | ||||||
|                 method: 'POST', |                 method: 'POST', | ||||||
|                 headers: { |                 headers: { 'Content-Type': 'application/json' }, | ||||||
|                     'Content-Type': 'application/json' |  | ||||||
|                 }, |  | ||||||
|                 body: JSON.stringify(requestBody) |                 body: JSON.stringify(requestBody) | ||||||
|             }); |             }); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -2,6 +2,8 @@ import options from '../../options.js'; | |||||||
| import { BaseAIService } from '../base_ai_service.js'; | import { BaseAIService } from '../base_ai_service.js'; | ||||||
| import type { ChatCompletionOptions, ChatResponse, Message } from '../ai_interface.js'; | import type { ChatCompletionOptions, ChatResponse, Message } from '../ai_interface.js'; | ||||||
| import { PROVIDER_CONSTANTS } from '../constants/provider_constants.js'; | import { PROVIDER_CONSTANTS } from '../constants/provider_constants.js'; | ||||||
|  | import type { OpenAIOptions } from './provider_options.js'; | ||||||
|  | import { getOpenAIOptions } from './providers.js'; | ||||||
| 
 | 
 | ||||||
| export class OpenAIService extends BaseAIService { | export class OpenAIService extends BaseAIService { | ||||||
|     constructor() { |     constructor() { | ||||||
| @ -17,14 +19,10 @@ export class OpenAIService extends BaseAIService { | |||||||
|             throw new Error('OpenAI service is not available. Check API key and AI settings.'); |             throw new Error('OpenAI service is not available. Check API key and AI settings.'); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         const apiKey = options.getOption('openaiApiKey'); |         // Get provider-specific options from the central provider manager
 | ||||||
|         const baseUrl = options.getOption('openaiBaseUrl') || PROVIDER_CONSTANTS.OPENAI.BASE_URL; |         const providerOptions = getOpenAIOptions(opts); | ||||||
|         const model = opts.model || options.getOption('openaiDefaultModel') || PROVIDER_CONSTANTS.OPENAI.DEFAULT_MODEL; |  | ||||||
|         const temperature = opts.temperature !== undefined |  | ||||||
|             ? opts.temperature |  | ||||||
|             : parseFloat(options.getOption('aiTemperature') || '0.7'); |  | ||||||
| 
 | 
 | ||||||
|         const systemPrompt = this.getSystemPrompt(opts.systemPrompt || options.getOption('aiSystemPrompt')); |         const systemPrompt = this.getSystemPrompt(providerOptions.systemPrompt || options.getOption('aiSystemPrompt')); | ||||||
| 
 | 
 | ||||||
|         // Ensure we have a system message
 |         // Ensure we have a system message
 | ||||||
|         const systemMessageExists = messages.some(m => m.role === 'system'); |         const systemMessageExists = messages.some(m => m.role === 'system'); | ||||||
| @ -34,23 +32,52 @@ export class OpenAIService extends BaseAIService { | |||||||
| 
 | 
 | ||||||
|         try { |         try { | ||||||
|             // Fix endpoint construction - ensure we don't double up on /v1
 |             // Fix endpoint construction - ensure we don't double up on /v1
 | ||||||
|             const normalizedBaseUrl = baseUrl.replace(/\/+$/, ''); |             const normalizedBaseUrl = providerOptions.baseUrl.replace(/\/+$/, ''); | ||||||
|             const endpoint = normalizedBaseUrl.includes('/v1') |             const endpoint = normalizedBaseUrl.includes('/v1') | ||||||
|                 ? `${normalizedBaseUrl}/chat/completions` |                 ? `${normalizedBaseUrl}/chat/completions` | ||||||
|                 : `${normalizedBaseUrl}/v1/chat/completions`; |                 : `${normalizedBaseUrl}/v1/chat/completions`; | ||||||
| 
 | 
 | ||||||
|  |             // Create request body directly from provider options
 | ||||||
|  |             const requestBody: any = { | ||||||
|  |                 model: providerOptions.model, | ||||||
|  |                 messages: messagesWithSystem, | ||||||
|  |             }; | ||||||
|  | 
 | ||||||
|  |             // Extract API parameters from provider options
 | ||||||
|  |             const apiParams = { | ||||||
|  |                 temperature: providerOptions.temperature, | ||||||
|  |                 max_tokens: providerOptions.max_tokens, | ||||||
|  |                 stream: providerOptions.stream, | ||||||
|  |                 top_p: providerOptions.top_p, | ||||||
|  |                 frequency_penalty: providerOptions.frequency_penalty, | ||||||
|  |                 presence_penalty: providerOptions.presence_penalty | ||||||
|  |             }; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |             // Merge API parameters, filtering out undefined values
 | ||||||
|  |             Object.entries(apiParams).forEach(([key, value]) => { | ||||||
|  |                 if (value !== undefined) { | ||||||
|  |                     requestBody[key] = value; | ||||||
|  |                 } | ||||||
|  |             }); | ||||||
|  | 
 | ||||||
|  |             // Add tools if enabled
 | ||||||
|  |             if (providerOptions.enableTools && providerOptions.tools && providerOptions.tools.length > 0) { | ||||||
|  |                 requestBody.tools = providerOptions.tools; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             if (providerOptions.tool_choice) { | ||||||
|  |                 requestBody.tool_choice = providerOptions.tool_choice; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|             const response = await fetch(endpoint, { |             const response = await fetch(endpoint, { | ||||||
|                 method: 'POST', |                 method: 'POST', | ||||||
|                 headers: { |                 headers: { | ||||||
|                     'Content-Type': 'application/json', |                     'Content-Type': 'application/json', | ||||||
|                     'Authorization': `Bearer ${apiKey}` |                     'Authorization': `Bearer ${providerOptions.apiKey}` | ||||||
|                 }, |                 }, | ||||||
|                 body: JSON.stringify({ |                 body: JSON.stringify(requestBody) | ||||||
|                     model, |  | ||||||
|                     messages: messagesWithSystem, |  | ||||||
|                     temperature, |  | ||||||
|                     max_tokens: opts.maxTokens, |  | ||||||
|                 }) |  | ||||||
|             }); |             }); | ||||||
| 
 | 
 | ||||||
|             if (!response.ok) { |             if (!response.ok) { | ||||||
| @ -68,7 +95,8 @@ export class OpenAIService extends BaseAIService { | |||||||
|                     promptTokens: data.usage?.prompt_tokens, |                     promptTokens: data.usage?.prompt_tokens, | ||||||
|                     completionTokens: data.usage?.completion_tokens, |                     completionTokens: data.usage?.completion_tokens, | ||||||
|                     totalTokens: data.usage?.total_tokens |                     totalTokens: data.usage?.total_tokens | ||||||
|                 } |                 }, | ||||||
|  |                 tool_calls: data.choices[0].message.tool_calls | ||||||
|             }; |             }; | ||||||
|         } catch (error) { |         } catch (error) { | ||||||
|             console.error('OpenAI service error:', error); |             console.error('OpenAI service error:', error); | ||||||
|  | |||||||
							
								
								
									
										202
									
								
								src/services/llm/providers/provider_options.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										202
									
								
								src/services/llm/providers/provider_options.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,202 @@ | |||||||
|  | import type { Message, ChatCompletionOptions } from '../ai_interface.js'; | ||||||
|  | import type { ToolCall } from '../tools/tool_interfaces.js'; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Model metadata interface to track provider information | ||||||
|  |  */ | ||||||
|  | export interface ModelMetadata { | ||||||
|  |   // The provider that supports this model
 | ||||||
|  |   provider: 'openai' | 'anthropic' | 'ollama' | 'local'; | ||||||
|  |   // The actual model identifier used by the provider's API
 | ||||||
|  |   modelId: string; | ||||||
|  |   // Display name for UI (optional)
 | ||||||
|  |   displayName?: string; | ||||||
|  |   // Model capabilities
 | ||||||
|  |   capabilities?: { | ||||||
|  |     contextWindow?: number; | ||||||
|  |     supportsTools?: boolean; | ||||||
|  |     supportsVision?: boolean; | ||||||
|  |     supportsStreaming?: boolean; | ||||||
|  |   }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Base provider configuration that's common to all providers | ||||||
|  |  * but not necessarily sent directly to APIs | ||||||
|  |  */ | ||||||
|  | export interface ProviderConfig { | ||||||
|  |   // Internal configuration
 | ||||||
|  |   systemPrompt?: string; | ||||||
|  |   // Provider metadata for model routing
 | ||||||
|  |   providerMetadata?: ModelMetadata; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * OpenAI-specific options, structured to match the OpenAI API | ||||||
|  |  */ | ||||||
|  | export interface OpenAIOptions extends ProviderConfig { | ||||||
|  |   // Connection settings (not sent to API)
 | ||||||
|  |   apiKey: string; | ||||||
|  |   baseUrl: string; | ||||||
|  | 
 | ||||||
|  |   // Direct API parameters as they appear in requests
 | ||||||
|  |   model: string; | ||||||
|  |   messages?: Message[]; | ||||||
|  |   temperature?: number; | ||||||
|  |   max_tokens?: number; | ||||||
|  |   stream?: boolean; | ||||||
|  |   top_p?: number; | ||||||
|  |   frequency_penalty?: number; | ||||||
|  |   presence_penalty?: number; | ||||||
|  |   tools?: any[]; | ||||||
|  |   tool_choice?: string | object; | ||||||
|  | 
 | ||||||
|  |   // Internal control flags (not sent directly to API)
 | ||||||
|  |   enableTools?: boolean; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Anthropic-specific options, structured to match the Anthropic API | ||||||
|  |  */ | ||||||
|  | export interface AnthropicOptions extends ProviderConfig { | ||||||
|  |   // Connection settings (not sent to API)
 | ||||||
|  |   apiKey: string; | ||||||
|  |   baseUrl: string; | ||||||
|  |   apiVersion?: string; | ||||||
|  |   betaVersion?: string; | ||||||
|  | 
 | ||||||
|  |   // Direct API parameters as they appear in requests
 | ||||||
|  |   model: string; | ||||||
|  |   messages?: any[]; | ||||||
|  |   system?: string; | ||||||
|  |   temperature?: number; | ||||||
|  |   max_tokens?: number; | ||||||
|  |   stream?: boolean; | ||||||
|  |   top_p?: number; | ||||||
|  | 
 | ||||||
|  |   // Internal parameters (not sent directly to API)
 | ||||||
|  |   formattedMessages?: { messages: any[], system: string }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Ollama-specific options, structured to match the Ollama API | ||||||
|  |  */ | ||||||
|  | export interface OllamaOptions extends ProviderConfig { | ||||||
|  |   // Connection settings (not sent to API)
 | ||||||
|  |   baseUrl: string; | ||||||
|  | 
 | ||||||
|  |   // Direct API parameters as they appear in requests
 | ||||||
|  |   model: string; | ||||||
|  |   messages?: Message[]; | ||||||
|  |   stream?: boolean; | ||||||
|  |   options?: { | ||||||
|  |     temperature?: number; | ||||||
|  |     num_ctx?: number; | ||||||
|  |     top_p?: number; | ||||||
|  |     top_k?: number; | ||||||
|  |     num_predict?: number; // equivalent to max_tokens
 | ||||||
|  |     response_format?: { type: string }; | ||||||
|  |   }; | ||||||
|  |   tools?: any[]; | ||||||
|  | 
 | ||||||
|  |   // Internal control flags (not sent directly to API)
 | ||||||
|  |   enableTools?: boolean; | ||||||
|  |   bypassFormatter?: boolean; | ||||||
|  |   preserveSystemPrompt?: boolean; | ||||||
|  |   expectsJsonResponse?: boolean; | ||||||
|  |   toolExecutionStatus?: any[]; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Create OpenAI options from generic options and config | ||||||
|  |  */ | ||||||
|  | export function createOpenAIOptions( | ||||||
|  |   opts: ChatCompletionOptions = {}, | ||||||
|  |   apiKey: string, | ||||||
|  |   baseUrl: string, | ||||||
|  |   defaultModel: string | ||||||
|  | ): OpenAIOptions { | ||||||
|  |   return { | ||||||
|  |     // Connection settings
 | ||||||
|  |     apiKey, | ||||||
|  |     baseUrl, | ||||||
|  | 
 | ||||||
|  |     // API parameters
 | ||||||
|  |     model: opts.model || defaultModel, | ||||||
|  |     temperature: opts.temperature, | ||||||
|  |     max_tokens: opts.maxTokens, | ||||||
|  |     stream: opts.stream, | ||||||
|  |     top_p: opts.topP, | ||||||
|  |     frequency_penalty: opts.frequencyPenalty, | ||||||
|  |     presence_penalty: opts.presencePenalty, | ||||||
|  |     tools: opts.tools, | ||||||
|  | 
 | ||||||
|  |     // Internal configuration
 | ||||||
|  |     systemPrompt: opts.systemPrompt, | ||||||
|  |     enableTools: opts.enableTools, | ||||||
|  |   }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Create Anthropic options from generic options and config | ||||||
|  |  */ | ||||||
|  | export function createAnthropicOptions( | ||||||
|  |   opts: ChatCompletionOptions = {}, | ||||||
|  |   apiKey: string, | ||||||
|  |   baseUrl: string, | ||||||
|  |   defaultModel: string, | ||||||
|  |   apiVersion: string, | ||||||
|  |   betaVersion: string | ||||||
|  | ): AnthropicOptions { | ||||||
|  |   return { | ||||||
|  |     // Connection settings
 | ||||||
|  |     apiKey, | ||||||
|  |     baseUrl, | ||||||
|  |     apiVersion, | ||||||
|  |     betaVersion, | ||||||
|  | 
 | ||||||
|  |     // API parameters
 | ||||||
|  |     model: opts.model || defaultModel, | ||||||
|  |     temperature: opts.temperature, | ||||||
|  |     max_tokens: opts.maxTokens, | ||||||
|  |     stream: opts.stream, | ||||||
|  |     top_p: opts.topP, | ||||||
|  | 
 | ||||||
|  |     // Internal configuration
 | ||||||
|  |     systemPrompt: opts.systemPrompt, | ||||||
|  |   }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Create Ollama options from generic options and config | ||||||
|  |  */ | ||||||
|  | export function createOllamaOptions( | ||||||
|  |   opts: ChatCompletionOptions = {}, | ||||||
|  |   baseUrl: string, | ||||||
|  |   defaultModel: string, | ||||||
|  |   contextWindow: number | ||||||
|  | ): OllamaOptions { | ||||||
|  |   return { | ||||||
|  |     // Connection settings
 | ||||||
|  |     baseUrl, | ||||||
|  | 
 | ||||||
|  |     // API parameters
 | ||||||
|  |     model: opts.model || defaultModel, | ||||||
|  |     stream: opts.stream, | ||||||
|  |     options: { | ||||||
|  |       temperature: opts.temperature, | ||||||
|  |       num_ctx: contextWindow, | ||||||
|  |       num_predict: opts.maxTokens, | ||||||
|  |       response_format: opts.expectsJsonResponse ? { type: "json_object" } : undefined | ||||||
|  |     }, | ||||||
|  |     tools: opts.tools, | ||||||
|  | 
 | ||||||
|  |     // Internal configuration
 | ||||||
|  |     systemPrompt: opts.systemPrompt, | ||||||
|  |     enableTools: opts.enableTools, | ||||||
|  |     bypassFormatter: opts.bypassFormatter, | ||||||
|  |     preserveSystemPrompt: opts.preserveSystemPrompt, | ||||||
|  |     expectsJsonResponse: opts.expectsJsonResponse, | ||||||
|  |     toolExecutionStatus: opts.toolExecutionStatus, | ||||||
|  |   }; | ||||||
|  | } | ||||||
| @ -9,6 +9,14 @@ import { OpenAIEmbeddingProvider } from "../embeddings/providers/openai.js"; | |||||||
| import { OllamaEmbeddingProvider } from "../embeddings/providers/ollama.js"; | import { OllamaEmbeddingProvider } from "../embeddings/providers/ollama.js"; | ||||||
| import { VoyageEmbeddingProvider } from "../embeddings/providers/voyage.js"; | import { VoyageEmbeddingProvider } from "../embeddings/providers/voyage.js"; | ||||||
| import type { OptionDefinitions } from "../../options_interface.js"; | import type { OptionDefinitions } from "../../options_interface.js"; | ||||||
|  | import type { ChatCompletionOptions } from '../ai_interface.js'; | ||||||
|  | import type { OpenAIOptions, AnthropicOptions, OllamaOptions, ModelMetadata } from './provider_options.js'; | ||||||
|  | import { | ||||||
|  |     createOpenAIOptions, | ||||||
|  |     createAnthropicOptions, | ||||||
|  |     createOllamaOptions | ||||||
|  | } from './provider_options.js'; | ||||||
|  | import { PROVIDER_CONSTANTS } from '../constants/provider_constants.js'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Simple local embedding provider implementation |  * Simple local embedding provider implementation | ||||||
| @ -362,3 +370,238 @@ export default { | |||||||
|     getEmbeddingProviderConfigs, |     getEmbeddingProviderConfigs, | ||||||
|     initializeDefaultProviders |     initializeDefaultProviders | ||||||
| }; | }; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Get OpenAI provider options from chat options and configuration | ||||||
|  |  * Updated to use provider metadata approach | ||||||
|  |  */ | ||||||
|  | export function getOpenAIOptions( | ||||||
|  |     opts: ChatCompletionOptions = {} | ||||||
|  | ): OpenAIOptions { | ||||||
|  |     try { | ||||||
|  |         const apiKey = options.getOption('openaiApiKey'); | ||||||
|  |         if (!apiKey) { | ||||||
|  |             throw new Error('OpenAI API key is not configured'); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         const baseUrl = options.getOption('openaiBaseUrl') || PROVIDER_CONSTANTS.OPENAI.BASE_URL; | ||||||
|  |         const modelName = opts.model || options.getOption('openaiDefaultModel') || PROVIDER_CONSTANTS.OPENAI.DEFAULT_MODEL; | ||||||
|  | 
 | ||||||
|  |         // Create provider metadata
 | ||||||
|  |         const providerMetadata: ModelMetadata = { | ||||||
|  |             provider: 'openai', | ||||||
|  |             modelId: modelName, | ||||||
|  |             displayName: modelName, | ||||||
|  |             capabilities: { | ||||||
|  |                 supportsTools: modelName.includes('gpt-4') || modelName.includes('gpt-3.5-turbo'), | ||||||
|  |                 supportsVision: modelName.includes('vision') || modelName.includes('gpt-4-turbo') || modelName.includes('gpt-4o'), | ||||||
|  |                 supportsStreaming: true | ||||||
|  |             } | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         // Get temperature from options or global setting
 | ||||||
|  |         const temperature = opts.temperature !== undefined | ||||||
|  |             ? opts.temperature | ||||||
|  |             : parseFloat(options.getOption('aiTemperature') || '0.7'); | ||||||
|  | 
 | ||||||
|  |         return { | ||||||
|  |             // Connection settings
 | ||||||
|  |             apiKey, | ||||||
|  |             baseUrl, | ||||||
|  | 
 | ||||||
|  |             // Provider metadata
 | ||||||
|  |             providerMetadata, | ||||||
|  | 
 | ||||||
|  |             // API parameters
 | ||||||
|  |             model: modelName, | ||||||
|  |             temperature, | ||||||
|  |             max_tokens: opts.maxTokens, | ||||||
|  |             stream: opts.stream, | ||||||
|  |             top_p: opts.topP, | ||||||
|  |             frequency_penalty: opts.frequencyPenalty, | ||||||
|  |             presence_penalty: opts.presencePenalty, | ||||||
|  |             tools: opts.tools, | ||||||
|  | 
 | ||||||
|  |             // Internal configuration
 | ||||||
|  |             systemPrompt: opts.systemPrompt, | ||||||
|  |             enableTools: opts.enableTools, | ||||||
|  |         }; | ||||||
|  |     } catch (error) { | ||||||
|  |         log.error(`Error creating OpenAI provider options: ${error}`); | ||||||
|  |         throw error; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Get Anthropic provider options from chat options and configuration | ||||||
|  |  * Updated to use provider metadata approach | ||||||
|  |  */ | ||||||
|  | export function getAnthropicOptions( | ||||||
|  |     opts: ChatCompletionOptions = {} | ||||||
|  | ): AnthropicOptions { | ||||||
|  |     try { | ||||||
|  |         const apiKey = options.getOption('anthropicApiKey'); | ||||||
|  |         if (!apiKey) { | ||||||
|  |             throw new Error('Anthropic API key is not configured'); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         const baseUrl = options.getOption('anthropicBaseUrl') || PROVIDER_CONSTANTS.ANTHROPIC.BASE_URL; | ||||||
|  |         const modelName = opts.model || options.getOption('anthropicDefaultModel') || PROVIDER_CONSTANTS.ANTHROPIC.DEFAULT_MODEL; | ||||||
|  | 
 | ||||||
|  |         // Create provider metadata
 | ||||||
|  |         const providerMetadata: ModelMetadata = { | ||||||
|  |             provider: 'anthropic', | ||||||
|  |             modelId: modelName, | ||||||
|  |             displayName: modelName, | ||||||
|  |             capabilities: { | ||||||
|  |                 supportsTools: modelName.includes('claude-3') || modelName.includes('claude-3.5'), | ||||||
|  |                 supportsVision: modelName.includes('claude-3') || modelName.includes('claude-3.5'), | ||||||
|  |                 supportsStreaming: true, | ||||||
|  |                 // Anthropic models typically have large context windows
 | ||||||
|  |                 contextWindow: modelName.includes('claude-3-opus') ? 200000 : | ||||||
|  |                                modelName.includes('claude-3-sonnet') ? 180000 : | ||||||
|  |                                modelName.includes('claude-3.5-sonnet') ? 200000 : 100000 | ||||||
|  |             } | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         // Get temperature from options or global setting
 | ||||||
|  |         const temperature = opts.temperature !== undefined | ||||||
|  |             ? opts.temperature | ||||||
|  |             : parseFloat(options.getOption('aiTemperature') || '0.7'); | ||||||
|  | 
 | ||||||
|  |         return { | ||||||
|  |             // Connection settings
 | ||||||
|  |             apiKey, | ||||||
|  |             baseUrl, | ||||||
|  |             apiVersion: PROVIDER_CONSTANTS.ANTHROPIC.API_VERSION, | ||||||
|  |             betaVersion: PROVIDER_CONSTANTS.ANTHROPIC.BETA_VERSION, | ||||||
|  | 
 | ||||||
|  |             // Provider metadata
 | ||||||
|  |             providerMetadata, | ||||||
|  | 
 | ||||||
|  |             // API parameters
 | ||||||
|  |             model: modelName, | ||||||
|  |             temperature, | ||||||
|  |             max_tokens: opts.maxTokens, | ||||||
|  |             stream: opts.stream, | ||||||
|  |             top_p: opts.topP, | ||||||
|  | 
 | ||||||
|  |             // Internal configuration
 | ||||||
|  |             systemPrompt: opts.systemPrompt | ||||||
|  |         }; | ||||||
|  |     } catch (error) { | ||||||
|  |         log.error(`Error creating Anthropic provider options: ${error}`); | ||||||
|  |         throw error; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Get Ollama provider options from chat options and configuration | ||||||
|  |  * This implementation cleanly separates provider information from model names | ||||||
|  |  */ | ||||||
|  | export async function getOllamaOptions( | ||||||
|  |     opts: ChatCompletionOptions = {}, | ||||||
|  |     contextWindow?: number | ||||||
|  | ): Promise<OllamaOptions> { | ||||||
|  |     try { | ||||||
|  |         const baseUrl = options.getOption('ollamaBaseUrl'); | ||||||
|  |         if (!baseUrl) { | ||||||
|  |             throw new Error('Ollama API URL is not configured'); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // Get the model name - no prefix handling needed now
 | ||||||
|  |         let modelName = opts.model || options.getOption('ollamaDefaultModel') || 'llama3'; | ||||||
|  | 
 | ||||||
|  |         // Create provider metadata
 | ||||||
|  |         const providerMetadata: ModelMetadata = { | ||||||
|  |             provider: 'ollama', | ||||||
|  |             modelId: modelName, | ||||||
|  |             capabilities: { | ||||||
|  |                 supportsTools: true, | ||||||
|  |                 supportsStreaming: true | ||||||
|  |             } | ||||||
|  |         }; | ||||||
|  | 
 | ||||||
|  |         // Get temperature from options or global setting
 | ||||||
|  |         const temperature = opts.temperature !== undefined | ||||||
|  |             ? opts.temperature | ||||||
|  |             : parseFloat(options.getOption('aiTemperature') || '0.7'); | ||||||
|  | 
 | ||||||
|  |         // Use provided context window or get from model if not specified
 | ||||||
|  |         const modelContextWindow = contextWindow || await getOllamaModelContextWindow(modelName); | ||||||
|  | 
 | ||||||
|  |         // Update capabilities with context window information
 | ||||||
|  |         providerMetadata.capabilities!.contextWindow = modelContextWindow; | ||||||
|  | 
 | ||||||
|  |         return { | ||||||
|  |             // Connection settings
 | ||||||
|  |             baseUrl, | ||||||
|  | 
 | ||||||
|  |             // Provider metadata
 | ||||||
|  |             providerMetadata, | ||||||
|  | 
 | ||||||
|  |             // API parameters
 | ||||||
|  |             model: modelName,  // Clean model name without provider prefix
 | ||||||
|  |             stream: opts.stream, | ||||||
|  |             options: { | ||||||
|  |                 temperature: opts.temperature, | ||||||
|  |                 num_ctx: modelContextWindow, | ||||||
|  |                 num_predict: opts.maxTokens, | ||||||
|  |                 response_format: opts.expectsJsonResponse ? { type: "json_object" } : undefined | ||||||
|  |             }, | ||||||
|  |             tools: opts.tools, | ||||||
|  | 
 | ||||||
|  |             // Internal configuration
 | ||||||
|  |             systemPrompt: opts.systemPrompt, | ||||||
|  |             enableTools: opts.enableTools, | ||||||
|  |             bypassFormatter: opts.bypassFormatter, | ||||||
|  |             preserveSystemPrompt: opts.preserveSystemPrompt, | ||||||
|  |             expectsJsonResponse: opts.expectsJsonResponse, | ||||||
|  |             toolExecutionStatus: opts.toolExecutionStatus, | ||||||
|  |         }; | ||||||
|  |     } catch (error) { | ||||||
|  |         log.error(`Error creating Ollama provider options: ${error}`); | ||||||
|  |         throw error; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Get context window size for Ollama model | ||||||
|  |  */ | ||||||
|  | async function getOllamaModelContextWindow(modelName: string): Promise<number> { | ||||||
|  |     try { | ||||||
|  |         const baseUrl = options.getOption('ollamaBaseUrl'); | ||||||
|  | 
 | ||||||
|  |         // Try to get model information from Ollama API
 | ||||||
|  |         const response = await fetch(`${baseUrl}/api/show`, { | ||||||
|  |             method: 'POST', | ||||||
|  |             headers: { 'Content-Type': 'application/json' }, | ||||||
|  |             body: JSON.stringify({ name: modelName }) | ||||||
|  |         }); | ||||||
|  | 
 | ||||||
|  |         if (response.ok) { | ||||||
|  |             const data = await response.json(); | ||||||
|  |             // Get context window from model parameters
 | ||||||
|  |             if (data && data.parameters && data.parameters.num_ctx) { | ||||||
|  |                 return data.parameters.num_ctx; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // Default context sizes by model family if we couldn't get specific info
 | ||||||
|  |         if (modelName.includes('llama3')) { | ||||||
|  |             return 8192; | ||||||
|  |         } else if (modelName.includes('llama2')) { | ||||||
|  |             return 4096; | ||||||
|  |         } else if (modelName.includes('mistral') || modelName.includes('mixtral')) { | ||||||
|  |             return 8192; | ||||||
|  |         } else if (modelName.includes('gemma')) { | ||||||
|  |             return 8192; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // Return a reasonable default
 | ||||||
|  |         return 4096; | ||||||
|  |     } catch (error) { | ||||||
|  |         log.info(`Error getting context window for model ${modelName}: ${error}`); | ||||||
|  |         return 4096; // Default fallback
 | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 perf3ct
						perf3ct