Skip to content

Add MiniMax LLM adapter#2166

Open
octo-patch wants to merge 6 commits into
Zipstack:mainfrom
octo-patch:octo/20260712-provider-add-recvozNE1fKYRA-clean
Open

Add MiniMax LLM adapter#2166
octo-patch wants to merge 6 commits into
Zipstack:mainfrom
octo-patch:octo/20260712-provider-add-recvozNE1fKYRA-clean

Conversation

@octo-patch

@octo-patch octo-patch commented Jul 12, 2026

Copy link
Copy Markdown

What

  • Adds a branded MiniMax LLM adapter for the OpenAI- and Anthropic-compatible chat APIs.
  • Supports MiniMax-M3 and MiniMax-M2.7 across global and China endpoints.
  • Exposes official context, modality, thinking, service-tier, and endpoint configuration.

Why

  • MiniMax users need a first-class adapter with correct protocol routing, request parameters, model limits, and regional configuration.

How

  • Uses native minimax/ routing for OpenAI-compatible bases and anthropic/ routing for bases ending in /anthropic.
  • Defaults to the global OpenAI-compatible base while documenting all four supported regional and protocol bases in the adapter schema.
  • Keeps the model field free-text, maps the UI thinking toggle to thinking.type, and forwards service_tier.
  • Enforces protocol-specific temperature bounds and always-on thinking for MiniMax-M2.x models.
  • Uses the repository's standard LiteLLM cost path without adapter-specific pricing registration or billing hooks.
  • Uses the official MiniMax icon asset.

Can this PR break any existing features. If yes, please list possible items. If no, please explain why. (PS: Admins do not merge the PR without this section filled)

  • No existing adapter or shared usage behavior changes. The implementation adds a new adapter and its focused validation tests.

Database Migrations

  • None.

Env Config

  • None. Users provide their MiniMax API key and can override the API base for region or protocol selection.

Relevant Docs

Related Issues or PRs

  • None.

Dependencies Versions

  • No dependency changes in this PR. The current base pins litellm==1.90.3.

Notes on Testing

  • Focused MiniMax adapter tests: 25 passed, 27 deselected.
  • LiteLLM request capture verified both regional OpenAI-compatible /v1/chat/completions paths and both Anthropic-compatible /anthropic/v1/messages paths, including thinking and priority-tier fields.
  • Ruff lint and format, Python compilation, JSON parsing, diff whitespace, and public-content scans passed.

Screenshots

  • Not applicable.

Checklist

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

Adds MiniMax LLM adapter support with provider-aware model routing, thinking and service-tier validation, adapter metadata, configuration schema, exports, and comprehensive branded adapter tests.

Changes

MiniMax adapter integration

Layer / File(s) Summary
MiniMax parameter validation
unstract/sdk1/src/unstract/sdk1/adapters/base1.py
Adds MiniMax endpoint constants, provider-prefix selection, model normalization, thinking and service-tier validation, temperature constraints, and cost metadata.
Adapter export and configuration contract
unstract/sdk1/src/unstract/sdk1/adapters/llm1/minimax.py, unstract/sdk1/src/unstract/sdk1/adapters/llm1/__init__.py, unstract/sdk1/src/unstract/sdk1/adapters/llm1/static/minimax.json
Defines and exports MiniMaxLLMAdapter and adds its configuration schema.
MiniMax integration coverage
unstract/sdk1/tests/test_branded_openai_adapters.py
Tests registration, endpoint fallback, provider routing, cost handling, temperature limits, service tiers, thinking behavior, and schema metadata.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant AdapterConfiguration
  participant MiniMaxLLMAdapter
  participant MiniMaxLLMParameters
  AdapterConfiguration->>MiniMaxLLMAdapter: provide api_key, model, and options
  MiniMaxLLMAdapter->>MiniMaxLLMParameters: validate configuration
  MiniMaxLLMParameters-->>MiniMaxLLMAdapter: return routed model and validated parameters
Loading

