-
Notifications
You must be signed in to change notification settings - Fork 683
fix(model): handle minimax m3 #1771
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| # Plan | ||
|
|
||
| 1. Fix provider DB model ID comparison in `ModelConfigHelper`. | ||
| 2. Add a narrow MiniMax-M3 config correction for interleaved thinking and the documented context | ||
| window. | ||
| 3. Add MiniMax-M3 adaptive thinking provider options for Anthropic-compatible runtime. | ||
| 4. Cover the behavior with focused unit tests. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| # MiniMax model matching and thinking | ||
|
|
||
| ## Problem | ||
|
|
||
| MiniMax provider models with mixed-case IDs such as `MiniMax-M3` and `MiniMax-M2.5` can miss | ||
| provider DB-derived configuration because model config lookup lowercases the requested model ID but | ||
| compares it with the raw DB model ID. | ||
|
|
||
| MiniMax-M3 also requires explicit Anthropic-compatible `thinking: { type: "adaptive" }` to emit | ||
| thinking blocks. Current Anthropic-compatible provider options only send `thinking` for official | ||
| Anthropic adaptive reasoning or budget-based thinking. | ||
|
|
||
| ## Acceptance Criteria | ||
|
|
||
| - Provider DB model lookup matches model IDs case-insensitively while keeping provider matching | ||
| strict. | ||
| - MiniMax mixed-case model IDs inherit provider DB context, output, multimodal, tool-call, and | ||
| reasoning defaults. | ||
| - MiniMax-M3 defaults to interleaved thinking compatibility even if the provider DB source has not | ||
| caught up. | ||
| - MiniMax-M3 sends Anthropic-compatible adaptive thinking when reasoning is enabled. | ||
| - Reasoning-disabled MiniMax-M3 requests do not send adaptive thinking. | ||
|
|
||
| ## Non-goals | ||
|
|
||
| - Do not route MiniMax through Anthropic provider capability semantics. | ||
| - Do not change Claude or generic Anthropic proxy behavior. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| # Tasks | ||
|
|
||
| - [x] Add provider DB case-insensitive matching coverage. | ||
| - [x] Fix `ModelConfigHelper` matching and MiniMax-M3 defaults. | ||
| - [x] Add MiniMax-M3 provider options coverage. | ||
| - [x] Run focused tests. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -34,6 +34,20 @@ import type { StoreLike } from './storeLike' | |
| const SPECIAL_CONCAT_CHAR = '-_-' | ||
|
|
||
| const MODEL_CONFIG_META_KEY = '__meta__' | ||
| const MINIMAX_M3_CONTEXT_LENGTH = 1_000_000 | ||
|
|
||
| const normalizeProviderDbModelId = (modelId: string | undefined): string | undefined => { | ||
| const normalized = modelId ? modelId.toLowerCase() : modelId | ||
| return normalized ? normalized.replace(/^models\//, '') : normalized | ||
| } | ||
|
|
||
| const isMiniMaxProviderId = (providerId: string | undefined): boolean => { | ||
| const normalized = providerId?.trim().toLowerCase() | ||
| return normalized === 'minimax' || normalized === 'minimax-cn' | ||
| } | ||
|
|
||
| const isMiniMaxM3Model = (providerId: string | undefined, modelId: string): boolean => | ||
| isMiniMaxProviderId(providerId) && modelId.trim().toLowerCase() === 'minimax-m3' | ||
|
|
||
| const normalizeVerbosityValue = ( | ||
| portrait: ReasoningPortrait | null, | ||
|
|
@@ -154,7 +168,17 @@ export class ModelConfigHelper { | |
| return config | ||
| } | ||
|
|
||
| return applyMoonshotKimiReasoningTemperaturePolicy(providerId, modelId, config) | ||
| const policyConfig = applyMoonshotKimiReasoningTemperaturePolicy(providerId, modelId, config) | ||
|
|
||
| if (!isMiniMaxM3Model(providerId, modelId)) { | ||
| return policyConfig | ||
| } | ||
|
|
||
| return { | ||
| ...policyConfig, | ||
| contextLength: Math.max(policyConfig.contextLength ?? 0, MINIMAX_M3_CONTEXT_LENGTH), | ||
| forceInterleavedThinkingCompat: true | ||
| } | ||
| } | ||
|
|
||
| private buildConfigFromProviderModel(model: ProviderModel, providerId: string): ModelConfig { | ||
|
|
@@ -178,10 +202,13 @@ export class ModelConfigHelper { | |
| portrait, | ||
| portrait?.verbosity ?? model.reasoning?.verbosity | ||
| ) | ||
| const contextLimit = isMiniMaxM3Model(providerId, model.id) | ||
| ? Math.max(model.limit?.context ?? 0, MINIMAX_M3_CONTEXT_LENGTH) | ||
| : model.limit?.context | ||
|
|
||
| return this.applyProviderSpecificPolicies(providerId, model.id, { | ||
| maxTokens: resolveDerivedModelMaxTokens(model.limit?.output), | ||
| contextLength: resolveModelContextLength(model.limit?.context), | ||
| contextLength: resolveModelContextLength(contextLimit), | ||
|
Comment on lines
+205
to
+211
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. MiniMax-M3 context floor can be silently bypassed by provider cache merge. You compute the M3 floor here, but Line 534 later prefers Proposed fix- contextLength: storedConfig.contextLength ?? finalConfig.contextLength,
+ contextLength:
+ isMiniMaxM3Model(providerId, modelId)
+ ? Math.max(
+ storedConfig.contextLength ?? 0,
+ finalConfig.contextLength ?? MINIMAX_M3_CONTEXT_LENGTH
+ )
+ : storedConfig.contextLength ?? finalConfig.contextLength,🤖 Prompt for AI Agents |
||
| timeout: DEFAULT_MODEL_TIMEOUT, | ||
| temperature: 0.6, | ||
| topP: undefined, | ||
|
|
@@ -199,7 +226,9 @@ export class ModelConfigHelper { | |
| ? ApiEndpointType.AudioSpeech | ||
| : ApiEndpointType.Chat, | ||
| thinkingBudget, | ||
| forceInterleavedThinkingCompat, | ||
| forceInterleavedThinkingCompat: isMiniMaxM3Model(providerId, model.id) | ||
| ? true | ||
| : forceInterleavedThinkingCompat, | ||
| reasoningEffort, | ||
| reasoningVisibility, | ||
| verbosity, | ||
|
|
@@ -455,7 +484,7 @@ export class ModelConfigHelper { | |
| ) { | ||
| for (let i = 0; i < providerEntry.models.length; i += 1) { | ||
| const candidate = providerEntry.models[i] | ||
| if (candidate && candidate.id === normModelId) { | ||
| if (candidate && normalizeProviderDbModelId(candidate.id) === normModelId) { | ||
| finalConfig = this.buildConfigFromProviderModel(candidate, resolvedProviderId) | ||
| break | ||
| } | ||
|
|
@@ -472,7 +501,7 @@ export class ModelConfigHelper { | |
|
|
||
| for (let j = 0; j < candidateProvider.models.length; j += 1) { | ||
| const candidateModel = candidateProvider.models[j] | ||
| if (candidateModel && candidateModel.id === normModelId) { | ||
| if (candidateModel && normalizeProviderDbModelId(candidateModel.id) === normModelId) { | ||
| finalConfig = this.buildConfigFromProviderModel(candidateModel, candidateProvider.id) | ||
| break | ||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.