Skip to content

Add MiniMax LLM adapter#2156

Closed
octo-patch wants to merge 4 commits into
Zipstack:mainfrom
octo-patch:octo/20260706-provider-add-recvozNE1fKYRA
Closed

Add MiniMax LLM adapter#2156
octo-patch wants to merge 4 commits into
Zipstack:mainfrom
octo-patch:octo/20260706-provider-add-recvozNE1fKYRA

Conversation

@octo-patch

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

Copy link
Copy Markdown

What

  • Adds a branded MiniMax LLM adapter for the compatible chat API.
  • Supports MiniMax-M3 and MiniMax-M2.7 with native routing, regional endpoint configuration, thinking controls, an official icon, and focused tests.

Why

  • MiniMax users need a first-class adapter with correct request transformation and usage tracking.

How

  • Registers the adapter and prefixes model IDs with minimax/ for native routing.
  • Defaults to the global API endpoint while documenting the China endpoint as an override.
  • Maps the UI thinking toggle to the official thinking.type request field and prevents disabling thinking for MiniMax-M2.7.
  • Replaces the placeholder icon with the official MiniMax 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 behavior is changed. The implementation is isolated to the new MiniMax adapter, its registration, schema, icon, and tests.

Database Migrations

  • None.

Env Config

  • None. Users provide their API key in the adapter configuration and may override the regional API base.

Relevant Docs

Related Issues or PRs

  • None.

Dependencies Versions

  • No dependency changes. The implementation uses the repository's pinned litellm==1.85.1.

Notes on Testing

  • Focused adapter tests: 19 passed.
  • Ruff lint and format checks passed for the changed Python files.
  • JSON parsing, Python compilation, secret scanning, and git diff --check passed.
  • The full adapter test file reached 35 passed; three existing embedding tests could not load the optional system libmagic library on this machine.

Screenshots

  • Not applicable.

Checklist

@CLAassistant

CLAassistant commented Jul 8, 2026

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
1 out of 2 committers have signed the CLA.

✅ octo-patch
❌ kapelame


kapelame seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a6ba5799-c6a2-4fc0-b1b9-157343099c69

📥 Commits

Reviewing files that changed from the base of the PR and between 049e8c3 and 813de35.

📒 Files selected for processing (2)
  • unstract/sdk1/src/unstract/sdk1/adapters/base1.py
  • unstract/sdk1/tests/test_branded_openai_adapters.py
💤 Files with no reviewable changes (2)
  • unstract/sdk1/src/unstract/sdk1/adapters/base1.py
  • unstract/sdk1/tests/test_branded_openai_adapters.py

Summary by CodeRabbit

  • New Features

    • Added MiniMax as a supported large language model provider.
    • Added configuration options for API credentials, model selection, custom endpoints, token limits, retries, timeouts, and thinking mode.
    • Automatically applies MiniMax model routing and API defaults.
    • Added validation for supported thinking modes and model-specific requirements.
  • Tests

    • Added coverage for routing, configuration defaults, thinking behavior, model validation, and usage cost resolution.

Walkthrough

This PR adds a MiniMax branded OpenAI-compatible LLM adapter to the Unstract SDK, including parameter validation, adapter metadata, a JSON configuration schema, package exports, and tests for routing, defaults, thinking behavior, and schema generation.

Changes

MiniMax LLM adapter

Layer / File(s) Summary
MiniMax parameter validation
unstract/sdk1/src/unstract/sdk1/adapters/base1.py
Adds MiniMax API constants and validates API base normalization, model prefixing, thinking configuration, and minimax-m2* constraints.
Adapter implementation and configuration
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 adapter metadata and exports, plus required fields, defaults, and constraints for MiniMax configuration.
Routing and schema tests
unstract/sdk1/tests/test_branded_openai_adapters.py
Covers registration, native provider routing, model normalization, thinking behavior, API base fallback and overrides, and generated schema contents.

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

Sequence Diagram(s)

