diff --git a/README.md b/README.md index 75ca8d6..6f63e32 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,7 @@ There are mainly 2 ways of installing Perplexica - With Docker, Without Docker. - `OPENAI`: Your OpenAI API key. **You only need to fill this if you wish to use OpenAI's models**. - `OLLAMA`: Your Ollama API URL. You should enter it as `http://host.docker.internal:PORT_NUMBER`. If you installed Ollama on port 11434, use `http://host.docker.internal:11434`. For other ports, adjust accordingly. **You need to fill this if you wish to use Ollama's models instead of OpenAI's**. - `GROQ`: Your Groq API key. **You only need to fill this if you wish to use Groq's hosted models**. + - `OPENROUTER`: Your OpenRouter API key. **You only need to fill this if you wish to use models via OpenRouter**. - `ANTHROPIC`: Your Anthropic API key. **You only need to fill this if you wish to use Anthropic models**. **Note**: You can change these after starting Perplexica from the settings dialog. diff --git a/sample.config.toml b/sample.config.toml index 03fa407..6526281 100644 --- a/sample.config.toml +++ b/sample.config.toml @@ -9,6 +9,9 @@ API_KEY = "" [MODELS.GROQ] API_KEY = "" +[MODELS.OPENROUTER] +API_KEY = "" + [MODELS.ANTHROPIC] API_KEY = "" diff --git a/src/app/api/config/route.ts b/src/app/api/config/route.ts index 193ead5..bcc4c3b 100644 --- a/src/app/api/config/route.ts +++ b/src/app/api/config/route.ts @@ -8,6 +8,7 @@ import { getGroqApiKey, getOllamaApiEndpoint, getOpenaiApiKey, + getOpenrouterApiKey, getDeepseekApiKey, getLMStudioApiEndpoint, updateConfig, @@ -62,6 +63,7 @@ export const GET = async (req: Request) => { config['anthropicApiKey'] = protectApiKey(getAnthropicApiKey()); config['geminiApiKey'] = protectApiKey(getGeminiApiKey()); config['deepseekApiKey'] = protectApiKey(getDeepseekApiKey()); + config['openrouterApiKey'] = protectApiKey(getOpenrouterApiKey()); config['customOpenaiApiKey'] = protectApiKey(getCustomOpenaiApiKey()); // Non-sensitive values remain unchanged @@ -130,6 +132,12 @@ export const POST = async (req: Request) => { LM_STUDIO: { API_URL: config.lmStudioApiUrl, }, + OPENROUTER: { + API_KEY: getUpdatedProtectedValue( + config.openrouterApiKey, + getOpenrouterApiKey(), + ), + }, CUSTOM_OPENAI: { API_URL: config.customOpenaiApiUrl, API_KEY: getUpdatedProtectedValue( diff --git a/src/app/settings/page.tsx b/src/app/settings/page.tsx index 6611f39..c3813d1 100644 --- a/src/app/settings/page.tsx +++ b/src/app/settings/page.tsx @@ -28,6 +28,7 @@ interface SettingsType { }; openaiApiKey: string; groqApiKey: string; + openrouterApiKey: string; anthropicApiKey: string; geminiApiKey: string; ollamaApiUrl: string; @@ -1352,6 +1353,25 @@ export default function SettingsPage() { /> +
+ OpenRouter API Key +
+
Anthropic API Key
diff --git a/src/lib/config.ts b/src/lib/config.ts
index 143ee28..55bcadf 100644
--- a/src/lib/config.ts
+++ b/src/lib/config.ts
@@ -39,6 +39,9 @@ interface Config {
LM_STUDIO: {
API_URL: string;
};
+ OPENROUTER: {
+ API_KEY: string;
+ };
CUSTOM_OPENAI: {
API_URL: string;
API_KEY: string;
@@ -77,6 +80,8 @@ export const getOpenaiApiKey = () => loadConfig().MODELS.OPENAI.API_KEY;
export const getGroqApiKey = () => loadConfig().MODELS.GROQ.API_KEY;
+export const getOpenrouterApiKey = () => loadConfig().MODELS.OPENROUTER.API_KEY;
+
export const getAnthropicApiKey = () => loadConfig().MODELS.ANTHROPIC.API_KEY;
export const getGeminiApiKey = () => loadConfig().MODELS.GEMINI.API_KEY;
diff --git a/src/lib/providers/index.ts b/src/lib/providers/index.ts
index 04ad82f..d65bea0 100644
--- a/src/lib/providers/index.ts
+++ b/src/lib/providers/index.ts
@@ -40,6 +40,10 @@ import {
loadLMStudioEmbeddingsModels,
PROVIDER_INFO as LMStudioInfo,
} from './lmstudio';
+import {
+ loadOpenrouterChatModels,
+ PROVIDER_INFO as OpenRouterInfo,
+} from './openrouter';
export const PROVIDER_METADATA = {
openai: OpenAIInfo,
@@ -50,6 +54,7 @@ export const PROVIDER_METADATA = {
transformers: TransformersInfo,
deepseek: DeepseekInfo,
lmstudio: LMStudioInfo,
+ openrouter: OpenRouterInfo,
custom_openai: {
key: 'custom_openai',
displayName: 'Custom OpenAI',
@@ -77,6 +82,7 @@ export const chatModelProviders: Record<
gemini: loadGeminiChatModels,
deepseek: loadDeepseekChatModels,
lmstudio: loadLMStudioChatModels,
+ openrouter: loadOpenrouterChatModels,
};
export const embeddingModelProviders: Record<
diff --git a/src/lib/providers/openrouter.ts b/src/lib/providers/openrouter.ts
new file mode 100644
index 0000000..ef7110d
--- /dev/null
+++ b/src/lib/providers/openrouter.ts
@@ -0,0 +1,65 @@
+export const PROVIDER_INFO = {
+ key: 'openrouter',
+ displayName: 'OpenRouter',
+};
+import { ChatOpenAI } from '@langchain/openai';
+import { getOpenrouterApiKey } from '../config';
+import { ChatModel } from '.';
+import { BaseChatModel } from '@langchain/core/language_models/chat_models';
+
+let openrouterChatModels: Record