Suggested reviewers: pk-zipstack

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title is concise and accurately summarizes the main change: adding a MiniMax LLM adapter.
Description check ✅ Passed The description follows the required template and covers what, why, how, breakage risk, migrations, config, testing, and checklist items.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@octo-patch octo-patch mentioned this pull request Jul 12, 2026
1 task
@greptile-apps

greptile-apps Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds a first-class MiniMax LLM adapter. The main changes are:

  • OpenAI- and Anthropic-compatible protocol routing.
  • Global and China endpoint support.
  • MiniMax-M3 and MiniMax-M2.7 parameter validation.
  • Thinking, service-tier, token-limit, and pricing metadata.
  • Adapter registration, UI schema, icon, and focused tests.

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the changed code.
  • No eligible follow-up issue could be tied to an earlier critical review finding.

Important Files Changed

Filename Overview
unstract/sdk1/src/unstract/sdk1/adapters/base1.py Adds MiniMax endpoint detection, model routing, parameter validation, and usage-cost model selection.
unstract/sdk1/src/unstract/sdk1/adapters/llm1/init.py Exports the MiniMax adapter through the LLM adapter package.
unstract/sdk1/src/unstract/sdk1/adapters/llm1/minimax.py Defines the MiniMax adapter identity, metadata, provider, icon, and adapter type.
unstract/sdk1/src/unstract/sdk1/adapters/llm1/static/minimax.json Adds the MiniMax configuration schema for models, endpoints, request controls, and thinking.
unstract/sdk1/tests/test_branded_openai_adapters.py Covers registration, routing, validation, revalidation, pricing, service tiers, and schema metadata.