sequenceDiagram
  participant Configuration
  participant MiniMaxLLMAdapter
  participant LiteLLM
  Configuration->>MiniMaxLLMAdapter: provide model and adapter parameters
  MiniMaxLLMAdapter->>MiniMaxLLMAdapter: normalize model, API base, and thinking
  MiniMaxLLMAdapter->>LiteLLM: route using the minimax provider
  LiteLLM-->>MiniMaxLLMAdapter: resolve model usage costs
Loading
🚥 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
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding a MiniMax LLM adapter.
Description check ✅ Passed The description follows the template and includes the required sections with meaningful details.
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.
✨ 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.

@greptile-apps

greptile-apps Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Adds a new MiniMaxLLMAdapter that routes through LiteLLM's native minimax/ provider prefix, maps the enable_thinking UI toggle to MiniMax's thinking.type field, and guards MiniMax-M2.7 from having thinking disabled.

  • MiniMaxLLMParameters in base1.py extends BaseChatCompletionParameters directly (rather than OpenAICompatibleLLMParameters), correctly avoiding the reasoning_effort/extra_body path that was called out in the previous review thread.
  • Schema (minimax.json) defaults enable_thinking to true and documents both the global and China-region endpoints; reasoning_effort is absent as requested.
  • Tests cover registration, model prefix idempotency, cost resolution via litellm.cost_per_token, thinking toggle mapping, M2.7 guard, and schema content — 19 focused cases.

Confidence Score: 5/5

Change is isolated to a new adapter; no existing adapter behaviour is modified and the implementation correctly avoids the reasoning_effort path that was flagged in prior review.

All changes are self-contained in the new MiniMax adapter, its schema, and tests. No existing adapter logic is touched. The three findings are quality and robustness observations on the new code, not present defects in the existing paths.

unstract/sdk1/src/unstract/sdk1/adapters/base1.py — the thinking field declaration and missing temperature guard in MiniMaxLLMParameters are worth a second look before this ships.

Important Files Changed

Filename Overview
unstract/sdk1/src/unstract/sdk1/adapters/base1.py Adds MiniMaxLLMParameters class with its own validate() and validate_model(); correctly uses native minimax/ LiteLLM prefix and maps enable_thinking → thinking.type. The thinking field is declared as a Pydantic field (unlike Anthropic/Bedrock/Gemini/VertexAI, which inject it post-model_dump), so model_dump() always emits thinking: None when unset. Also missing temperature=1 enforcement when thinking is enabled, which every other thinking-capable adapter enforces.
unstract/sdk1/src/unstract/sdk1/adapters/llm1/minimax.py Clean adapter class wiring MiniMaxLLMParameters to the BaseAdapter interface; correct provider name, icon path, and adapter type.
unstract/sdk1/src/unstract/sdk1/adapters/llm1/static/minimax.json Well-formed JSON schema; enable_thinking defaults to true and exposes both regional endpoints. Correctly excludes reasoning_effort as noted in prior review threads.
unstract/sdk1/tests/test_branded_openai_adapters.py 19 new test cases covering registration, model prefix idempotency, cost resolution, thinking toggle mapping, M2.7 guard, schema content, and api_base override; good coverage of the happy path.
unstract/sdk1/src/unstract/sdk1/adapters/llm1/init.py MiniMaxLLMAdapter correctly registered in both imports and all.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant UI
    participant MiniMaxLLMAdapter
    participant MiniMaxLLMParameters
    participant LiteLLM
    participant MiniMaxAPI

    UI->>MiniMaxLLMAdapter: get_json_schema()
    MiniMaxLLMAdapter-->>UI: minimax.json (enable_thinking default: true)

    UI->>MiniMaxLLMParameters: "validate({model, api_key, enable_thinking})"
    MiniMaxLLMParameters->>MiniMaxLLMParameters: validate_model() → minimax/MiniMax-M3
    MiniMaxLLMParameters->>MiniMaxLLMParameters: "pop enable_thinking → thinking={type:adaptive}"
    MiniMaxLLMParameters->>MiniMaxLLMParameters: guard M2.7 + disabled
    MiniMaxLLMParameters->>MiniMaxLLMParameters: model_dump()
    MiniMaxLLMParameters-->>UI: "{model, api_key, api_base, temperature, thinking, ...}"

    UI->>LiteLLM: "completion(**validated_params)"
    LiteLLM->>LiteLLM: route via minimax/ provider
    LiteLLM->>MiniMaxAPI: "POST /v1/chat/completions {thinking:{type:adaptive}}"
    MiniMaxAPI-->>LiteLLM: response + usage
    LiteLLM-->>UI: ChatCompletion
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant UI
    participant MiniMaxLLMAdapter
    participant MiniMaxLLMParameters
    participant LiteLLM
    participant MiniMaxAPI

    UI->>MiniMaxLLMAdapter: get_json_schema()
    MiniMaxLLMAdapter-->>UI: minimax.json (enable_thinking default: true)

    UI->>MiniMaxLLMParameters: "validate({model, api_key, enable_thinking})"
    MiniMaxLLMParameters->>MiniMaxLLMParameters: validate_model() → minimax/MiniMax-M3
    MiniMaxLLMParameters->>MiniMaxLLMParameters: "pop enable_thinking → thinking={type:adaptive}"
    MiniMaxLLMParameters->>MiniMaxLLMParameters: guard M2.7 + disabled
    MiniMaxLLMParameters->>MiniMaxLLMParameters: model_dump()
    MiniMaxLLMParameters-->>UI: "{model, api_key, api_base, temperature, thinking, ...}"

    UI->>LiteLLM: "completion(**validated_params)"
    LiteLLM->>LiteLLM: route via minimax/ provider
    LiteLLM->>MiniMaxAPI: "POST /v1/chat/completions {thinking:{type:adaptive}}"
    MiniMaxAPI-->>LiteLLM: response + usage
    LiteLLM-->>UI: ChatCompletion
