feat: add MiniMax Chat node with M2.7 as default model#12924
feat: add MiniMax Chat node with M2.7 as default model#12924octo-patch wants to merge 4 commits intoComfy-Org:masterfrom
Conversation
Extend the existing MiniMax integration (currently video-only) with a new MinimaxChatNode that supports text generation via MiniMax-M2.5 and MiniMax-M2.5-highspeed language models. The node follows the same ComfyExtension pattern used by OpenAI and Gemini chat nodes. Changes: - Add chat API models (request/response) to apis/minimax.py - Add MinimaxChatNode with system prompt, temperature, and max_tokens support - Register the new node in MinimaxExtension
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughAdded a public node class 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 📝 Coding Plan
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@comfy_api_nodes/nodes_minimax.py`:
- Around line 551-553: The current code in nodes_minimax.py returns
IO.NodeOutput("No response generated by MiniMax model.") when response.choices
is empty, which masks API failures; instead, change the behavior in the function
that handles the MiniMax API response so that if response.choices is falsy you
raise an exception (e.g., RuntimeError or a custom exception) with a clear
message including any available response metadata (e.g., the raw response or
status) rather than returning IO.NodeOutput; update the branch that currently
checks response.choices and replace the fallback return with a raised error to
surface API anomalies consistently.
- Around line 524-548: The execute method forwards the model string unchecked;
validate that the provided model is a member of MiniMaxChatModel before sending
the request so invalid values fail fast. Add a local validation in
MiniMaxChatNode.execute (or the listed async execute) right after
validate_string(prompt...) that checks if model is one of MiniMaxChatModel.* (or
use MiniMaxChatModel(model) / an explicit membership check) and raise a clear
ValueError/IO.NodeError if not; only proceed to build messages and call sync_op
when the model is valid.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 1736802c-61fd-461c-aa83-08868760e74c
⛔ Files ignored due to path filters (1)
comfy_api_nodes/apis/minimax.pyis excluded by!comfy_api_nodes/apis/**
📒 Files selected for processing (1)
comfy_api_nodes/nodes_minimax.py
- Validate `model` parameter against MiniMaxChatModel enum before forwarding to the API request, preventing invalid model strings. - Raise RuntimeError instead of returning a fallback string when the API returns empty choices, surfacing failures consistently. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Thanks for the review feedback! I've pushed a fix (c01e019) addressing both issues:
|
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@comfy_api_nodes/nodes_minimax.py`:
- Around line 539-552: The MiniMax chat request currently omits the
reasoning_split flag so message.content can contain <think> reasoning tags;
update the MiniMaxChatRequest constructed where sync_op is called (the call that
builds MiniMaxChatRequest with model=MiniMaxChatModel(model).value,
messages=messages, max_tokens=max_tokens, temperature=temperature) to include
reasoning_split=True so the API strips <think> markup before returning content
to be wrapped in IO.NodeOutput; ensure this change is applied to the
MiniMaxChatRequest used in the ApiEndpoint("/proxy/minimax/chat/completions",
method="POST") call that expects MiniMaxChatResponse.
- Around line 503-520: The price badge values for MiniMax in the IO.PriceBadge
expression are outdated; update the USD per-1K token arrays to match MiniMax API
pricing by replacing the current usd arrays in the expression for the two
branches: for the "highspeed" branch (when $contains(widgets.model,
"highspeed")) set usd to [0.0006, 0.0024], and for the default branch set usd to
[0.0003, 0.0012]; keep the surrounding structure (price_badge = IO.PriceBadge,
depends_on = IO.PriceBadgeDepends(widgets=["model"]), and the expr using $m :=
widgets.model and $contains) unchanged.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: f7328424-41f5-4c4c-b817-edbd1d445259
📒 Files selected for processing (1)
comfy_api_nodes/nodes_minimax.py
| price_badge=IO.PriceBadge( | ||
| depends_on=IO.PriceBadgeDepends(widgets=["model"]), | ||
| expr=""" | ||
| ( | ||
| $m := widgets.model; | ||
| $contains($m, "highspeed") ? { | ||
| "type": "list_usd", | ||
| "usd": [0.00004, 0.0002], | ||
| "format": { "approximate": true, "separator": "-", "suffix": " per 1K tokens" } | ||
| } | ||
| : { | ||
| "type": "list_usd", | ||
| "usd": [0.0001, 0.0006], | ||
| "format": { "approximate": true, "separator": "-", "suffix": " per 1K tokens" } | ||
| } | ||
| ) | ||
| """, | ||
| ), |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's confirm the file exists and examine the relevant section
cat -n comfy_api_nodes/nodes_minimax.py | sed -n '500,525p'Repository: Comfy-Org/ComfyUI
Length of output: 1113
🌐 Web query:
MiniMax M2.5 API pricing per token cost 2024 2025
💡 Result:
MiniMax M2.5 token pricing you’ll see published publicly is not a 2024/2025 price—MiniMax’s official pay‑as‑you‑go table listing MiniMax‑M2.5 appears in the current docs/pricing pages (live as of March 2026). [1]
Official MiniMax pay‑as‑you‑go (CNY)
Prices are shown as 元 / 1,000,000 tokens: [1]
- Input: ¥2.1 / 1M tokens → ¥0.0000021 per token
- Output: ¥8.4 / 1M tokens → ¥0.0000084 per token
- (Also listed) Cache read: ¥0.21 / 1M; Cache write: ¥2.625 / 1M. [1]
Common USD quotes (third‑party trackers, for reference)
Artificial Analysis lists MiniMax‑M2.5 at: [2]
- $0.30 / 1M input tokens (=$0.00000030/token)
- $1.20 / 1M output tokens (=$0.00000120/token)
If you specifically need what MiniMax charged in 2024 or 2025, you’ll likely need an archived snapshot or a dated MiniMax announcement—because M2.5 pricing as such doesn’t appear to be a 2024/2025 item on the current official pages. [1]
Sources: [1] MiniMax Open Platform docs – Pay‑as‑you‑go pricing table (文本/按量计费) (platform.minimaxi.com) • [2] Artificial Analysis – MiniMax‑M2.5 pricing (artificialanalysis.ai)
🌐 Web query:
MiniMax M2.5 highspeed model pricing API cost
💡 Result:
MiniMax M2.5-highspeed API cost (Pay‑as‑you‑go)
From MiniMax’s pay‑as‑you‑go pricing table (prices in CNY per 1M tokens): Input ¥4.2 / 1M, Output ¥16.8 / 1M; cache read ¥0.21 / 1M, cache write ¥2.625 / 1M. [1]
Approximate USD equivalents (using ~¥6.88 per $1): input ~$0.61 / 1M, output ~$2.44 / 1M, cache read ~$0.03 / 1M, cache write ~$0.38 / 1M. [1][2]
(Reference) MiniMax M2.5 (non‑highspeed) PAYG
Input ¥2.1 / 1M (~$0.31), Output ¥8.4 / 1M (~$1.22). [1][2]
If you meant the Coding Plan (subscription, not per-token)
Plans that include MiniMax M2.5-highspeed are $40 / $80 / $150 per month (300 / 1000 / 2000 prompts per 5 hours). [3]
Sources: [1] MiniMax PAYG pricing table, [2] USD/CNY rate reference, [3] MiniMax Coding Plan pricing.
🏁 Script executed:
# Check if this node and price_badge are new additions
git log -1 --oneline comfy_api_nodes/nodes_minimax.py
git diff HEAD~1 comfy_api_nodes/nodes_minimax.py | head -100Repository: Comfy-Org/ComfyUI
Length of output: 339
🏁 Script executed:
# Check the structure to confirm this is new code
git status comfy_api_nodes/nodes_minimax.py
git log --oneline -5 comfy_api_nodes/nodes_minimax.pyRepository: Comfy-Org/ComfyUI
Length of output: 201
Update price badge values to match current MiniMax API pricing.
The per-1K token amounts are materially below official rates. MiniMax's current pay-as-you-go pricing is $0.30/$1.20 per 1M tokens for M2.5 and $0.61/$2.44 per 1M tokens for M2.5-highspeed, which translates to $0.0003/$0.0012 and $0.0006/$0.0024 per 1K tokens respectively.
Suggested patch
(
$m := widgets.model;
$contains($m, "highspeed") ? {
"type": "list_usd",
- "usd": [0.00004, 0.0002],
+ "usd": [0.0006, 0.0024],
"format": { "approximate": true, "separator": "-", "suffix": " per 1K tokens" }
}
: {
"type": "list_usd",
- "usd": [0.0001, 0.0006],
+ "usd": [0.0003, 0.0012],
"format": { "approximate": true, "separator": "-", "suffix": " per 1K tokens" }
}
)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@comfy_api_nodes/nodes_minimax.py` around lines 503 - 520, The price badge
values for MiniMax in the IO.PriceBadge expression are outdated; update the USD
per-1K token arrays to match MiniMax API pricing by replacing the current usd
arrays in the expression for the two branches: for the "highspeed" branch (when
$contains(widgets.model, "highspeed")) set usd to [0.0006, 0.0024], and for the
default branch set usd to [0.0003, 0.0012]; keep the surrounding structure
(price_badge = IO.PriceBadge, depends_on =
IO.PriceBadgeDepends(widgets=["model"]), and the expr using $m := widgets.model
and $contains) unchanged.
| response = await sync_op( | ||
| cls, | ||
| ApiEndpoint(path="/proxy/minimax/chat/completions", method="POST"), | ||
| response_model=MiniMaxChatResponse, | ||
| data=MiniMaxChatRequest( | ||
| model=MiniMaxChatModel(model).value, | ||
| messages=messages, | ||
| max_tokens=max_tokens, | ||
| temperature=temperature, | ||
| ), | ||
| ) | ||
|
|
||
| if response.choices: | ||
| return IO.NodeOutput(response.choices[0].message.content) |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's find and examine the MiniMax-related files
find . -name "*minimax*" -type f | head -20Repository: Comfy-Org/ComfyUI
Length of output: 129
🏁 Script executed:
# Let's examine the MiniMax API models file
wc -l ./comfy_api_nodes/apis/minimax.pyRepository: Comfy-Org/ComfyUI
Length of output: 98
🏁 Script executed:
# And the nodes file
wc -l ./comfy_api_nodes/nodes_minimax.pyRepository: Comfy-Org/ComfyUI
Length of output: 99
🏁 Script executed:
# Read the MiniMaxChatRequest definition
cat -n ./comfy_api_nodes/apis/minimax.py | grep -A 50 "class MiniMaxChatRequest"Repository: Comfy-Org/ComfyUI
Length of output: 1685
🏁 Script executed:
# Read the execute method from nodes_minimax.py around lines 539-552
sed -n '530,560p' ./comfy_api_nodes/nodes_minimax.pyRepository: Comfy-Org/ComfyUI
Length of output: 1157
🏁 Script executed:
# Check git status and history to see if this code is new
cd ./comfy_api_nodes && git log --oneline -20 -- nodes_minimax.pyRepository: Comfy-Org/ComfyUI
Length of output: 135
🏁 Script executed:
# Check if reasoning_split field was previously in the file
git log -p -- comfy_api_nodes/apis/minimax.py | grep -A 20 "reasoning_split" | head -30Repository: Comfy-Org/ComfyUI
Length of output: 43
🏁 Script executed:
# Get more context about the MinimaxChatNode.execute method - find the full function
sed -n '520,560p' ./comfy_api_nodes/nodes_minimax.pyRepository: Comfy-Org/ComfyUI
Length of output: 1384
🏁 Script executed:
# Check the actual diff of the recent commit
git show c01e019 -- comfy_api_nodes/nodes_minimax.py | head -100Repository: Comfy-Org/ComfyUI
Length of output: 3387
🏁 Script executed:
# Also check if there are any references to <think> or reasoning in the codebase
rg -i "think|reasoning" comfy_api_nodes/Repository: Comfy-Org/ComfyUI
Length of output: 2830
🌐 Web query:
MiniMax API OpenAI compatible chat completions <think> markup reasoning_split parameter
💡 Result:
MiniMax’s OpenAI-compatible Chat Completions endpoint (/v1/chat/completions) can return interleaved thinking markup (e.g., <think>...</think>) in the assistant message.content for models like MiniMax-M2.5 / M2.1 / M2 (and their highspeed variants). MiniMax’s docs say that if you see <think> content in content, you must preserve it completely when storing/replaying conversation history. [1]
To avoid having <think> appear inside message.content, enable Interleaved Thinking compatible format by passing the extra parameter:
reasoning_split: true(akareasoning_split=Truein SDKs)
Then the model’s thinking is provided separately in message.reasoning_details (which also must be preserved completely), while message.content is the user-facing answer. [1][2]
Example (OpenAI SDK-style):
from openai import OpenAI
client = OpenAI(
api_key="YOUR_MINIMAX_KEY",
base_url="https://api.minimax.io/v1",
)
resp = client.chat.completions.create(
model="MiniMax-M2.5",
messages=[{"role":"user","content":"Explain X briefly."}],
extra_body={"reasoning_split": True},
)This “split thinking into reasoning_details via reasoning_split=True” behavior is explicitly documented by MiniMax. [1][2][3]
Sources: MiniMax OpenAI-compatible API docs (including <think> handling and reasoning_split → reasoning_details) [1], MiniMax “Tool Use & Interleaved Thinking” docs [2], MiniMax M2.5 release technical read (compatibility + reasoning_split) [3].
References: [1] (platform.minimax.io) [2] (platform.minimax.io) [3] (atoms.dev)
Citations:
- 1: https://platform.minimax.io/docs/api-reference/text-openai-api?utm_source=openai
- 2: https://platform.minimax.io/docs/api-reference/text-m2-function-call-refer?utm_source=openai
- 3: https://atoms.dev/blog/minimax-m2-5-official-release?utm_source=openai
🌐 Web query:
MiniMax M2.5 model reasoning content OpenAI API documentation
💡 Result:
MiniMax M2.5’s OpenAI-compatible Chat Completions endpoint does not use OpenAI’s documented “reasoning items” schema. Instead, MiniMax injects the model’s reasoning into the normal message.content as <think>…</think>, and MiniMax explicitly says you must preserve that <think> block verbatim in the conversation history (especially for multi-turn/tool use), because the OpenAI ChatCompletions format has no native place for it. [1], [2]
In OpenAI’s own API documentation, “reasoning content/state” is handled in the Responses API as dedicated reasoning items/streaming events (e.g., response.reasoning_text.*) and optionally encrypted reasoning you can request via include: ["reasoning.encrypted_content"] and pass back on later turns—this is separate from content and is not expressed as <think> tags. [3], [4], [5]
So: if you’re using MiniMax M2.5 via an OpenAI-compatible Chat Completions API, follow MiniMax’s docs for <think> handling; if you want OpenAI’s documented reasoning mechanism, use OpenAI’s Responses API reasoning items/encrypted content flow. [1], [3]
Sources:
[1] MiniMax “Compatible OpenAI API” docs (OpenAI-compatible endpoint; <think> in content)
[2] MiniMax “Tool Use & Interleaved Thinking” docs (why <think> is used in OpenAI-native format)
[3] OpenAI API Reference — Responses (reasoning items / reasoning.encrypted_content)
[4] OpenAI API Reference — Responses streaming (response.reasoning_text.*)
[5] OpenAI Cookbook — Responses API reasoning items (include=["reasoning.encrypted_content"])
Set reasoning_split=True to exclude <think> markup from node output.
MiniMax's OpenAI-compatible API includes <think> reasoning markup directly in message.content for MiniMax-M2.5 models by default. Without reasoning_split=True, the node will return raw reasoning tags to users. This requires adding the reasoning_split field to MiniMaxChatRequest and enabling it in the request. (platform.minimax.io)
Suggested fix
# comfy_api_nodes/apis/minimax.py
class MiniMaxChatRequest(BaseModel):
model: str = Field(..., description='ID of the model to use.')
messages: list[MiniMaxChatMessage] = Field(..., description='A list of messages comprising the conversation.')
max_tokens: Optional[int] = Field(None, description='The maximum number of tokens to generate.')
temperature: Optional[float] = Field(
None,
description='Sampling temperature. Must be between 0 (exclusive) and 1 (inclusive).',
gt=0.0,
le=1.0,
)
+ reasoning_split: Optional[bool] = Field(
+ None,
+ description='Return reasoning separately from content for the OpenAI-compatible MiniMax API.',
+ )
# comfy_api_nodes/nodes_minimax.py
data=MiniMaxChatRequest(
model=MiniMaxChatModel(model).value,
messages=messages,
max_tokens=max_tokens,
temperature=temperature,
+ reasoning_split=True,
),🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@comfy_api_nodes/nodes_minimax.py` around lines 539 - 552, The MiniMax chat
request currently omits the reasoning_split flag so message.content can contain
<think> reasoning tags; update the MiniMaxChatRequest constructed where sync_op
is called (the call that builds MiniMaxChatRequest with
model=MiniMaxChatModel(model).value, messages=messages, max_tokens=max_tokens,
temperature=temperature) to include reasoning_split=True so the API strips
<think> markup before returning content to be wrapped in IO.NodeOutput; ensure
this change is applied to the MiniMaxChatRequest used in the
ApiEndpoint("/proxy/minimax/chat/completions", method="POST") call that expects
MiniMaxChatResponse.
|
We would need the actual proxy implementation in our backend for this to work right |
- Add MiniMax-M2.7 and MiniMax-M2.7-highspeed to chat model list - Set MiniMax-M2.7 as default model (replacing M2.5) - Keep all previous models as available alternatives
- Add MiniMax-M2.7 and MiniMax-M2.7-highspeed to model list - Set MiniMax-M2.7 as default model - Keep all previous models as alternatives - Add unit tests for model configuration
|
Thanks for the feedback @christian-byrne! You're right - this PR only adds the frontend/node configuration. I'd be happy to implement the actual proxy backend as well if you can point me to the right location in the codebase for adding new provider backends. Alternatively, I can close this and resubmit once the backend implementation is included. |
Summary
Add a new MiniMax Chat node for text generation using MiniMax language models.
Changes
Why
MiniMax provides high-quality language models through an OpenAI-compatible API. The M2.7 model is the latest flagship with improved performance.
Testing
API Node PR Checklist
Scope
Pricing & Billing
If Need pricing update:
QA
Comms