Reviews (4): Last reviewed commit: "[pre-commit.ci] auto fixes from pre-comm..." | Re-trigger Greptile

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@unstract/sdk1/src/unstract/sdk1/adapters/base1.py`:
- Line 539: Update the MiniMax subclass’s temperature declaration to retain the
base class’s Pydantic Field validation, including default 0.1 and ge=0/le=2
constraints, rather than redeclaring it as an unconstrained scalar. Preserve the
existing nullable float type.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 288ec4d5-fe33-44a6-b15c-b218f17ee909

📥 Commits

Reviewing files that changed from the base of the PR and between 09b6834 and 1e10ef8.

⛔ Files ignored due to path filters (1)
  • frontend/public/icons/adapter-icons/MiniMax.png is excluded by !**/*.png
📒 Files selected for processing (5)
  • unstract/sdk1/src/unstract/sdk1/adapters/base1.py
  • unstract/sdk1/src/unstract/sdk1/adapters/llm1/__init__.py
  • unstract/sdk1/src/unstract/sdk1/adapters/llm1/minimax.py
  • unstract/sdk1/src/unstract/sdk1/adapters/llm1/static/minimax.json
  • unstract/sdk1/tests/test_branded_openai_adapters.py

Comment thread unstract/sdk1/src/unstract/sdk1/adapters/base1.py Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
unstract/sdk1/src/unstract/sdk1/adapters/base1.py (1)

564-583: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

"Thinking always enabled for MiniMax-M2.7" is only partially enforced.

The validation blocks explicitly disabling thinking for minimax-m2* models (line 579-583), but if neither enable_thinking nor thinking is present in adapter_metadata at all, thinking stays at the class default (None) and no thinking param is sent — relying entirely on the JSON-schema UI default (enable_thinking: true) and/or the provider's own default to actually enable it. Any caller that invokes MiniMaxLLMParameters.validate()/LLM.__init__ directly (bypassing the schema-populated defaults — e.g. persisted adapter configs created before this default existed, or non-UI programmatic callers) would silently omit thinking for M2.7, which doesn't guarantee "always enabled" as stated in the PR objectives.

Consider enforcing the default at the validation layer itself, e.g.:

💡 Proposed fix to force adaptive thinking as the default for the M2 family
         thinking = adapter_metadata.get("thinking")
+        if thinking is None and model_id.lower().startswith("minimax-m2"):
+            thinking = {"type": "adaptive"}
+            adapter_metadata["thinking"] = thinking
         if thinking is not None:
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@unstract/sdk1/src/unstract/sdk1/adapters/base1.py` around lines 564 - 583,
Update the adapter metadata validation around the existing thinking handling so
minimax-m2* models default to {"type": "adaptive"} when neither enable_thinking
nor thinking is provided. Preserve explicit disabled-thinking rejection and
existing validation for supplied values, ensuring direct validation and LLM
initialization always send adaptive thinking for MiniMax-M2 models.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@unstract/sdk1/src/unstract/sdk1/adapters/base1.py`:
- Around line 564-583: Update the adapter metadata validation around the
existing thinking handling so minimax-m2* models default to {"type": "adaptive"}
when neither enable_thinking nor thinking is provided. Preserve explicit
disabled-thinking rejection and existing validation for supplied values,
ensuring direct validation and LLM initialization always send adaptive thinking
for MiniMax-M2 models.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 476807d6-7add-498f-a968-25dda55fe2c3

📥 Commits

Reviewing files that changed from the base of the PR and between 7c04f32 and b0a8525.

📒 Files selected for processing (6)
  • unstract/sdk1/src/unstract/sdk1/adapters/base1.py
  • unstract/sdk1/src/unstract/sdk1/adapters/llm1/minimax.py
  • unstract/sdk1/src/unstract/sdk1/adapters/llm1/static/minimax.json
  • unstract/sdk1/src/unstract/sdk1/llm.py
  • unstract/sdk1/tests/test_branded_openai_adapters.py
  • unstract/sdk1/tests/test_openai_compatible_adapter.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • unstract/sdk1/src/unstract/sdk1/adapters/llm1/static/minimax.json

@chandrasekharan-zipstack

Copy link
Copy Markdown
Contributor

Thanks for the rework — routing through BaseChatCompletionParameters with the native minimax/ (and anthropic/) prefixes is the right call, and the reasoning / service_tier passthrough looks good.

One structural request on the cost side: could we drop the bespoke pricing engine (_ModelSpec / _TokenRates / _MODEL_SPECS, the static calculate_usage_cost, the local register_model call, and the calculate_usage_cost reflection hook added in llm.py) and rely on litellm's standard cost path, like every other adapter?

The only reason that engine is needed today is that our pinned litellm==1.85.1 has no minimax/MiniMax-M3 entry in its cost map at all, so M3 silently bills $0. That's now fixed upstream — litellm 1.90.0 added M3 with its _above_512k_tokens long-context tier. I've raised #2169 to bump litellm to 1.90.3, which prices M3 correctly (including the >512k rate switch) straight through the normal cost_per_token path. Verified on the bump branch:

minimax/MiniMax-M3: base $0.03 (<512k, @3e-7); $0.60 for a 1M-token prompt (@6e-7 above-512k)

Once #2169 lands, the standard path covers M3 with zero local pricing code — which avoids the drift/maintenance of a MiniMax-only cost table and keeps this adapter consistent with the rest.

Two follow-ups:

  • MiniMax-M2.7 is the one model litellm still doesn't price under the native minimax/ prefix (only sambanova/ and fireworks_ai/ variants exist upstream). I've filed an issue to add it: Add "minimax/MiniMax-M2.7" in "model_prices_and_context_window.json" BerriAI/litellm#33058. Until that lands, M2.7 bills $0 — acceptable as a known transient gap rather than a reason to keep a local engine.
  • Model field: every other LLM adapter (openai, anthropic, bedrock, openrouter, mistral, …) uses a free-text model string rather than an enum dropdown. Suggest matching that here — it's consistent and lets users select newer MiniMax models (M2.1 / M2.5 / lightning, and future releases) without a code change each time.

Happy to help coordinate sequencing with #2169.

@chandrasekharan-zipstack

Copy link
Copy Markdown
Contributor

@octo-patch TLDR from this comment

@sonarqubecloud

Copy link
Copy Markdown

@octo-patch

Copy link
Copy Markdown
Author

Thanks for the review. I removed the adapter-specific model registration, pricing calculator, and shared billing hook; the adapter now uses the standard LiteLLM cost path from the merged dependency update, while keeping the model field free-text. I also added protocol-specific temperature validation and MiniMax-M2.x thinking coverage, and ran 25 focused tests plus four endpoint request captures.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
unstract/sdk1/src/unstract/sdk1/adapters/base1.py (1)

622-624: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Fix literal "None" coercion for missing models.

If a caller explicitly sets {"model": None} in adapter_metadata, adapter_metadata.get("model", "") evaluates to None. The subsequent str(None) call coerces it into the literal string "None". Because "None" is truthy, it bypasses the not model check and sends a malformed model ID to the upstream API.

Update the extraction to safely handle None values, mirroring the robust pattern used in the Mistral adapter below.

🐛 Proposed fix
     `@staticmethod`
     def validate_model(adapter_metadata: dict[str, "Any"]) -> str:
-        model = str(adapter_metadata.get("model", "")).strip()
+        raw_model = adapter_metadata.get("model")
+        model = str(raw_model).strip() if raw_model is not None else ""
         if not model:
             raise ValueError("model is required for the MiniMax adapter.")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@unstract/sdk1/src/unstract/sdk1/adapters/base1.py` around lines 622 - 624,
