From e00264236ec9e853357da788291c20de7835c342 Mon Sep 17 00:00:00 2001 From: Arsalaan Ahmed <147995884+Ahmed-Rahil@users.noreply.github.com> Date: Mon, 30 Dec 2024 23:26:33 +0530 Subject: [PATCH] feat: added hyperbolic llm models (#943) * Added Hyperbolic Models * Fix: Fixed problem in connecting with hyperbolic models * added dynamic models for hyperbolic * removed logs --- .env.example | 6 + app/lib/modules/llm/providers/hyperbolic.ts | 117 ++++++++++++++++++++ app/lib/modules/llm/registry.ts | 2 + package.json | 1 + pnpm-lock.yaml | 13 ++- 5 files changed, 134 insertions(+), 5 deletions(-) create mode 100644 app/lib/modules/llm/providers/hyperbolic.ts diff --git a/.env.example b/.env.example index 4e4b4f33..6f2f5f5a 100644 --- a/.env.example +++ b/.env.example @@ -51,6 +51,12 @@ OPENAI_LIKE_API_KEY= # Get your Together API Key TOGETHER_API_KEY= +# You only need this environment variable set if you want to use Hyperbolic models +#Get your Hyperbolics API Key at https://app.hyperbolic.xyz/settings +#baseURL="https://api.hyperbolic.xyz/v1/chat/completions" +HYPERBOLIC_API_KEY= +HYPERBOLIC_API_BASE_URL= + # Get your Mistral API Key by following these instructions - # https://console.mistral.ai/api-keys/ # You only need this environment variable set if you want to use Mistral models diff --git a/app/lib/modules/llm/providers/hyperbolic.ts b/app/lib/modules/llm/providers/hyperbolic.ts new file mode 100644 index 00000000..88c943ca --- /dev/null +++ b/app/lib/modules/llm/providers/hyperbolic.ts @@ -0,0 +1,117 @@ +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 { createOpenAI } from '@ai-sdk/openai'; + +export default class HyperbolicProvider extends BaseProvider { + name = 'Hyperbolic'; + getApiKeyLink = 'https://hyperbolic.xyz/settings'; + + config = { + apiTokenKey: 'HYPERBOLIC_API_KEY', + }; + + staticModels: ModelInfo[] = [ + { + name: 'Qwen/Qwen2.5-Coder-32B-Instruct', + label: 'Qwen 2.5 Coder 32B Instruct', + provider: 'Hyperbolic', + maxTokenAllowed: 8192, + }, + { + name: 'Qwen/Qwen2.5-72B-Instruct', + label: 'Qwen2.5-72B-Instruct', + provider: 'Hyperbolic', + maxTokenAllowed: 8192, + }, + { + name: 'deepseek-ai/DeepSeek-V2.5', + label: 'DeepSeek-V2.5', + provider: 'Hyperbolic', + maxTokenAllowed: 8192, + }, + { + name: 'Qwen/QwQ-32B-Preview', + label: 'QwQ-32B-Preview', + provider: 'Hyperbolic', + maxTokenAllowed: 8192, + }, + { + name: 'Qwen/Qwen2-VL-72B-Instruct', + label: 'Qwen2-VL-72B-Instruct', + provider: 'Hyperbolic', + maxTokenAllowed: 8192, + }, + ]; + + async getDynamicModels( + apiKeys?: Record, + settings?: IProviderSetting, + serverEnv: Record = {}, + ): Promise { + try { + const { baseUrl: fetchBaseUrl, apiKey } = this.getProviderBaseUrlAndKey({ + apiKeys, + providerSettings: settings, + serverEnv, + defaultBaseUrlKey: '', + defaultApiTokenKey: 'HYPERBOLIC_API_KEY', + }); + const baseUrl = fetchBaseUrl || 'https://api.hyperbolic.xyz/v1'; + + if (!baseUrl || !apiKey) { + return []; + } + + const response = await fetch(`${baseUrl}/models`, { + headers: { + Authorization: `Bearer ${apiKey}`, + }, + }); + + const res = (await response.json()) as any; + + const data = res.data.filter((model: any) => model.object === 'model' && model.supports_chat); + + return data.map((m: any) => ({ + name: m.id, + label: `${m.id} - context ${m.context_length ? Math.floor(m.context_length / 1000) + 'k' : 'N/A'}`, + provider: this.name, + maxTokenAllowed: m.context_length || 8000, + })); + } catch (error: any) { + console.error('Error getting Hyperbolic models:', error.message); + return []; + } + } + + getModelInstance(options: { + model: string; + serverEnv: Env; + apiKeys?: Record; + providerSettings?: Record; + }): LanguageModelV1 { + const { model, serverEnv, apiKeys, providerSettings } = options; + + const { apiKey } = this.getProviderBaseUrlAndKey({ + apiKeys, + providerSettings: providerSettings?.[this.name], + serverEnv: serverEnv as any, + defaultBaseUrlKey: '', + defaultApiTokenKey: 'HYPERBOLIC_API_KEY', + }); + + if (!apiKey) { + console.log(`Missing configuration for ${this.name} provider`); + throw new Error(`Missing configuration for ${this.name} provider`); + } + + const openai = createOpenAI({ + baseURL: 'https://api.hyperbolic.xyz/v1/', + apiKey, + }); + + return openai(model); + } +} diff --git a/app/lib/modules/llm/registry.ts b/app/lib/modules/llm/registry.ts index fb5a31f9..c002eb88 100644 --- a/app/lib/modules/llm/registry.ts +++ b/app/lib/modules/llm/registry.ts @@ -13,6 +13,7 @@ import OpenAIProvider from './providers/openai'; import PerplexityProvider from './providers/perplexity'; import TogetherProvider from './providers/together'; import XAIProvider from './providers/xai'; +import HyperbolicProvider from './providers/hyperbolic'; export { AnthropicProvider, @@ -21,6 +22,7 @@ export { GoogleProvider, GroqProvider, HuggingFaceProvider, + HyperbolicProvider, MistralProvider, OllamaProvider, OpenAIProvider, diff --git a/package.json b/package.json index 05d483b9..19c83531 100644 --- a/package.json +++ b/package.json @@ -76,6 +76,7 @@ "ai": "^4.0.13", "date-fns": "^3.6.0", "diff": "^5.2.0", + "dotenv": "^16.4.7", "file-saver": "^2.0.5", "framer-motion": "^11.12.0", "ignore": "^6.0.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index da73295a..a78cfef3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -149,6 +149,9 @@ importers: diff: specifier: ^5.2.0 version: 5.2.0 + dotenv: + specifier: ^16.4.7 + version: 16.4.7 file-saver: specifier: ^2.0.5 version: 2.0.5 @@ -2901,8 +2904,8 @@ packages: resolution: {integrity: sha512-IGBwjF7tNk3cwypFNH/7bfzBcgSCbaMOD3GsaY1AU/JRrnHnYgEM0+9kQt52iZxjNsjBtJYtao146V+f8jFZNw==} engines: {node: '>=10'} - dotenv@16.4.5: - resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} + dotenv@16.4.7: + resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==} engines: {node: '>=12'} duplexer@0.1.2: @@ -7246,7 +7249,7 @@ snapshots: chalk: 4.1.2 chokidar: 3.6.0 cross-spawn: 7.0.6 - dotenv: 16.4.5 + dotenv: 16.4.7 es-module-lexer: 1.5.4 esbuild: 0.17.6 esbuild-plugins-node-modules-polyfill: 1.6.8(esbuild@0.17.6) @@ -8450,7 +8453,7 @@ snapshots: domain-browser@4.22.0: {} - dotenv@16.4.5: {} + dotenv@16.4.7: {} duplexer@0.1.2: {} @@ -11957,4 +11960,4 @@ snapshots: zod@3.23.8: {} - zwitch@2.0.4: {} \ No newline at end of file + zwitch@2.0.4: {}