Skip to content

feat: add MiniMax LLM provider support#96

Open
octo-patch wants to merge 4 commits into
arklexai:mainfrom
octo-patch:feature/add-minimax-provider
Open

feat: add MiniMax LLM provider support#96
octo-patch wants to merge 4 commits into
arklexai:mainfrom
octo-patch:feature/add-minimax-provider

Conversation

@octo-patch

@octo-patch octo-patch commented Mar 14, 2026

Copy link
Copy Markdown

Summary

Add MiniMax as a new LLM provider for ArkSim. MiniMax offers high-performance language models through an OpenAI-compatible API, making it straightforward to integrate.

Changes

  • New provider: arksim/llms/chat/providers/minimax.py - MiniMax LLM provider using OpenAI-compatible Chat Completions API
  • Factory registration: Added minimax provider option in LLM._get_provider()
  • Unit tests: Full test coverage in tests/unit/test_minimax_llm.py and factory test in test_llm_factory.py
  • README: Updated provider documentation to include MiniMax

Supported Models

Model Description
MiniMax-M2.5 Peak performance, 204K context window
MiniMax-M2.5-highspeed Same performance, faster and more agile

Usage

export MINIMAX_API_KEY="your-key"
provider: minimax
model: MiniMax-M2.5
from arksim.llms.chat import LLM
llm = LLM(model="MiniMax-M2.5", provider="minimax")
result = llm.call("Hello\!")

