🧠 feat: Add reasoning_effort configuration for Bedrock models (#11991)
Some checks are pending
Docker Dev Branch Images Build / build (Dockerfile, lc-dev, node) (push) Waiting to run
Docker Dev Branch Images Build / build (Dockerfile.multi, lc-dev-api, api-build) (push) Waiting to run

* 🧠 feat: Add reasoning_effort configuration for Bedrock models

- Introduced a new `reasoning_effort` setting in the Bedrock configuration, allowing users to specify the reasoning level for supported models.
- Updated the input parser to map `reasoning_effort` to `reasoning_config` for Moonshot and ZAI models, ensuring proper handling of reasoning levels.
- Enhanced tests to validate the mapping of `reasoning_effort` to `reasoning_config` and to ensure correct behavior for various model types, including Anthropic models.
- Updated translation files to include descriptions for the new configuration option.

* chore: Update translation keys for Bedrock reasoning configuration

- Renamed translation key from `com_endpoint_bedrock_reasoning_config` to `com_endpoint_bedrock_reasoning_effort` for consistency with the new configuration setting.
- Updated the parameter settings to reflect the change in the description key, ensuring accurate mapping in the application.

* 🧪 test: Enhance bedrockInputParser tests for reasoning_config handling

- Added tests to ensure that stale `reasoning_config` is stripped when switching models from Moonshot to Meta and ZAI to DeepSeek.
- Included additional tests to verify that `reasoning_effort` values of "none", "minimal", and "xhigh" do not forward to `reasoning_config` for Moonshot and ZAI models.
- Improved coverage for the bedrockInputParser functionality to ensure correct behavior across various model configurations.

* feat: Introduce Bedrock reasoning configuration and update input parser

- Added a new `BedrockReasoningConfig` enum to define reasoning levels: low, medium, and high.
- Updated the `bedrockInputParser` to utilize the new reasoning configuration, ensuring proper handling of `reasoning_effort` values.
- Enhanced logic to validate `reasoning_effort` against the defined configuration values before assigning to `reasoning_config`.
- Improved code clarity with additional comments and refactored conditions for better readability.
This commit is contained in:
Danny Avila 2026-02-28 15:02:09 -05:00 committed by GitHub
parent cde5079886
commit e6b324b259
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 326 additions and 9 deletions

View file

@ -4,6 +4,8 @@ import * as s from './schemas';
const DEFAULT_ENABLED_MAX_TOKENS = 8192;
const DEFAULT_THINKING_BUDGET = 2000;
const bedrockReasoningConfigValues = new Set<string>(Object.values(s.BedrockReasoningConfig));
type ThinkingConfig = { type: 'enabled'; budget_tokens: number } | { type: 'adaptive' };
type AnthropicReasoning = {
@ -134,6 +136,7 @@ export const bedrockInputSchema = s.tConversationSchema
thinking: true,
thinkingBudget: true,
effort: true,
reasoning_effort: true,
promptCache: true,
/* Catch-all fields */
topK: true,
@ -178,6 +181,7 @@ export const bedrockInputParser = s.tConversationSchema
thinking: true,
thinkingBudget: true,
effort: true,
reasoning_effort: true,
promptCache: true,
/* Catch-all fields */
topK: true,
@ -256,6 +260,9 @@ export const bedrockInputParser = s.tConversationSchema
delete additionalFields.effort;
}
/** Anthropic uses 'effort' via output_config, not reasoning_config */
delete additionalFields.reasoning_effort;
if ((typedData.model as string).includes('anthropic.')) {
const betaHeaders = getBedrockAnthropicBetaHeaders(typedData.model as string);
if (betaHeaders.length > 0) {
@ -268,23 +275,37 @@ export const bedrockInputParser = s.tConversationSchema
delete additionalFields.effort;
delete additionalFields.output_config;
delete additionalFields.anthropic_beta;
const reasoningEffort = additionalFields.reasoning_effort;
delete additionalFields.reasoning_effort;
if (
typeof reasoningEffort === 'string' &&
bedrockReasoningConfigValues.has(reasoningEffort)
) {
additionalFields.reasoning_config = reasoningEffort;
}
}
const isAnthropicModel =
typeof typedData.model === 'string' && typedData.model.includes('anthropic.');
/** Strip stale anthropic_beta from previously-persisted additionalModelRequestFields */
/** Strip stale fields from previously-persisted additionalModelRequestFields */
if (
!isAnthropicModel &&
typeof typedData.additionalModelRequestFields === 'object' &&
typedData.additionalModelRequestFields != null
) {
const amrf = typedData.additionalModelRequestFields as Record<string, unknown>;
delete amrf.anthropic_beta;
delete amrf.thinking;
delete amrf.thinkingBudget;
delete amrf.effort;
delete amrf.output_config;
if (!isAnthropicModel) {
delete amrf.anthropic_beta;
delete amrf.thinking;
delete amrf.thinkingBudget;
delete amrf.effort;
delete amrf.output_config;
delete amrf.reasoning_config;
} else {
delete amrf.reasoning_config;
delete amrf.reasoning_effort;
}
}
/** Default promptCache for claude and nova models, if not defined */

View file

@ -530,6 +530,30 @@ const bedrock: Record<string, SettingDefinition> = {
showDefault: false,
columnSpan: 2,
},
reasoning_effort: {
key: 'reasoning_effort',
label: 'com_endpoint_reasoning_effort',
labelCode: true,
description: 'com_endpoint_bedrock_reasoning_effort',
descriptionCode: true,
type: 'enum',
default: ReasoningEffort.unset,
component: 'slider',
options: [
ReasoningEffort.unset,
ReasoningEffort.low,
ReasoningEffort.medium,
ReasoningEffort.high,
],
enumMappings: {
[ReasoningEffort.unset]: 'com_ui_off',
[ReasoningEffort.low]: 'com_ui_low',
[ReasoningEffort.medium]: 'com_ui_medium',
[ReasoningEffort.high]: 'com_ui_high',
},
optionType: 'model',
columnSpan: 4,
},
};
const mistral: Record<string, SettingDefinition> = {
@ -905,6 +929,34 @@ const bedrockGeneralCol2: SettingsConfiguration = [
librechat.fileTokenLimit,
];
const bedrockZAI: SettingsConfiguration = [
librechat.modelLabel,
librechat.promptPrefix,
librechat.maxContextTokens,
meta.temperature,
meta.topP,
librechat.resendFiles,
bedrock.region,
bedrock.reasoning_effort,
librechat.fileTokenLimit,
];
const bedrockZAICol1: SettingsConfiguration = [
baseDefinitions.model as SettingDefinition,
librechat.modelLabel,
librechat.promptPrefix,
];
const bedrockZAICol2: SettingsConfiguration = [
librechat.maxContextTokens,
meta.temperature,
meta.topP,
librechat.resendFiles,
bedrock.region,
bedrock.reasoning_effort,
librechat.fileTokenLimit,
];
const bedrockMoonshot: SettingsConfiguration = [
librechat.modelLabel,
bedrock.system,
@ -917,6 +969,7 @@ const bedrockMoonshot: SettingsConfiguration = [
baseDefinitions.stop,
librechat.resendFiles,
bedrock.region,
bedrock.reasoning_effort,
librechat.fileTokenLimit,
];
@ -936,6 +989,7 @@ const bedrockMoonshotCol2: SettingsConfiguration = [
bedrock.topP,
librechat.resendFiles,
bedrock.region,
bedrock.reasoning_effort,
librechat.fileTokenLimit,
];
@ -954,7 +1008,7 @@ export const paramSettings: Record<string, SettingsConfiguration | undefined> =
[`${EModelEndpoint.bedrock}-${BedrockProviders.Moonshot}`]: bedrockMoonshot,
[`${EModelEndpoint.bedrock}-${BedrockProviders.MoonshotAI}`]: bedrockMoonshot,
[`${EModelEndpoint.bedrock}-${BedrockProviders.OpenAI}`]: bedrockGeneral,
[`${EModelEndpoint.bedrock}-${BedrockProviders.ZAI}`]: bedrockGeneral,
[`${EModelEndpoint.bedrock}-${BedrockProviders.ZAI}`]: bedrockZAI,
[EModelEndpoint.google]: googleConfig,
};
@ -1008,7 +1062,10 @@ export const presetSettings: Record<
col2: bedrockMoonshotCol2,
},
[`${EModelEndpoint.bedrock}-${BedrockProviders.OpenAI}`]: bedrockGeneralColumns,
[`${EModelEndpoint.bedrock}-${BedrockProviders.ZAI}`]: bedrockGeneralColumns,
[`${EModelEndpoint.bedrock}-${BedrockProviders.ZAI}`]: {
col1: bedrockZAICol1,
col2: bedrockZAICol2,
},
[EModelEndpoint.google]: {
col1: googleCol1,
col2: googleCol2,

View file

@ -185,6 +185,12 @@ export enum AnthropicEffort {
max = 'max',
}
export enum BedrockReasoningConfig {
low = 'low',
medium = 'medium',
high = 'high',
}
export enum ReasoningSummary {
none = '',
auto = 'auto',