🔍 feat: Anthropic/Google Web Search Support via addParams / dropParams (#10456)

* feat: add support for known/add/drop parameters in Anthropic and Google LLM configurations

* ci: add tests for web search support for Anthropic and Google configurations with addParams and dropParams handling
This commit is contained in:
Danny Avila 2025-11-11 14:39:12 -05:00 committed by GitHub
parent 4685a063f5
commit 2b0fe036a8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 521 additions and 8 deletions

View file

@ -4,6 +4,25 @@ import { anthropicSettings, removeNullishValues } from 'librechat-data-provider'
import type { AnthropicLLMConfigResult, AnthropicConfigOptions } from '~/types/anthropic';
import { checkPromptCacheSupport, getClaudeHeaders, configureReasoning } from './helpers';
/** Known Anthropic parameters that map directly to the client config */
export const knownAnthropicParams = new Set([
'model',
'temperature',
'topP',
'topK',
'maxTokens',
'maxOutputTokens',
'stopSequences',
'stop',
'stream',
'apiKey',
'maxRetries',
'timeout',
'anthropicVersion',
'anthropicApiUrl',
'defaultHeaders',
]);
/**
* Generates configuration options for creating an Anthropic language model (LLM) instance.
* @param apiKey - The API key for authentication with Anthropic.
@ -39,6 +58,8 @@ function getLLMConfig(
const mergedOptions = Object.assign(defaultOptions, options.modelOptions);
let enableWebSearch = mergedOptions.web_search;
let requestOptions: AnthropicClientOptions & { stream?: boolean } = {
apiKey,
model: mergedOptions.model,
@ -84,9 +105,45 @@ function getLLMConfig(
requestOptions.anthropicApiUrl = options.reverseProxyUrl;
}
/** Handle addParams - only process Anthropic-native params, leave OpenAI params for transform */
if (options.addParams && typeof options.addParams === 'object') {
for (const [key, value] of Object.entries(options.addParams)) {
/** Handle web_search separately - don't add to config */
if (key === 'web_search') {
if (typeof value === 'boolean') {
enableWebSearch = value;
}
continue;
}
if (knownAnthropicParams.has(key)) {
/** Route known Anthropic params to requestOptions */
(requestOptions as Record<string, unknown>)[key] = value;
}
/** Leave other params for transform to handle - they might be OpenAI params */
}
}
/** Handle dropParams - only drop from Anthropic config */
if (options.dropParams && Array.isArray(options.dropParams)) {
options.dropParams.forEach((param) => {
if (param === 'web_search') {
enableWebSearch = false;
return;
}
if (param in requestOptions) {
delete requestOptions[param as keyof AnthropicClientOptions];
}
if (requestOptions.invocationKwargs && param in requestOptions.invocationKwargs) {
delete (requestOptions.invocationKwargs as Record<string, unknown>)[param];
}
});
}
const tools = [];
if (mergedOptions.web_search) {
if (enableWebSearch) {
tools.push({
type: 'web_search_20250305',
name: 'web_search',