Skip to content

Commit 9af95ae

Browse files
Improve MiniMax endpoint selection and response parsing
Update MiniMax provider and URL utilities to better handle region-specific endpoints and response formats. Changes: - config.py: set default model to "MiniMax-M2.1" and update default API URL to the .com endpoint. - providers/minimax.py: import re, switch to a smart endpoint selector (get_working_minimax_endpoint), update log messages, and strip <think>...</think> reasoning blocks from responses before processing. - url_utils.py: export get_working_minimax_endpoint and implement it; this function probes MiniMax .com and .chat endpoints using an auth test (checks base_resp for status) and falls back to the domestic endpoint if none accept the key. Also update __all__ accordingly. Rationale: MiniMax uses region/key-specific endpoints that require auth-based checks rather than simple connectivity tests. These changes improve reliability by selecting a compatible endpoint and cleaning out embedded reasoning blocks from model outputs.
1 parent 12fda15 commit 9af95ae

3 files changed

Lines changed: 76 additions & 7 deletions

File tree

python/mllmcelltype/config.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,9 @@ class ProviderConfig:
6363
default_api_url="https://open.bigmodel.cn/api/paas/v4/chat/completions",
6464
),
6565
"minimax": ProviderConfig(
66-
default_model="minimax-m2.1",
66+
default_model="MiniMax-M2.1",
6767
api_key_env_var="MINIMAX_API_KEY",
68-
default_api_url="https://api.minimaxi.chat/v1/text/chatcompletion_v2",
68+
default_api_url="https://api.minimaxi.com/v1/chat/completions",
6969
),
7070
"grok": ProviderConfig(
7171
default_model="grok-4",

python/mllmcelltype/providers/minimax.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@
33
from __future__ import annotations
44

55
import json
6+
import re
67
import time
78

89
import requests
910

1011
from ..logger import write_log
11-
from ..url_utils import get_default_api_url, validate_base_url
12+
from ..url_utils import get_working_minimax_endpoint, validate_base_url
1213

1314

1415
def process_minimax(
@@ -34,15 +35,15 @@ def process_minimax(
3435
write_log(error_msg, level="error")
3536
raise ValueError(error_msg)
3637

37-
# Use custom URL or default URL
38+
# Use custom URL or smart selection
3839
if base_url:
3940
if not validate_base_url(base_url):
4041
raise ValueError(f"Invalid base URL: {base_url}")
4142
url = base_url
4243
write_log(f"Using custom base URL: {url}")
4344
else:
44-
url = get_default_api_url("minimax")
45-
write_log(f"Using default URL: {url}")
45+
url = get_working_minimax_endpoint(api_key)
46+
write_log(f"Using smart-selected endpoint: {url}")
4647

4748
write_log(f"Using model: {model}")
4849
write_log(f"API URL: {url}")
@@ -119,6 +120,10 @@ def process_minimax(
119120
and "content" in choices[0]["message"]
120121
):
121122
response_content = choices[0]["message"]["content"]
123+
# Strip <think>...</think> reasoning block (MiniMax M2.1 Coding Plan)
124+
response_content = re.sub(
125+
r"<think>[\s\S]*?</think>\s*", "", response_content
126+
)
122127
res = response_content.strip().split("\n")
123128
else:
124129
write_log(f"Unexpected response format: {content}")

python/mllmcelltype/url_utils.py

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,13 @@
99

1010
# Re-export get_default_api_url for backward compatibility
1111
# The actual implementation is in config.py (Single Source of Truth)
12-
__all__ = ["get_default_api_url", "get_working_qwen_endpoint", "resolve_provider_base_url", "validate_base_url"]
12+
__all__ = [
13+
"get_default_api_url",
14+
"get_working_minimax_endpoint",
15+
"get_working_qwen_endpoint",
16+
"resolve_provider_base_url",
17+
"validate_base_url",
18+
]
1319

1420

1521
def resolve_provider_base_url(provider: str, base_urls: str | dict | None) -> str | None:
@@ -54,6 +60,64 @@ def validate_base_url(url: str) -> bool:
5460
return url.startswith("http://") or url.startswith("https://")
5561

5662

63+
def get_working_minimax_endpoint(api_key: str) -> str:
64+
"""Smart endpoint selection for MiniMax.
65+
66+
MiniMax has region-specific endpoints that only accept keys issued for
67+
that region (e.g. Coding Plan ``sk-cp-`` keys work on the domestic
68+
``.com`` endpoint but not on the international ``.chat`` endpoint).
69+
Unlike Qwen where any key works on any reachable endpoint, MiniMax
70+
requires matching the key to its endpoint, so we test authentication
71+
rather than mere connectivity.
72+
73+
Args:
74+
api_key: MiniMax API key
75+
76+
Returns:
77+
Working endpoint URL
78+
"""
79+
endpoints = [
80+
"https://api.minimaxi.com/v1/chat/completions", # Domestic (China)
81+
"https://api.minimaxi.chat/v1/chat/completions", # International
82+
]
83+
84+
write_log("Testing MiniMax endpoint compatibility...", level="debug")
85+
86+
for endpoint in endpoints:
87+
try:
88+
headers = {"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"}
89+
test_body = {
90+
"model": "MiniMax-M2.1",
91+
"messages": [{"role": "user", "content": "test"}],
92+
"max_tokens": 1,
93+
}
94+
response = requests.post(endpoint, headers=headers, json=test_body, timeout=5)
95+
96+
# MiniMax returns HTTP 200 even for auth errors; check base_resp
97+
if response.status_code == 200:
98+
data = response.json()
99+
base_resp = data.get("base_resp", {})
100+
status_code = base_resp.get("status_code", 0)
101+
if status_code == 0:
102+
write_log(f"MiniMax endpoint accepted key: {endpoint}", level="debug")
103+
return endpoint
104+
write_log(
105+
f"MiniMax endpoint rejected key ({base_resp.get('status_msg', '')}): {endpoint}",
106+
level="debug",
107+
)
108+
else:
109+
write_log(
110+
f"MiniMax endpoint returned HTTP {response.status_code}: {endpoint}",
111+
level="debug",
112+
)
113+
except Exception:
114+
write_log(f"MiniMax endpoint unreachable: {endpoint}", level="debug")
115+
116+
# Fallback to domestic endpoint
117+
write_log("No MiniMax endpoint accepted the key, using domestic endpoint as fallback")
118+
return endpoints[0]
119+
120+
57121
def get_working_qwen_endpoint(api_key: str) -> str:
58122
"""Smart endpoint selection for Qwen.
59123

0 commit comments

Comments
 (0)