Loading

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

Comment thread unstract/sdk1/src/unstract/sdk1/adapters/llm1/static/minimax.json Outdated
)


class MiniMaxLLMParameters(OpenAICompatibleLLMParameters):

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.

Routing through custom_openai/ silently zeroes out cost tracking for MiniMax.

_validate_branded_openai_compatible delegates to OpenAICompatibleLLMParameters.validate(), whose validate_model() unconditionally prepends custom_openai/. cost_model is only populated when the endpoint is OpenAI's own (base1.py:483), so it stays unset here, and audit.py:98 ends up calling cost_per_token(model="custom_openai/MiniMax-M3") — which raises, gets swallowed by the bare except, and records cost_in_dollars = 0.0 at debug level.

LiteLLM already ships a native MiniMax provider, and it prices M3:

litellm.get_llm_provider("minimax/MiniMax-M3")  -> ('MiniMax-M3', 'minimax', None, None)

cost_per_token("custom_openai/MiniMax-M3") -> raises        => cost = 0.0
cost_per_token("minimax/MiniMax-M3")       -> $0.30 / $1.20 per 1M tokens

So every MiniMax token would bill as $0 in usage tracking, silently.

This is why OpenRouterLLMParameters extends BaseChatCompletionParameters instead of OpenAICompatibleLLMParameters — its own docstring says so: "Routed through LiteLLM's native openrouter/ provider so per-token costs resolve and reasoning params map without provider-specific workarounds." MiniMax should follow OpenRouter's template, not NVIDIA Build's.

Worth noting NVIDIA Build's custom_openai/ routing is correct for NVIDIA — LiteLLM prices zero nvidia_nim/ chat models (3 entries, all rerankers, all $0.0), so there's nothing to forfeit there. That reason doesn't carry over to MiniMax.

Bonus: MinimaxChatConfig.get_api_base() already returns https://api.minimax.io/v1, so going native lets you drop the hardcoded _MINIMAX_API_BASE constant entirely.


@staticmethod
def get_icon() -> str:
return "/icons/adapter-icons/MiniMax.png"

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.

The shipped MiniMax.png is the OpenRouter logo.

frontend/public/icons/adapter-icons/MiniMax.png is byte-for-byte identical to OpenRouter.png:

