-
Notifications
You must be signed in to change notification settings - Fork 670
feat: add MiniMax as a model provider (default M3) #2717
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,115 @@ | ||
| import httpx | ||
| from typing import Dict, List | ||
|
|
||
| from consts.const import DEFAULT_LLM_MAX_TOKENS | ||
| from consts.provider import MINIMAX_GET_URL | ||
| from services.providers.base import AbstractModelProvider, _classify_provider_error | ||
|
|
||
|
|
||
| # MiniMax known model context windows (tokens) | ||
| MINIMAX_MODEL_CONTEXT = { | ||
| "MiniMax-M3": 512000, | ||
| "MiniMax-M2.7": 192000, | ||
| "MiniMax-M2.7-highspeed": 192000, | ||
| } | ||
|
|
||
|
|
||
| class MiniMaxModelProvider(AbstractModelProvider): | ||
| """Concrete implementation for MiniMax provider.""" | ||
|
|
||
| async def get_models(self, provider_config: Dict) -> List[Dict]: | ||
|
Check failure on line 20 in backend/services/providers/minimax_provider.py
|
||
| """ | ||
| Fetch models from MiniMax API, categorize them based on model ID, | ||
| and return the requested model type. | ||
|
|
||
| Args: | ||
| provider_config: Configuration dict containing model_type and api_key | ||
|
|
||
| Returns: | ||
| List of models with canonical fields. Returns error dict if API call fails. | ||
| """ | ||
| try: | ||
| target_model_type: str = provider_config["model_type"] | ||
| model_api_key: str = provider_config["api_key"] | ||
| # Default SSL verification to True; can be disabled via provider config. | ||
| ssl_verify: bool = provider_config.get("ssl_verify", True) | ||
|
|
||
| headers = {"Authorization": f"Bearer {model_api_key}"} | ||
| url = MINIMAX_GET_URL | ||
|
|
||
| async with httpx.AsyncClient(verify=ssl_verify, timeout=15.0) as client: | ||
| response = await client.get(url, headers=headers) | ||
| response.raise_for_status() | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 缺少 timeout 配置:
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed in c38ef2c — added |
||
| all_models: List[Dict] = response.json().get("data", []) | ||
|
|
||
| # Initialize containers for the main categories | ||
| categorized_models = { | ||
| "chat": [], # Maps to "llm" | ||
| "vlm": [], # Maps to "vlm" | ||
| "embedding": [], # Maps to "embedding" / "multi_embedding" | ||
| "reranker": [], # Maps to "reranker" | ||
| "tts": [], # Maps to "tts" | ||
| "stt": [] # Maps to "stt" | ||
| } | ||
|
|
||
| for model_obj in all_models: | ||
| m_id = model_obj.get("id", "") | ||
| m_id_lower = m_id.lower() | ||
| model_obj.setdefault("object", "model") | ||
| model_obj.setdefault("owned_by", "minimax") | ||
|
|
||
| # Use known context window or default | ||
| max_tokens = MINIMAX_MODEL_CONTEXT.get(m_id, DEFAULT_LLM_MAX_TOKENS) | ||
|
|
||
| cleaned_model = { | ||
| "id": m_id, | ||
| "object": model_obj.get("object"), | ||
| "created": model_obj.get("created", 0), | ||
| "owned_by": model_obj.get("owned_by"), | ||
| "model_tag": "", | ||
| "model_type": "", | ||
| "max_tokens": max_tokens, | ||
| } | ||
|
|
||
| # 1. Embedding | ||
| if "embo" in m_id_lower or "embedding" in m_id_lower: | ||
| cleaned_model.update({"model_tag": "embedding", "model_type": "embedding"}) | ||
| categorized_models["embedding"].append(cleaned_model) | ||
|
|
||
| # 2. TTS (speech models) | ||
| elif "speech" in m_id_lower or "tts" in m_id_lower: | ||
| cleaned_model.update({"model_tag": "tts", "model_type": "tts"}) | ||
| categorized_models["tts"].append(cleaned_model) | ||
|
|
||
| # 3. STT | ||
| elif "stt" in m_id_lower or "whisper" in m_id_lower: | ||
| cleaned_model.update({"model_tag": "stt", "model_type": "stt"}) | ||
| categorized_models["stt"].append(cleaned_model) | ||
|
|
||
| # 4. Reranker | ||
| elif "rerank" in m_id_lower: | ||
| cleaned_model.update({"model_tag": "reranker", "model_type": "reranker"}) | ||
| categorized_models["reranker"].append(cleaned_model) | ||
|
|
||
| # 5. VLM | ||
| elif any(kw in m_id_lower for kw in ["-vl", "vl-", "vision"]): | ||
| cleaned_model.update({"model_tag": "chat", "model_type": "vlm"}) | ||
| categorized_models["vlm"].append(cleaned_model) | ||
|
|
||
| # 6. Chat / LLM (default fallback) | ||
| else: | ||
| cleaned_model.update({"model_tag": "chat", "model_type": "llm"}) | ||
| categorized_models["chat"].append(cleaned_model) | ||
|
|
||
| # Return the specific list based on the requested target_model_type | ||
| if target_model_type == "llm": | ||
| return categorized_models["chat"] | ||
| elif target_model_type in ("embedding", "multi_embedding"): | ||
| return categorized_models["embedding"] | ||
| elif target_model_type in categorized_models: | ||
| return categorized_models[target_model_type] | ||
| else: | ||
| return [] | ||
|
|
||
| except (httpx.HTTPStatusError, httpx.ConnectTimeout, httpx.ConnectError, Exception) as e: | ||
| return _classify_provider_error("MiniMax", exception=e) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
安全风险:
verify=False禁用了 SSL 证书验证,生产环境下容易遭受中间人攻击。建议从配置读取或默认为True。There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch — fixed in c38ef2c.
verifynow comes fromprovider_config.get("ssl_verify", True), so it defaults to True and can only be disabled by explicit operator opt-in (matching the existingssl_verifyconfig flow elsewhere in the codebase).