Spaces:
Running
Running
import { BaseProvider } from '~/lib/modules/llm/base-provider'; | |
import type { ModelInfo } from '~/lib/modules/llm/types'; | |
import type { IProviderSetting } from '~/types/model'; | |
import type { LanguageModelV1 } from 'ai'; | |
import { createOpenRouter } from '@openrouter/ai-sdk-provider'; | |
interface OpenRouterModel { | |
name: string; | |
id: string; | |
context_length: number; | |
pricing: { | |
prompt: number; | |
completion: number; | |
}; | |
} | |
interface OpenRouterModelsResponse { | |
data: OpenRouterModel[]; | |
} | |
export default class OpenRouterProvider extends BaseProvider { | |
name = 'OpenRouter'; | |
getApiKeyLink = 'https://openrouter.ai/settings/keys'; | |
config = { | |
apiTokenKey: 'OPEN_ROUTER_API_KEY', | |
}; | |
staticModels: ModelInfo[] = [ | |
{ | |
name: 'anthropic/claude-3.5-sonnet', | |
label: 'Anthropic: Claude 3.5 Sonnet (OpenRouter)', | |
provider: 'OpenRouter', | |
maxTokenAllowed: 8000, | |
}, | |
{ | |
name: 'anthropic/claude-3-haiku', | |
label: 'Anthropic: Claude 3 Haiku (OpenRouter)', | |
provider: 'OpenRouter', | |
maxTokenAllowed: 8000, | |
}, | |
{ | |
name: 'deepseek/deepseek-coder', | |
label: 'Deepseek-Coder V2 236B (OpenRouter)', | |
provider: 'OpenRouter', | |
maxTokenAllowed: 8000, | |
}, | |
{ | |
name: 'google/gemini-flash-1.5', | |
label: 'Google Gemini Flash 1.5 (OpenRouter)', | |
provider: 'OpenRouter', | |
maxTokenAllowed: 8000, | |
}, | |
{ | |
name: 'google/gemini-pro-1.5', | |
label: 'Google Gemini Pro 1.5 (OpenRouter)', | |
provider: 'OpenRouter', | |
maxTokenAllowed: 8000, | |
}, | |
{ name: 'x-ai/grok-beta', label: 'xAI Grok Beta (OpenRouter)', provider: 'OpenRouter', maxTokenAllowed: 8000 }, | |
{ | |
name: 'mistralai/mistral-nemo', | |
label: 'OpenRouter Mistral Nemo (OpenRouter)', | |
provider: 'OpenRouter', | |
maxTokenAllowed: 8000, | |
}, | |
{ | |
name: 'qwen/qwen-110b-chat', | |
label: 'OpenRouter Qwen 110b Chat (OpenRouter)', | |
provider: 'OpenRouter', | |
maxTokenAllowed: 8000, | |
}, | |
{ name: 'cohere/command', label: 'Cohere Command (OpenRouter)', provider: 'OpenRouter', maxTokenAllowed: 4096 }, | |
]; | |
async getDynamicModels( | |
_apiKeys?: Record<string, string>, | |
_settings?: IProviderSetting, | |
_serverEnv: Record<string, string> = {}, | |
): Promise<ModelInfo[]> { | |
try { | |
const response = await fetch('https://openrouter.ai/api/v1/models', { | |
headers: { | |
'Content-Type': 'application/json', | |
}, | |
}); | |
const data = (await response.json()) as OpenRouterModelsResponse; | |
return data.data | |
.sort((a, b) => a.name.localeCompare(b.name)) | |
.map((m) => ({ | |
name: m.id, | |
label: `${m.name} - in:$${(m.pricing.prompt * 1_000_000).toFixed(2)} out:$${(m.pricing.completion * 1_000_000).toFixed(2)} - context ${Math.floor(m.context_length / 1000)}k`, | |
provider: this.name, | |
maxTokenAllowed: 8000, | |
})); | |
} catch (error) { | |
console.error('Error getting OpenRouter models:', error); | |
return []; | |
} | |
} | |
getModelInstance(options: { | |
model: string; | |
serverEnv: Env; | |
apiKeys?: Record<string, string>; | |
providerSettings?: Record<string, IProviderSetting>; | |
}): LanguageModelV1 { | |
const { model, serverEnv, apiKeys, providerSettings } = options; | |
const { apiKey } = this.getProviderBaseUrlAndKey({ | |
apiKeys, | |
providerSettings: providerSettings?.[this.name], | |
serverEnv: serverEnv as any, | |
defaultBaseUrlKey: '', | |
defaultApiTokenKey: 'OPEN_ROUTER_API_KEY', | |
}); | |
if (!apiKey) { | |
throw new Error(`Missing API key for ${this.name} provider`); | |
} | |
const openRouter = createOpenRouter({ | |
apiKey, | |
}); | |
const instance = openRouter.chat(model) as LanguageModelV1; | |
return instance; | |
} | |
} | |