From 54ba5eafa18febd3331c819eca12a2f72bb08569 Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Sat, 15 Feb 2025 16:49:03 -0500 Subject: [PATCH] feat: OpenRouter Agent Reasoning --- api/app/clients/OpenAIClient.js | 7 ++----- api/package.json | 2 +- api/server/controllers/agents/client.js | 20 +------------------ api/server/controllers/agents/run.js | 10 +++++++++- .../services/Endpoints/agents/initialize.js | 7 ++++--- api/server/services/Endpoints/openAI/llm.js | 8 ++++---- package-lock.json | 8 ++++---- 7 files changed, 25 insertions(+), 37 deletions(-) diff --git a/api/app/clients/OpenAIClient.js b/api/app/clients/OpenAIClient.js index 368e7d6e84b..7bd7879dcfb 100644 --- a/api/app/clients/OpenAIClient.js +++ b/api/app/clients/OpenAIClient.js @@ -7,6 +7,7 @@ const { ImageDetail, EModelEndpoint, resolveHeaders, + KnownEndpoints, openAISettings, ImageDetailCost, CohereConstants, @@ -116,11 +117,7 @@ class OpenAIClient extends BaseClient { const { reverseProxyUrl: reverseProxy } = this.options; - if ( - !this.useOpenRouter && - reverseProxy && - reverseProxy.includes('https://openrouter.ai/api/v1') - ) { + if (!this.useOpenRouter && reverseProxy && reverseProxy.includes(KnownEndpoints.openrouter)) { this.useOpenRouter = true; } diff --git a/api/package.json b/api/package.json index 2cac1c6df6e..e000dd8bd00 100644 --- a/api/package.json +++ b/api/package.json @@ -45,7 +45,7 @@ "@langchain/google-genai": "^0.1.7", "@langchain/google-vertexai": "^0.1.8", "@langchain/textsplitters": "^0.1.0", - "@librechat/agents": "^2.1.0", + "@librechat/agents": "^2.1.2", "@waylaidwanderer/fetch-event-source": "^3.0.1", "axios": "1.7.8", "bcryptjs": "^2.4.3", diff --git a/api/server/controllers/agents/client.js b/api/server/controllers/agents/client.js index a8e9ad82f7b..156424e0351 100644 --- a/api/server/controllers/agents/client.js +++ b/api/server/controllers/agents/client.js @@ -20,11 +20,6 @@ const { bedrockOutputParser, removeNullishValues, } = require('librechat-data-provider'); -const { - extractBaseURL, - // constructAzureURL, - // genAzureChatCompletion, -} = require('~/utils'); const { formatMessage, formatAgentMessages, @@ -477,19 +472,6 @@ class AgentClient extends BaseClient { abortController = new AbortController(); } - const baseURL = extractBaseURL(this.completionsUrl); - logger.debug('[api/server/controllers/agents/client.js] chatCompletion', { - baseURL, - payload, - }); - - // if (this.useOpenRouter) { - // opts.defaultHeaders = { - // 'HTTP-Referer': 'https://librechat.ai', - // 'X-Title': 'LibreChat', - // }; - // } - // if (this.options.headers) { // opts.defaultHeaders = { ...opts.defaultHeaders, ...this.options.headers }; // } @@ -626,7 +608,7 @@ class AgentClient extends BaseClient { let systemContent = [ systemMessage, agent.instructions ?? '', - i !== 0 ? agent.additional_instructions ?? '' : '', + i !== 0 ? (agent.additional_instructions ?? '') : '', ] .join('\n') .trim(); diff --git a/api/server/controllers/agents/run.js b/api/server/controllers/agents/run.js index 0fcc58a3792..346b9e6df88 100644 --- a/api/server/controllers/agents/run.js +++ b/api/server/controllers/agents/run.js @@ -1,5 +1,5 @@ const { Run, Providers } = require('@librechat/agents'); -const { providerEndpointMap } = require('librechat-data-provider'); +const { providerEndpointMap, KnownEndpoints } = require('librechat-data-provider'); /** * @typedef {import('@librechat/agents').t} t @@ -7,6 +7,7 @@ const { providerEndpointMap } = require('librechat-data-provider'); * @typedef {import('@librechat/agents').StreamEventData} StreamEventData * @typedef {import('@librechat/agents').EventHandler} EventHandler * @typedef {import('@librechat/agents').GraphEvents} GraphEvents + * @typedef {import('@librechat/agents').LLMConfig} LLMConfig * @typedef {import('@librechat/agents').IState} IState */ @@ -32,6 +33,7 @@ async function createRun({ streamUsage = true, }) { const provider = providerEndpointMap[agent.provider] ?? agent.provider; + /** @type {LLMConfig} */ const llmConfig = Object.assign( { provider, @@ -41,6 +43,11 @@ async function createRun({ agent.model_parameters, ); + /** @type {'reasoning_content' | 'reasoning'} */ + let reasoningKey; + if (llmConfig.configuration?.baseURL.includes(KnownEndpoints.openrouter)) { + reasoningKey = 'reasoning'; + } if (/o1(?!-(?:mini|preview)).*$/.test(llmConfig.model)) { llmConfig.streaming = false; llmConfig.disableStreaming = true; @@ -50,6 +57,7 @@ async function createRun({ const graphConfig = { signal, llmConfig, + reasoningKey, tools: agent.tools, instructions: agent.instructions, additional_instructions: agent.additional_instructions, diff --git a/api/server/services/Endpoints/agents/initialize.js b/api/server/services/Endpoints/agents/initialize.js index e2329383e6b..1726ef34601 100644 --- a/api/server/services/Endpoints/agents/initialize.js +++ b/api/server/services/Endpoints/agents/initialize.js @@ -22,13 +22,14 @@ const { getAgent } = require('~/models/Agent'); const { logger } = require('~/config'); const providerConfigMap = { + [Providers.OLLAMA]: initCustom, + [Providers.DEEPSEEK]: initCustom, + [Providers.OPENROUTER]: initCustom, [EModelEndpoint.openAI]: initOpenAI, + [EModelEndpoint.google]: initGoogle, [EModelEndpoint.azureOpenAI]: initOpenAI, [EModelEndpoint.anthropic]: initAnthropic, [EModelEndpoint.bedrock]: getBedrockOptions, - [EModelEndpoint.google]: initGoogle, - [Providers.OLLAMA]: initCustom, - [Providers.DEEPSEEK]: initCustom, }; /** diff --git a/api/server/services/Endpoints/openAI/llm.js b/api/server/services/Endpoints/openAI/llm.js index 2587b242c99..05b08b284b6 100644 --- a/api/server/services/Endpoints/openAI/llm.js +++ b/api/server/services/Endpoints/openAI/llm.js @@ -1,4 +1,5 @@ const { HttpsProxyAgent } = require('https-proxy-agent'); +const { KnownEndpoints } = require('librechat-data-provider'); const { sanitizeModelName, constructAzureURL } = require('~/utils'); const { isEnabled } = require('~/server/utils'); @@ -57,10 +58,9 @@ function getLLMConfig(apiKey, options = {}) { /** @type {OpenAIClientOptions['configuration']} */ const configOptions = {}; - - // Handle OpenRouter or custom reverse proxy - if (useOpenRouter || reverseProxyUrl === 'https://openrouter.ai/api/v1') { - configOptions.baseURL = 'https://openrouter.ai/api/v1'; + if (useOpenRouter || reverseProxyUrl.includes(KnownEndpoints.openrouter)) { + llmConfig.include_reasoning = true; + configOptions.baseURL = reverseProxyUrl; configOptions.defaultHeaders = Object.assign( { 'HTTP-Referer': 'https://librechat.ai', diff --git a/package-lock.json b/package-lock.json index 882a8dbf2f9..dfae230c574 100644 --- a/package-lock.json +++ b/package-lock.json @@ -61,7 +61,7 @@ "@langchain/google-genai": "^0.1.7", "@langchain/google-vertexai": "^0.1.8", "@langchain/textsplitters": "^0.1.0", - "@librechat/agents": "^2.1.0", + "@librechat/agents": "^2.1.2", "@waylaidwanderer/fetch-event-source": "^3.0.1", "axios": "1.7.8", "bcryptjs": "^2.4.3", @@ -11529,9 +11529,9 @@ } }, "node_modules/@librechat/agents": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@librechat/agents/-/agents-2.1.0.tgz", - "integrity": "sha512-ZdxO6lQOH3C0HIAJDXIx0c3i+Mc8P5riv+lfTVJNu6ZcN5laOBOvFmAtMGOgq563tAC8LM0YbCJJKkJbUocBrw==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@librechat/agents/-/agents-2.1.2.tgz", + "integrity": "sha512-OYGIX4qJAcd++sdtYDVW31QSpnJjsK90Bks7hASxbyegy6WRVU3LUd6/ko0gRv0O7RUVE98/wtly3Q3qLbEz1w==", "dependencies": { "@aws-crypto/sha256-js": "^5.2.0", "@aws-sdk/credential-provider-node": "^3.613.0",