From 7d285ab28083abcb5c27505c99571ed1959de9e6 Mon Sep 17 00:00:00 2001 From: octo-patch <266937838+octo-patch@users.noreply.github.com> Date: Thu, 9 Jul 2026 10:33:13 +0000 Subject: [PATCH 1/2] Add MiniMax provider support --- README.md | 9 +++- pyproject.toml | 1 + simplemind/providers/__init__.py | 7 ++- simplemind/providers/minimax.py | 74 ++++++++++++++++++++++++++++++++ simplemind/settings.py | 4 ++ tests/test_minimax.py | 41 ++++++++++++++++++ 6 files changed, 134 insertions(+), 2 deletions(-) create mode 100644 simplemind/providers/minimax.py create mode 100644 tests/test_minimax.py diff --git a/README.md b/README.md index c84fb1d..76c6cc7 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,11 @@ The APIs remain identical between all supported providers / models: "ollama" "llama3.2" + + MiniMax + "minimax" / "minimax-anthropic" + "MiniMax-M3" + OpenAI's GPT "openai" @@ -70,6 +75,8 @@ The APIs remain identical between all supported providers / models: +MiniMax supports the `MiniMax-M3` and `MiniMax-M2.7` model IDs. The `minimax` provider uses its OpenAI-compatible API and `minimax-anthropic` uses its Anthropic-compatible API. Set `MINIMAX_API_REGION` to `global_en` (the default) for `https://api.minimax.io/v1` and `https://api.minimax.io/anthropic/v1`, or to `cn_zh` for `https://api.minimaxi.com/v1` and `https://api.minimaxi.com/anthropic/v1`. See the [global](https://platform.minimax.io/docs) or [mainland China](https://platform.minimaxi.com/docs) documentation for details. + To specify a specific provider or model, you can use the `llm_provider` and `llm_model` parameters when calling: `generate_text`, `generate_data`, or `create_conversation`. If you want to see Simplemind support additional providers or models, please send a pull request! @@ -88,7 +95,7 @@ First, authenticate your API keys by setting them in the environment variables: $ export OPENAI_API_KEY="sk-..." ``` -This pattern allows you to keep your API keys private and out of your codebase. Other supported environment variables: `ANTHROPIC_API_KEY`, `XAI_API_KEY`, `DEEPSEEK_API_KEY`, `GROQ_API_KEY`, and `GEMINI_API_KEY`. +This pattern allows you to keep your API keys private and out of your codebase. Other supported environment variables: `ANTHROPIC_API_KEY`, `XAI_API_KEY`, `DEEPSEEK_API_KEY`, `GROQ_API_KEY`, `GEMINI_API_KEY`, and `MINIMAX_API_KEY`. Next, import Simplemind and start using it: diff --git a/pyproject.toml b/pyproject.toml index 3da756e..98acd25 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,6 +21,7 @@ gemini = ["google-generativeai", "jsonref"] groq = ["groq"] ollama = ["openai"] openai = ["openai"] +minimax = ["openai", "anthropic"] xai = ["openai"] deepseek = ["openai"] diff --git a/simplemind/providers/__init__.py b/simplemind/providers/__init__.py index c588b5a..a2cbf94 100644 --- a/simplemind/providers/__init__.py +++ b/simplemind/providers/__init__.py @@ -6,6 +6,7 @@ from .anthropic import Anthropic from .gemini import Gemini from .groq import Groq +from .minimax import MiniMax, MiniMaxAnthropic from .ollama import Ollama from .openai import OpenAI from .xai import XAI @@ -20,6 +21,8 @@ XAI, Amazon, Deepseek, + MiniMax, + MiniMaxAnthropic, ] __all__ = [ @@ -33,5 +36,7 @@ "providers", "BaseProvider", "BaseTool", - "Deepseek" + "Deepseek", + "MiniMax", + "MiniMaxAnthropic", ] diff --git a/simplemind/providers/minimax.py b/simplemind/providers/minimax.py new file mode 100644 index 0000000..58128f0 --- /dev/null +++ b/simplemind/providers/minimax.py @@ -0,0 +1,74 @@ +from functools import cached_property + +from ..settings import settings +from .anthropic import Anthropic +from .openai import OpenAI + + +class _MiniMaxConfig: + MODEL_IDS = ("MiniMax-M3", "MiniMax-M2.7") + ENDPOINTS = { + "global_en": { + "openai": "https://api.minimax.io/v1", + "anthropic": "https://api.minimax.io/anthropic/v1", + }, + "cn_zh": { + "openai": "https://api.minimaxi.com/v1", + "anthropic": "https://api.minimaxi.com/anthropic/v1", + }, + } + + def _configure(self, api_key: str | None, region: str | None) -> None: + self.api_key = api_key or settings.get_api_key("minimax") + self.region = region or settings.MINIMAX_API_REGION + if self.region not in self.ENDPOINTS: + regions = ", ".join(self.ENDPOINTS) + raise ValueError(f"MiniMax API region must be one of: {regions}") + + +class MiniMax(_MiniMaxConfig, OpenAI): + NAME = "minimax" + DEFAULT_MODEL = "MiniMax-M3" + + def __init__(self, api_key: str | None = None, region: str | None = None): + self._configure(api_key, region) + + @cached_property + def client(self): + """The raw OpenAI-compatible MiniMax client.""" + if not self.api_key: + raise ValueError("MiniMax API key is required") + try: + import openai as oa + except ImportError as exc: + raise ImportError( + "Please install the `openai` package: `pip install openai`" + ) from exc + return oa.OpenAI( + api_key=self.api_key, + base_url=self.ENDPOINTS[self.region]["openai"], + ) + + +class MiniMaxAnthropic(_MiniMaxConfig, Anthropic): + NAME = "minimax-anthropic" + DEFAULT_MODEL = "MiniMax-M3" + + def __init__(self, api_key: str | None = None, region: str | None = None): + self._configure(api_key, region) + + @cached_property + def client(self): + """The raw Anthropic-compatible MiniMax client.""" + if not self.api_key: + raise ValueError("MiniMax API key is required") + try: + import anthropic + except ImportError as exc: + raise ImportError( + "Please install the `anthropic` package: `pip install anthropic`" + ) from exc + return anthropic.Anthropic( + api_key=self.api_key, + base_url=self.ENDPOINTS[self.region]["anthropic"], + ) diff --git a/simplemind/settings.py b/simplemind/settings.py index de69339..e9904db 100644 --- a/simplemind/settings.py +++ b/simplemind/settings.py @@ -50,6 +50,10 @@ class Settings(BaseSettings): GROQ_API_KEY: Optional[SecretStr] = Field(None, description="API key for Groq") GEMINI_API_KEY: Optional[SecretStr] = Field(None, description="API key for Gemini") OPENAI_API_KEY: Optional[SecretStr] = Field(None, description="API key for OpenAI") + MINIMAX_API_KEY: Optional[SecretStr] = Field(None, description="API key for MiniMax") + MINIMAX_API_REGION: str = Field( + "global_en", description="MiniMax API region (global_en or cn_zh)" + ) OLLAMA_HOST_URL: Optional[str] = Field( "http://127.0.0.1:11434", description="Fully qualified host URL for Ollama" ) diff --git a/tests/test_minimax.py b/tests/test_minimax.py new file mode 100644 index 0000000..67a47d5 --- /dev/null +++ b/tests/test_minimax.py @@ -0,0 +1,41 @@ +import pytest + +from simplemind.providers import MiniMax, MiniMaxAnthropic, providers +from simplemind.utils import find_provider + + +@pytest.mark.parametrize( + ("provider_cls", "protocol", "region", "expected_url"), + [ + (MiniMax, "openai", "global_en", "https://api.minimax.io/v1"), + (MiniMax, "openai", "cn_zh", "https://api.minimaxi.com/v1"), + ( + MiniMaxAnthropic, + "anthropic", + "global_en", + "https://api.minimax.io/anthropic/v1", + ), + ( + MiniMaxAnthropic, + "anthropic", + "cn_zh", + "https://api.minimaxi.com/anthropic/v1", + ), + ], +) +def test_minimax_endpoints(provider_cls, protocol, region, expected_url): + provider = provider_cls(api_key="test-key", region=region) + + assert provider.MODEL_IDS == ("MiniMax-M3", "MiniMax-M2.7") + assert provider.ENDPOINTS[region][protocol] == expected_url + + +@pytest.mark.parametrize("provider_cls", [MiniMax, MiniMaxAnthropic]) +def test_minimax_registered(provider_cls): + assert provider_cls in providers + assert isinstance(find_provider(provider_cls.NAME), provider_cls) + + +def test_minimax_rejects_unknown_region(): + with pytest.raises(ValueError, match="MiniMax API region must be one of"): + MiniMax(api_key="test-key", region="unknown") From 54ee265d04b7ed4c156fe39847a58186e603f0d7 Mon Sep 17 00:00:00 2001 From: octo-patch <266937838+octo-patch@users.noreply.github.com> Date: Sun, 12 Jul 2026 17:06:33 +0800 Subject: [PATCH 2/2] Fix MiniMax Anthropic base URLs --- README.md | 2 +- simplemind/providers/minimax.py | 4 ++-- tests/test_minimax.py | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 76c6cc7..e0b5ecf 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,7 @@ The APIs remain identical between all supported providers / models: -MiniMax supports the `MiniMax-M3` and `MiniMax-M2.7` model IDs. The `minimax` provider uses its OpenAI-compatible API and `minimax-anthropic` uses its Anthropic-compatible API. Set `MINIMAX_API_REGION` to `global_en` (the default) for `https://api.minimax.io/v1` and `https://api.minimax.io/anthropic/v1`, or to `cn_zh` for `https://api.minimaxi.com/v1` and `https://api.minimaxi.com/anthropic/v1`. See the [global](https://platform.minimax.io/docs) or [mainland China](https://platform.minimaxi.com/docs) documentation for details. +MiniMax supports the `MiniMax-M3` and `MiniMax-M2.7` model IDs. The `minimax` provider uses its OpenAI-compatible API and `minimax-anthropic` uses its Anthropic-compatible API. Set `MINIMAX_API_REGION` to `global_en` (the default) for `https://api.minimax.io/v1` and `https://api.minimax.io/anthropic`, or to `cn_zh` for `https://api.minimaxi.com/v1` and `https://api.minimaxi.com/anthropic`. See the [global](https://platform.minimax.io/docs) or [mainland China](https://platform.minimaxi.com/docs) documentation for details. To specify a specific provider or model, you can use the `llm_provider` and `llm_model` parameters when calling: `generate_text`, `generate_data`, or `create_conversation`. diff --git a/simplemind/providers/minimax.py b/simplemind/providers/minimax.py index 58128f0..6fe48d1 100644 --- a/simplemind/providers/minimax.py +++ b/simplemind/providers/minimax.py @@ -10,11 +10,11 @@ class _MiniMaxConfig: ENDPOINTS = { "global_en": { "openai": "https://api.minimax.io/v1", - "anthropic": "https://api.minimax.io/anthropic/v1", + "anthropic": "https://api.minimax.io/anthropic", }, "cn_zh": { "openai": "https://api.minimaxi.com/v1", - "anthropic": "https://api.minimaxi.com/anthropic/v1", + "anthropic": "https://api.minimaxi.com/anthropic", }, } diff --git a/tests/test_minimax.py b/tests/test_minimax.py index 67a47d5..7164388 100644 --- a/tests/test_minimax.py +++ b/tests/test_minimax.py @@ -13,13 +13,13 @@ MiniMaxAnthropic, "anthropic", "global_en", - "https://api.minimax.io/anthropic/v1", + "https://api.minimax.io/anthropic", ), ( MiniMaxAnthropic, "anthropic", "cn_zh", - "https://api.minimaxi.com/anthropic/v1", + "https://api.minimaxi.com/anthropic", ), ], )