0980b0d3102c84da9d332862c563c44f  MiniMax.png
0980b0d3102c84da9d332862c563c44f  OpenRouter.png
676be9d2fc5cec78d5be80af03eb9fd4  NvidiaBuild.png

Both 29953 bytes. Rendering it confirms it's the OpenRouter fork-arrow mark. NvidiaBuild.png differs, so this isn't a shared-placeholder convention — it looks like the icon was copied along with the adapter template and never swapped.

Users would see OpenRouter's branding on the MiniMax card in the adapter picker. Needs the real MiniMax logo.

@octo-patch

Copy link
Copy Markdown
Author

Thanks for the review. I switched the MiniMax adapter to native routing, mapped the UI toggle to thinking.type, covered MiniMax-M3 and MiniMax-M2.7, documented both regional API endpoints, and replaced the icon with the official asset. I ran 19 focused tests plus Ruff and JSON validation.

@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.

🧹 Nitpick comments (2)
unstract/sdk1/tests/test_branded_openai_adapters.py (1)

48-96: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Comprehensive MiniMax test coverage; minor gap in thinking toggle assertion.

The test suite thoroughly covers routing, idempotency, cost resolution, thinking mapping, and M2 constraints. The cost-per-token test directly validates the fix for the previous review's cost-tracking concern.

Minor gap at line 87: assert "enable_thinking" not in enabled only checks the enabled dict. The disabled dict should also have enable_thinking removed (via pop), but this isn't asserted.

🤖 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/tests/test_branded_openai_adapters.py` around lines 48 - 96,
Update test_minimax_maps_thinking_toggle_to_native_parameter to also assert that
"enable_thinking" is absent from the disabled validation result, confirming both
toggle paths remove the source parameter after mapping.
unstract/sdk1/src/unstract/sdk1/adapters/base1.py (1)

534-582: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Past concern about cost tracking is resolved; flag silent thinking overwrite when both enable_thinking and thinking are provided.

The switch from OpenAICompatibleLLMParameters to BaseChatCompletionParameters with native minimax/ prefixing addresses the previous review's critical concern about custom_openai/ routing zeroing out cost tracking. The test test_minimax_native_routing_resolves_usage_cost confirms cost_per_token returns positive values.

One edge case: if a caller passes both enable_thinking and thinking in adapter_metadata, the enable_thinking block (lines 552-558) silently overwrites the thinking value. Consider raising or warning when both are present to avoid surprising behavior.

🤖 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 534 - 582,
Update MiniMaxLLMParameters.validate to detect when both enable_thinking and
thinking are provided before converting enable_thinking; raise a clear
ValueError (or use the project’s established warning mechanism) instead of
silently overwriting thinking. Preserve the existing boolean validation and
conversion behavior when only enable_thinking is supplied.
🤖 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.

Nitpick comments:
In `@unstract/sdk1/src/unstract/sdk1/adapters/base1.py`:
- Around line 534-582: Update MiniMaxLLMParameters.validate to detect when both
enable_thinking and thinking are provided before converting enable_thinking;
raise a clear ValueError (or use the project’s established warning mechanism)
instead of silently overwriting thinking. Preserve the existing boolean
validation and conversion behavior when only enable_thinking is supplied.

In `@unstract/sdk1/tests/test_branded_openai_adapters.py`:
- Around line 48-96: Update
test_minimax_maps_thinking_toggle_to_native_parameter to also assert that
"enable_thinking" is absent from the disabled validation result, confirming both
toggle paths remove the source parameter after mapping.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 57c23626-99d4-4647-819e-a1fac0fe9251

📥 Commits

Reviewing files that changed from the base of the PR and between f996449 and 049e8c3.

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

@sonarqubecloud

Copy link
Copy Markdown

@octo-patch

Copy link
Copy Markdown
Author

This work continues in #2166, rebuilt from the latest main with a clean commit history. The replacement contains the same scoped MiniMax adapter changes and focused checks.

@greptile-apps

greptile-apps Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Want your agent to iterate on Greptile's feedback? Try greploops.

@octo-patch octo-patch closed this Jul 12, 2026
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.

4 participants