Update the model extraction in the MiniMax adapter to handle an explicit None as
missing before string conversion, matching the robust handling used by the
Mistral adapter. Ensure None, empty, and whitespace-only values still trigger
the existing “model is required” ValueError, while valid model identifiers
remain stripped and accepted.
🧹 Nitpick comments (1)
unstract/sdk1/src/unstract/sdk1/adapters/base1.py (1)

591-604: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Future-proof the MiniMax-M2 prefix check.

The model_id.lower().startswith("minimax-m2") check correctly identifies current models like MiniMax-M2.7, but it will also unintentionally match future models like MiniMax-M20 or MiniMax-M200.

Consider tightening the check (e.g., matching "minimax-m2.", "minimax-m2-", or using a regex boundary) to ensure future model families don't accidentally inherit M2-specific thinking constraints.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@unstract/sdk1/src/unstract/sdk1/adapters/base1.py` around lines 591 - 604,
Update both MiniMax-M2 checks in the thinking logic to require a model-family
boundary after “minimax-m2” (such as a dot, hyphen, or equivalent regex
boundary), so models like MiniMax-M20 and MiniMax-M200 do not match. Preserve
automatic adaptive thinking and the disabled-thinking validation for valid
MiniMax-M2 variants.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@unstract/sdk1/src/unstract/sdk1/adapters/base1.py`:
- Around line 622-624: Update the model extraction in the MiniMax adapter to
handle an explicit None as missing before string conversion, matching the robust
handling used by the Mistral adapter. Ensure None, empty, and whitespace-only
values still trigger the existing “model is required” ValueError, while valid
model identifiers remain stripped and accepted.

---

Nitpick comments:
In `@unstract/sdk1/src/unstract/sdk1/adapters/base1.py`:
- Around line 591-604: Update both MiniMax-M2 checks in the thinking logic to
require a model-family boundary after “minimax-m2” (such as a dot, hyphen, or
equivalent regex boundary), so models like MiniMax-M20 and MiniMax-M200 do not
match. Preserve automatic adaptive thinking and the disabled-thinking validation
for valid MiniMax-M2 variants.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 77326b44-0569-40ac-8939-f863ea0f799e

📥 Commits

Reviewing files that changed from the base of the PR and between b0a8525 and 12c516a.

📒 Files selected for processing (4)
  • unstract/sdk1/src/unstract/sdk1/adapters/base1.py
  • unstract/sdk1/src/unstract/sdk1/adapters/llm1/minimax.py
  • unstract/sdk1/src/unstract/sdk1/adapters/llm1/static/minimax.json
  • unstract/sdk1/tests/test_branded_openai_adapters.py
💤 Files with no reviewable changes (1)
  • unstract/sdk1/src/unstract/sdk1/adapters/llm1/minimax.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • unstract/sdk1/src/unstract/sdk1/adapters/llm1/static/minimax.json

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants