feat: add MiniMax LLM provider support#96
Conversation
- 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
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
itsarbit
left a comment
There was a problem hiding this comment.
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.
| 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}) | ||
|
|
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
| temp = self.temperature if self.temperature is not None else 1.0 | ||
| params["temperature"] = max(0.01, min(temp, 1.0)) | ||
|
|
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
- 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
left a comment
There was a problem hiding this comment.
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, |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
left a comment
There was a problem hiding this comment.
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.
|
Thanks for the approval! Updated the PR description to reflect the M2.7 default model. |
|
Thank you for the thorough review and approval @itsarbit! Happy to make any further adjustments if needed. |
|
@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. |
|
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. |
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
arksim/llms/chat/providers/minimax.py- MiniMax LLM provider using OpenAI-compatible Chat Completions APIminimaxprovider option inLLM._get_provider()tests/unit/test_minimax_llm.pyand factory test intest_llm_factory.pySupported Models
MiniMax-M2.5MiniMax-M2.5-highspeedUsage
Implementation Details
https://api.minimax.io/v1)(0.0, 1.0]with automatic clampingMINIMAX_BASE_URLenv varAPI Documentation
Test Results