Implementation Details

  • Uses the bundled OpenAI SDK (no new dependencies) with MiniMax OpenAI-compatible endpoint (https://api.minimax.io/v1)
  • Handles temperature constraint (0.0, 1.0] with automatic clamping
  • Structured output via prompt engineering + JSON parsing
  • Supports custom base URL via MINIMAX_BASE_URL env var

API Documentation

Test Results

  • All 26 new unit tests pass
  • All 510 existing tests pass (0 regressions)
  • Integration tested with MiniMax API (both MiniMax-M2.5 and MiniMax-M2.5-highspeed)

- Add MiniMax LLM provider using OpenAI-compatible Chat Completions API
- Support MiniMax-M2.5 and MiniMax-M2.5-highspeed models
- Handle temperature constraint (0.0, 1.0] with automatic clamping
- Implement structured output via prompt engineering + JSON parsing
- Register provider in LLM factory with provider name "minimax"
- Add unit tests for MiniMax provider
- Update README with MiniMax provider documentation
@octo-patch octo-patch requested a review from a team as a code owner March 14, 2026 05:22
@codecov

codecov Bot commented Mar 14, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

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

hey, welcome and thanks for the contribution! clean implementation and thorough test coverage.

left a couple inline questions. nothing major, just want to make sure we're aligned on structured output and temperature defaults before merging.

Comment on lines +57 to +63
schema_json = json.dumps(schema.model_json_schema())
system_prompt = (
"You must respond with valid JSON only, no extra text. "
f"JSON Schema: {schema_json}"
)
chat_messages.insert(0, {"role": "system", "content": system_prompt})

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.

other providers use native structured output (OpenAI text_format, Anthropic output_format). does MiniMax's endpoint support response_format? that'd be way more reliable than prompt engineering + regex parsing. if it doesn't then this approach is totally fine, just want to make sure we tried the native path first.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Good call! MiniMax does support response_format via their OpenAI-compatible API. Updated to use native response_format: {"type": "json_object"} when a schema is requested. The system prompt with the JSON schema is kept as well to guide the model toward the correct structure, but the API-level constraint ensures valid JSON output. Fixed in c152382.

Comment thread arksim/llms/chat/providers/minimax.py Outdated
Comment on lines +70 to +72
temp = self.temperature if self.temperature is not None else 1.0
params["temperature"] = max(0.01, min(temp, 1.0))

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.

other providers skip temperature when the user hasn't set one and let the API use its own default. always sending 1.0 means more random outputs than users might expect. is there a reason MiniMax needs an explicit value here?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

You're right — removed the hardcoded temperature default. Now it only sends temperature when explicitly set by the user, matching the behavior of the OpenAI and Anthropic providers. The clamping to (0.01, 1.0] is still applied when a value is provided, since MiniMax rejects values outside that range. Fixed in c152382.

octo-patch and others added 2 commits March 18, 2026 11:55
- Add MiniMax-M2.7 and MiniMax-M2.7-highspeed to UI model selector
- Add minimax to providers list and env hints in frontend
- Update test references from M2.5 to M2.7
- Keep all previous models as alternatives

Co-Authored-By: Octopus <liyuan851277048@icloud.com>
…default

Address review feedback:
- Use response_format: {"type": "json_object"} for structured output instead
  of relying solely on prompt engineering. MiniMax supports this via their
  OpenAI-compatible API.
- Only include temperature in API calls when explicitly set by the user,
  matching the behavior of the OpenAI and Anthropic providers. Remove the
  hardcoded 1.0 default.

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

Thanks for the contribution! This is a really clean integration - love that it reuses the OpenAI SDK so there's no new dependency to pull in. The test coverage is solid too.

Left a couple of inline comments, one is a minor bug the rest are just small suggestions. Nice work overall!

One other thing - looks like the supported models table in the PR description still references M2.5, but the code was updated to default to M2.7 in a follow-up commit. Might want to update the description so it matches what's in app.js.

self,
messages: str | list[LLMMessage],
schema: type[T] | None = None,
**kwargs: object,

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.

Small thing - the OpenAI SDK can return None here if the model response has no content (rare but possible). Might be worth adding a quick guard so it doesn't surface as a confusing downstream error:

if content is None:
    raise ValueError("MiniMax returned empty response")

Same applies to the async version below.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Good catch! Added the null guard for both call() and call_async() — raises ValueError("MiniMax returned empty response") if content is None. Also added test cases for both sync and async paths. Fixed in 4c2c018.


@staticmethod
def _parse_json(text: str) -> dict[str, Any]:
"""Extract JSON from the response text.

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.

Totally makes sense given MiniMax's constraint. One thought - if someone explicitly passes temperature=0.0 expecting deterministic output, the silent bump to 0.01 could be a bit surprising. Maybe worth a logger.warning so they know? Totally optional though.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Great suggestion — added a logger.warning that fires whenever the temperature gets clamped. This way users passing temperature=0.0 will see a clear message explaining that MiniMax requires values in (0.0, 1.0] and their value was adjusted to 0.01. Added tests to verify the warning is emitted (and not emitted for valid values). Fixed in 4c2c018.

- Add null check for response content in both call() and call_async()
  to raise a clear ValueError instead of surfacing confusing downstream
  errors when MiniMax returns no content
- Add logger.warning when temperature is clamped to (0.01, 1.0] range
  so users are aware their value was adjusted
- Add tests for both changes (4 new test cases)

Addresses review feedback from @itsarbit.

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

LGTM! Clean integration, solid test coverage, and all feedback addressed.

nit: PR description still references M2.5 in the supported models table but the code defaults to M2.7 now. Worth updating for anyone reading this later.

@octo-patch

Copy link
Copy Markdown
Author

Thanks for the approval! Updated the PR description to reflect the M2.7 default model.

@octo-patch

Copy link
Copy Markdown
Author

Thank you for the thorough review and approval @itsarbit! Happy to make any further adjustments if needed.

@itsarbit

Copy link
Copy Markdown
Contributor

@octo-patch sound great! I think CI failed in some linting issue that you might want to fix. Could you fix it and I'll restamp.

@itsarbit

Copy link
Copy Markdown
Contributor

Hey @octo-patch, this has a merge conflict in README.md now since we restructured the README on main. Could you rebase against main and resolve the conflict? The code files should merge cleanly. The only conflict is in README.md where we simplified it to link to docs instead of inlining everything. Just take main's version of README.md and it should be good.

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