feat(llm): add MiniMax GroupId header support (#14610)

## Summary
- Add MiniMax provider GroupId query parameter support in `LiteLLMBase`
- Extract `group_id` from key configuration in `__init__`
- Append `GroupId` as query parameter to `api_base` in
`_construct_complete_args`

## Why this change is needed

MiniMax provides an OpenAI-compatible API endpoint
(`/v1/chat/completions`), but `GroupId` is a MiniMax-specific account
identifier required for billing and rate limiting - it is not part of
the OpenAI standard.

Looking at LiteLLM's `MinimaxChatConfig`:
- `get_complete_url()` only constructs the base URL (e.g.,
`https://api.minimaxi.com/v1/chat/completions`)
- LiteLLM does **not** automatically inject `GroupId` into requests
- This must be handled by the caller (ragflow's chat_model.py)

The implementation appends `GroupId` as a query parameter to `api_base`:
```python
api_base = completion_args.get("api_base", self.base_url)
separator = "&" if "?" in api_base else "?"
completion_args["api_base"] = f"{api_base}{separator}GroupId={self.group_id}"
```

This matches MiniMax's official API format (as documented by
LlamaFactory):
```bash
curl --location 'https://api.minimaxi.chat/v1/text/chatcompletion?GroupId=你的GroupId' \
  --header 'Authorization: Bearer 你的API_Key'
```

## Test plan
- [ ] Verify MiniMax API calls work with GroupId query parameter
- [ ] Verify backward compatibility for other providers

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Zhichang Yu
2026-05-07 11:54:49 +08:00
committed by GitHub
parent 12f80f170c
commit 86fe78c73f

View File

@@ -1298,6 +1298,17 @@ class LiteLLMBase(ABC):
elif self.provider == SupportedLiteLLMProvider.Azure_OpenAI:
self.api_key = json.loads(key).get("api_key", "")
self.api_version = json.loads(key).get("api_version", "2024-02-01")
elif self.provider == SupportedLiteLLMProvider.MiniMax:
# MiniMax requires GroupId as a query parameter for API authentication
try:
key_obj = json.loads(key) if isinstance(key, str) else key
self.api_key = key_obj.get("api_key", key) if isinstance(key_obj, dict) else key
self.group_id = key_obj.get("group_id", "") if isinstance(key_obj, dict) else ""
except (json.JSONDecodeError, TypeError):
self.api_key = key
self.group_id = ""
else:
self.group_id = ""
def _get_delay(self):
return self.base_delay * random.uniform(10, 150)
@@ -1848,6 +1859,11 @@ class LiteLLMBase(ABC):
extra_headers = deepcopy(completion_args.get("extra_headers") or {})
if self.provider == SupportedLiteLLMProvider.Ollama and self.api_key and "Authorization" not in extra_headers:
extra_headers["Authorization"] = f"Bearer {self.api_key}"
# MiniMax requires GroupId as a query parameter for API authentication
if self.provider == SupportedLiteLLMProvider.MiniMax and hasattr(self, 'group_id') and self.group_id:
api_base = completion_args.get("api_base", self.base_url)
separator = "&" if "?" in api_base else "?"
completion_args["api_base"] = f"{api_base}{separator}GroupId={self.group_id}"
if extra_headers:
completion_args["extra_headers"] = extra_headers
return completion_args