mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 11:39:01 +01:00 
			
		
		
		
	anthropic works
This commit is contained in:
		
							parent
							
								
									654ed4706e
								
							
						
					
					
						commit
						44b6734034
					
				| @ -3,6 +3,21 @@ import options from "../../services/options.js"; | ||||
| import log from "../../services/log.js"; | ||||
| import type { Request, Response } from "express"; | ||||
| 
 | ||||
| // Map of simplified model names to full model names with versions
 | ||||
| const MODEL_MAPPING: Record<string, string> = { | ||||
|     'claude-3-opus': 'claude-3-opus-20240229', | ||||
|     'claude-3-sonnet': 'claude-3-sonnet-20240229', | ||||
|     'claude-3-haiku': 'claude-3-haiku-20240307', | ||||
|     'claude-2': 'claude-2.1' | ||||
| }; | ||||
| 
 | ||||
| // Interface for Anthropic model entries
 | ||||
| interface AnthropicModel { | ||||
|     id: string; | ||||
|     name: string; | ||||
|     type: string; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * List available models from Anthropic | ||||
|  */ | ||||
| @ -10,20 +25,26 @@ async function listModels(req: Request, res: Response) { | ||||
|     try { | ||||
|         const { baseUrl } = req.body; | ||||
| 
 | ||||
|         // Use provided base URL or default from options
 | ||||
|         const anthropicBaseUrl = baseUrl || await options.getOption('anthropicBaseUrl') || 'https://api.anthropic.com/v1'; | ||||
|         // Use provided base URL or default from options, and ensure correct formatting
 | ||||
|         let anthropicBaseUrl = baseUrl || await options.getOption('anthropicBaseUrl') || 'https://api.anthropic.com'; | ||||
|         // Ensure base URL doesn't already include '/v1' and is properly formatted
 | ||||
|         anthropicBaseUrl = anthropicBaseUrl.replace(/\/+$/, '').replace(/\/v1$/, ''); | ||||
| 
 | ||||
|         const apiKey = await options.getOption('anthropicApiKey'); | ||||
| 
 | ||||
|         if (!apiKey) { | ||||
|             throw new Error('Anthropic API key is not configured'); | ||||
|         } | ||||
| 
 | ||||
|         log.info(`Listing models from Anthropic API at: ${anthropicBaseUrl}/v1/models`); | ||||
| 
 | ||||
|         // Call Anthropic API to get models
 | ||||
|         const response = await axios.get(`${anthropicBaseUrl}/models`, { | ||||
|         const response = await axios.get(`${anthropicBaseUrl}/v1/models`, { | ||||
|             headers: { | ||||
|                 'Content-Type': 'application/json', | ||||
|                 'x-api-key': apiKey, | ||||
|                 'anthropic-version': '2023-06-01' | ||||
|                 'X-Api-Key': apiKey, | ||||
|                 'anthropic-version': '2023-06-01', | ||||
|                 'anthropic-beta': 'messages-2023-12-15' | ||||
|             }, | ||||
|             timeout: 10000 | ||||
|         }); | ||||
| @ -31,17 +52,41 @@ async function listModels(req: Request, res: Response) { | ||||
|         // Process the models
 | ||||
|         const allModels = response.data.models || []; | ||||
| 
 | ||||
|         // Log available models
 | ||||
|         log.info(`Found ${allModels.length} models from Anthropic: ${allModels.map((m: any) => m.id).join(', ')}`); | ||||
| 
 | ||||
|         // Separate models into chat models and embedding models
 | ||||
|         const chatModels = allModels | ||||
|             .filter((model: any) => | ||||
|                 // Claude models are for chat
 | ||||
|                 model.id.includes('claude') | ||||
|             ) | ||||
|             .map((model: any) => ({ | ||||
|                 id: model.id, | ||||
|                 name: model.id, | ||||
|                 type: 'chat' | ||||
|             })); | ||||
|             .map((model: any) => { | ||||
|                 // Get a simplified name for display purposes
 | ||||
|                 let displayName = model.id; | ||||
|                 // Try to simplify the model name by removing version suffixes
 | ||||
|                 if (model.id.match(/claude-\d+-\w+-\d+/)) { | ||||
|                     displayName = model.id.replace(/-\d+$/, ''); | ||||
|                 } | ||||
| 
 | ||||
|                 return { | ||||
|                     id: model.id,      // Keep full ID for API calls
 | ||||
|                     name: displayName, // Use simplified name for display
 | ||||
|                     type: 'chat' | ||||
|                 }; | ||||
|             }); | ||||
| 
 | ||||
|         // Also include known models that might not be returned by the API
 | ||||
|         for (const [simpleName, fullName] of Object.entries(MODEL_MAPPING)) { | ||||
|             // Check if this model is already in our list
 | ||||
|             if (!chatModels.some((m: AnthropicModel) => m.id === fullName)) { | ||||
|                 chatModels.push({ | ||||
|                     id: fullName, | ||||
|                     name: simpleName, | ||||
|                     type: 'chat' | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         // Note: Anthropic might not have embedding models yet, but we'll include this for future compatibility
 | ||||
|         const embeddingModels = allModels | ||||
|  | ||||
| @ -3,6 +3,14 @@ import { BaseAIService } from '../base_ai_service.js'; | ||||
| import type { ChatCompletionOptions, ChatResponse, Message } from '../ai_interface.js'; | ||||
| 
 | ||||
| export class AnthropicService extends BaseAIService { | ||||
|     // Map of simplified model names to full model names with versions
 | ||||
|     private static MODEL_MAPPING: Record<string, string> = { | ||||
|         'claude-3-opus': 'claude-3-opus-20240229', | ||||
|         'claude-3-sonnet': 'claude-3-sonnet-20240229', | ||||
|         'claude-3-haiku': 'claude-3-haiku-20240307', | ||||
|         'claude-2': 'claude-2.1' | ||||
|     }; | ||||
| 
 | ||||
|     constructor() { | ||||
|         super('Anthropic'); | ||||
|     } | ||||
| @ -18,7 +26,14 @@ export class AnthropicService extends BaseAIService { | ||||
| 
 | ||||
|         const apiKey = options.getOption('anthropicApiKey'); | ||||
|         const baseUrl = options.getOption('anthropicBaseUrl') || 'https://api.anthropic.com'; | ||||
|         const model = opts.model || options.getOption('anthropicDefaultModel') || 'claude-3-haiku-20240307'; | ||||
|         let model = opts.model || options.getOption('anthropicDefaultModel') || 'claude-3-haiku-20240307'; | ||||
| 
 | ||||
|         // Apply model name mapping if needed
 | ||||
|         if (AnthropicService.MODEL_MAPPING[model]) { | ||||
|             model = AnthropicService.MODEL_MAPPING[model]; | ||||
|             console.log(`Mapped model name to: ${model}`); | ||||
|         } | ||||
| 
 | ||||
|         const temperature = opts.temperature !== undefined | ||||
|             ? opts.temperature | ||||
|             : parseFloat(options.getOption('aiTemperature') || '0.7'); | ||||
| @ -29,14 +44,20 @@ export class AnthropicService extends BaseAIService { | ||||
|         const formattedMessages = this.formatMessages(messages, systemPrompt); | ||||
| 
 | ||||
|         try { | ||||
|             const endpoint = `${baseUrl.replace(/\/+$/, '')}/v1/messages`; | ||||
|             // Ensure base URL doesn't already include '/v1' and build the complete endpoint
 | ||||
|             const cleanBaseUrl = baseUrl.replace(/\/+$/, '').replace(/\/v1$/, ''); | ||||
|             const endpoint = `${cleanBaseUrl}/v1/messages`; | ||||
| 
 | ||||
|             console.log(`Anthropic API endpoint: ${endpoint}`); | ||||
|             console.log(`Using model: ${model}`); | ||||
| 
 | ||||
|             const response = await fetch(endpoint, { | ||||
|                 method: 'POST', | ||||
|                 headers: { | ||||
|                     'Content-Type': 'application/json', | ||||
|                     'x-api-key': apiKey, | ||||
|                     'anthropic-version': '2023-06-01' | ||||
|                     'X-Api-Key': apiKey, | ||||
|                     'anthropic-version': '2023-06-01', | ||||
|                     'anthropic-beta': 'messages-2023-12-15' | ||||
|                 }, | ||||
|                 body: JSON.stringify({ | ||||
|                     model, | ||||
| @ -49,6 +70,7 @@ export class AnthropicService extends BaseAIService { | ||||
| 
 | ||||
|             if (!response.ok) { | ||||
|                 const errorBody = await response.text(); | ||||
|                 console.error(`Anthropic API error (${response.status}): ${errorBody}`); | ||||
|                 throw new Error(`Anthropic API error: ${response.status} ${response.statusText} - ${errorBody}`); | ||||
|             } | ||||
| 
 | ||||
| @ -82,7 +104,7 @@ export class AnthropicService extends BaseAIService { | ||||
| 
 | ||||
|         // Format remaining messages for Anthropic's API
 | ||||
|         const formattedMessages = nonSystemMessages.map(m => ({ | ||||
|             role: m.role, | ||||
|             role: m.role === 'user' ? 'user' : 'assistant', | ||||
|             content: m.content | ||||
|         })); | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 perf3ct
						perf3ct