From 47cfbdcde05c753b65fe96227f41f35eaebe8085 Mon Sep 17 00:00:00 2001 From: Octopus Date: Wed, 1 Apr 2026 22:46:33 +0800 Subject: [PATCH 1/2] feat(providers): add MiniMax as LLM vendor Add MiniMax Cloud API (MiniMax-M2.7, MiniMax-M2.7-highspeed) as a first-class LLM vendor in the RAI initialization module. MiniMax exposes an OpenAI-compatible chat endpoint, so it is wired through ChatOpenAI with a custom base_url. Changes: - model_initialization.py: MiniMaxConfig dataclass, RAIConfig.minimax field, get_llm_model/get_llm_model_direct minimax branch with temperature clamping (> 0.0 required), get_embeddings_model raises ValueError with a clear message (MiniMax has no public embeddings API), graceful defaults when [minimax] is absent from config - config_initialization.py: [minimax] section in the generated config.toml template (M2.7-highspeed as simple, M2.7 as complex, base_url) - vendors.md: MiniMax added to the supported-vendors table and installation guide - tests/initialization/test_minimax_initialization.py: 17 unit tests covering config loading, factory routing, temperature clamping, API key env var, and embeddings guard --- docs/setup/vendors.md | 34 +- .../initialization/config_initialization.py | 5 + .../initialization/model_initialization.py | 50 +++ .../test_minimax_initialization.py | 329 ++++++++++++++++++ 4 files changed, 415 insertions(+), 3 deletions(-) create mode 100644 tests/initialization/test_minimax_initialization.py diff --git a/docs/setup/vendors.md b/docs/setup/vendors.md index 855f0add7..d299a04ac 100644 --- a/docs/setup/vendors.md +++ b/docs/setup/vendors.md @@ -9,9 +9,9 @@ Alternatively vendors can be configured manually in `config.toml` file. The table summarizes vendor alternative for core AI service and optional RAI modules: -| Module | Open source | Alternative | Why to consider alternative? | More information | -| ----------------------------------------------- | ------------------ | ----------------------- | ------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [LLM service](#llm-model-configuration-in-rai) | Ollama | OpenAI, Bedrock | Overall performance of the LLM models, supported modalities and features | [LangChain models](https://docs.langchain4j.dev/integrations/language-models/) | +| Module | Open source | Alternative | Why to consider alternative? | More information | +| ----------------------------------------------- | ------------------ | ------------------------------ | ------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [LLM service](#llm-model-configuration-in-rai) | Ollama | OpenAI, Bedrock, MiniMax | Overall performance of the LLM models, supported modalities and features | [LangChain models](https://docs.langchain4j.dev/integrations/language-models/) | | **Optional:** [Tracing tool](./tracing.md) | Langfuse | LangSmith | Better integration with LangChain | [Comparison](https://langfuse.com/faq/all/langsmith-alternative) | | **Optional:** [Text to speech](#text-to-speech) | KokoroTTS, OpenTTS | ElevenLabs | Arguably, significantly better voice synthesis |
  • [KokoroTTS](https://huggingface.co/hexgrad/Kokoro-82M#usage)
  • [OpenTTS GitHub](https://github.com/synesthesiam/opentts)
  • [RAI voice interface][s2s]
  • | | **Optional:** [Speech to text](#speech-to-text) | Whisper | OpenAI Whisper (hosted) | When suitable local GPU is not an option |
  • [Whisper GitHub](https://github.com/openai/whisper)
  • [RAI voice interface][s2s]
  • | @@ -67,6 +67,34 @@ Ollama can be used to host models locally. 2. Use [RAI Configurator][configurator] -> `Model Selection` -> `bedrock` vendor +### MiniMax + +MiniMax provides high-capacity cloud LLM models (M2.7, M2.7-highspeed) with a 204K context +window via an OpenAI-compatible API. + +1. Obtain a MiniMax API key from [https://www.minimax.io](https://www.minimax.io) and set it: + + ```bash + export MINIMAX_API_KEY="your-api-key" + ``` + +2. In `config.toml`, set the vendor and model: + + ```toml + [vendor] + simple_model = "minimax" + complex_model = "minimax" + + [minimax] + simple_model = "MiniMax-M2.7-highspeed" + complex_model = "MiniMax-M2.7" + base_url = "https://api.minimax.io/v1" + ``` + +> [!NOTE] +> MiniMax does not provide a public embeddings API. Use a different vendor +> (e.g. `openai` or `ollama`) for the `embeddings_model` setting. + ## Complex LLM Model Configuration For custom setups please use LangChain API. diff --git a/src/rai_core/rai/initialization/config_initialization.py b/src/rai_core/rai/initialization/config_initialization.py index 94028b252..bf0e350ef 100644 --- a/src/rai_core/rai/initialization/config_initialization.py +++ b/src/rai_core/rai/initialization/config_initialization.py @@ -47,6 +47,11 @@ complex_model = "gemini-3-pro" embeddings_model = "text-embedding-004" +[minimax] +simple_model = "MiniMax-M2.7-highspeed" +complex_model = "MiniMax-M2.7" +base_url = "https://api.minimax.io/v1" + [tracing] project = "rai" diff --git a/src/rai_core/rai/initialization/model_initialization.py b/src/rai_core/rai/initialization/model_initialization.py index e16eede95..ead12a947 100644 --- a/src/rai_core/rai/initialization/model_initialization.py +++ b/src/rai_core/rai/initialization/model_initialization.py @@ -27,6 +27,8 @@ from langchain_openai import ChatOpenAI from langsmith import Client +_MINIMAX_DEFAULT_BASE_URL = "https://api.minimax.io/v1" + logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) coloredlogs.install(level="INFO") # type: ignore @@ -67,6 +69,13 @@ class GoogleConfig(ModelConfig): pass +@dataclass +class MiniMaxConfig: + simple_model: str + complex_model: str + base_url: str + + @dataclass class LangfuseConfig: use_langfuse: bool @@ -93,6 +102,7 @@ class RAIConfig: openai: OpenAIConfig ollama: OllamaConfig google: GoogleConfig + minimax: MiniMaxConfig tracing: TracingConfig @@ -109,6 +119,16 @@ def load_config(config_path: Optional[str] = None) -> RAIConfig: openai=OpenAIConfig(**config_dict["openai"]), ollama=OllamaConfig(**config_dict["ollama"]), google=GoogleConfig(**config_dict["google"]), + minimax=MiniMaxConfig( + **config_dict.get( + "minimax", + { + "simple_model": "MiniMax-M2.7-highspeed", + "complex_model": "MiniMax-M2.7", + "base_url": _MINIMAX_DEFAULT_BASE_URL, + }, + ) + ), tracing=TracingConfig( project=config_dict["tracing"]["project"], langfuse=LangfuseConfig(**config_dict["tracing"]["langfuse"]), @@ -170,6 +190,18 @@ def get_llm_model( model_config = cast(GoogleConfig, model_config) return ChatGoogleGenerativeAI(model=model, **kwargs) + elif vendor == "minimax": + from langchain_openai import ChatOpenAI + + model_config = cast(MiniMaxConfig, model_config) + if "temperature" in kwargs and kwargs["temperature"] <= 0.0: + kwargs["temperature"] = 0.01 + return ChatOpenAI( + model=model, + base_url=model_config.base_url, + api_key=os.environ.get("MINIMAX_API_KEY", ""), + **kwargs, + ) else: raise ValueError(f"Unknown LLM vendor: {vendor}") @@ -212,6 +244,18 @@ def get_llm_model_direct( model_config = cast(GoogleConfig, model_config) return ChatGoogleGenerativeAI(model=model_name, **kwargs) + elif vendor == "minimax": + from langchain_openai import ChatOpenAI + + model_config = cast(MiniMaxConfig, model_config) + if "temperature" in kwargs and kwargs["temperature"] <= 0.0: + kwargs["temperature"] = 0.01 + return ChatOpenAI( + model=model_name, + base_url=model_config.base_url, + api_key=os.environ.get("MINIMAX_API_KEY", ""), + **kwargs, + ) else: raise ValueError(f"Unknown LLM vendor: {vendor}") @@ -225,6 +269,12 @@ def get_embeddings_model( model_config = getattr(config, vendor) + if vendor == "minimax": + raise ValueError( + "MiniMax does not provide a public embeddings API. " + "Please use a different vendor for embeddings (e.g., 'openai', 'ollama')." + ) + logger.info(f"Using embeddings model: {vendor}-{model_config.embeddings_model}") if vendor == "openai": from langchain_openai import OpenAIEmbeddings diff --git a/tests/initialization/test_minimax_initialization.py b/tests/initialization/test_minimax_initialization.py new file mode 100644 index 000000000..c279b8cd0 --- /dev/null +++ b/tests/initialization/test_minimax_initialization.py @@ -0,0 +1,329 @@ +# Copyright (C) 2025 Robotec.AI +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Tests for MiniMax vendor integration with RAI framework. + +MiniMax exposes an OpenAI-compatible chat API at https://api.minimax.io/v1. +These tests verify that the RAI initialization module correctly routes to +ChatOpenAI with the MiniMax base URL and API key, and that temperature +clamping (>0.0) is applied before construction. +""" + +import pytest +from pathlib import Path + +from rai.initialization import model_initialization + +# --------------------------------------------------------------------------- +# Shared config template +# --------------------------------------------------------------------------- + +MINIMAX_CONFIG_TEMPLATE = """ +[vendor] +simple_model = "minimax" +complex_model = "minimax" +embeddings_model = "openai" + +[aws] +simple_model = "aws.simple" +complex_model = "aws.complex" +embeddings_model = "aws.embed" +region_name = "us-west-2" + +[openai] +simple_model = "gpt-4o-mini" +complex_model = "gpt-4o" +embeddings_model = "text-embedding-ada-002" +base_url = "https://api.openai.com/v1/" + +[ollama] +simple_model = "llama-simple" +complex_model = "llama-complex" +embeddings_model = "llama-embed" +base_url = "http://localhost:11434" + +[google] +simple_model = "gemini-3-flash" +complex_model = "gemini-3-pro" +embeddings_model = "text-embedding-004" + +[minimax] +simple_model = "MiniMax-M2.7-highspeed" +complex_model = "MiniMax-M2.7" +base_url = "https://api.minimax.io/v1" + +[tracing] +project = "rai" + +[tracing.langfuse] +use_langfuse = false +host = "http://localhost:3000" + +[tracing.langsmith] +use_langsmith = false +host = "https://api.smith.langchain.com" +""" + + +class DummyModel: + """Dummy model for testing factory routing without real API calls.""" + + def __init__(self, *args, **kwargs): + self.args = args + self.kwargs = kwargs + + +def write_config(path: Path, config: str) -> Path: + path.write_text(config, encoding="utf-8") + return path + + +# --------------------------------------------------------------------------- +# Config loading +# --------------------------------------------------------------------------- + + +class TestMiniMaxConfig: + """Tests for MiniMax config loading.""" + + def test_load_config_includes_minimax_section(self, tmp_path): + config_path = write_config(tmp_path / "config.toml", MINIMAX_CONFIG_TEMPLATE) + config = model_initialization.load_config(str(config_path)) + + assert config.minimax.simple_model == "MiniMax-M2.7-highspeed" + assert config.minimax.complex_model == "MiniMax-M2.7" + assert config.minimax.base_url == "https://api.minimax.io/v1" + + def test_load_config_defaults_when_minimax_section_absent(self, tmp_path): + """Configs without [minimax] section should use built-in defaults.""" + config_without_minimax = "\n".join( + line + for line in MINIMAX_CONFIG_TEMPLATE.splitlines() + if not line.startswith("[minimax]") + and not line.startswith("simple_model = \"MiniMax") + and not line.startswith("complex_model = \"MiniMax") + and not line.startswith("base_url = \"https://api.minimax") + ) + config_path = write_config(tmp_path / "config.toml", config_without_minimax) + config = model_initialization.load_config(str(config_path)) + + assert config.minimax.simple_model == "MiniMax-M2.7-highspeed" + assert config.minimax.complex_model == "MiniMax-M2.7" + assert config.minimax.base_url == "https://api.minimax.io/v1" + + def test_get_llm_model_config_and_vendor_minimax_simple(self, tmp_path): + config_path = write_config(tmp_path / "config.toml", MINIMAX_CONFIG_TEMPLATE) + + model_config, vendor = model_initialization.get_llm_model_config_and_vendor( + "simple_model", config_path=str(config_path) + ) + + assert vendor == "minimax" + assert model_config.simple_model == "MiniMax-M2.7-highspeed" + + def test_get_llm_model_config_and_vendor_minimax_complex(self, tmp_path): + config_path = write_config(tmp_path / "config.toml", MINIMAX_CONFIG_TEMPLATE) + + model_config, vendor = model_initialization.get_llm_model_config_and_vendor( + "complex_model", config_path=str(config_path) + ) + + assert vendor == "minimax" + assert model_config.complex_model == "MiniMax-M2.7" + + def test_get_llm_model_config_and_vendor_override_to_minimax(self, tmp_path): + """Explicitly passing vendor='minimax' works regardless of vendor defaults.""" + config_openai_default = MINIMAX_CONFIG_TEMPLATE.replace( + 'simple_model = "minimax"', 'simple_model = "openai"', 1 + ) + config_path = write_config(tmp_path / "config.toml", config_openai_default) + + model_config, vendor = model_initialization.get_llm_model_config_and_vendor( + "simple_model", vendor="minimax", config_path=str(config_path) + ) + + assert vendor == "minimax" + assert model_config.simple_model == "MiniMax-M2.7-highspeed" + + +# --------------------------------------------------------------------------- +# get_llm_model factory +# --------------------------------------------------------------------------- + + +class TestMiniMaxLLMModelFactory: + """Tests for get_llm_model factory with MiniMax vendor.""" + + def test_get_llm_model_returns_chat_openai_instance(self, monkeypatch, tmp_path): + config_path = write_config(tmp_path / "config.toml", MINIMAX_CONFIG_TEMPLATE) + monkeypatch.setattr("langchain_openai.ChatOpenAI", DummyModel) + + model = model_initialization.get_llm_model( + "simple_model", vendor="minimax", config_path=str(config_path) + ) + + assert isinstance(model, DummyModel) + assert model.kwargs["model"] == "MiniMax-M2.7-highspeed" + assert model.kwargs["base_url"] == "https://api.minimax.io/v1" + + def test_get_llm_model_complex_uses_m2_7(self, monkeypatch, tmp_path): + config_path = write_config(tmp_path / "config.toml", MINIMAX_CONFIG_TEMPLATE) + monkeypatch.setattr("langchain_openai.ChatOpenAI", DummyModel) + + model = model_initialization.get_llm_model( + "complex_model", vendor="minimax", config_path=str(config_path) + ) + + assert isinstance(model, DummyModel) + assert model.kwargs["model"] == "MiniMax-M2.7" + + def test_get_llm_model_reads_minimax_api_key_env_var( + self, monkeypatch, tmp_path + ): + config_path = write_config(tmp_path / "config.toml", MINIMAX_CONFIG_TEMPLATE) + monkeypatch.setenv("MINIMAX_API_KEY", "test-minimax-key") + monkeypatch.setattr("langchain_openai.ChatOpenAI", DummyModel) + + model = model_initialization.get_llm_model( + "simple_model", vendor="minimax", config_path=str(config_path) + ) + + assert model.kwargs["api_key"] == "test-minimax-key" + + def test_get_llm_model_passes_extra_kwargs(self, monkeypatch, tmp_path): + config_path = write_config(tmp_path / "config.toml", MINIMAX_CONFIG_TEMPLATE) + monkeypatch.setattr("langchain_openai.ChatOpenAI", DummyModel) + + model = model_initialization.get_llm_model( + "simple_model", + vendor="minimax", + config_path=str(config_path), + temperature=0.7, + max_tokens=2048, + ) + + assert model.kwargs["temperature"] == 0.7 + assert model.kwargs["max_tokens"] == 2048 + + def test_get_llm_model_clamps_zero_temperature(self, monkeypatch, tmp_path): + """MiniMax requires temperature > 0.0; zero should be clamped to 0.01.""" + config_path = write_config(tmp_path / "config.toml", MINIMAX_CONFIG_TEMPLATE) + monkeypatch.setattr("langchain_openai.ChatOpenAI", DummyModel) + + model = model_initialization.get_llm_model( + "simple_model", + vendor="minimax", + config_path=str(config_path), + temperature=0.0, + ) + + assert model.kwargs["temperature"] == 0.01 + + def test_get_llm_model_clamps_negative_temperature(self, monkeypatch, tmp_path): + """Negative temperature should also be clamped to 0.01.""" + config_path = write_config(tmp_path / "config.toml", MINIMAX_CONFIG_TEMPLATE) + monkeypatch.setattr("langchain_openai.ChatOpenAI", DummyModel) + + model = model_initialization.get_llm_model( + "simple_model", + vendor="minimax", + config_path=str(config_path), + temperature=-0.5, + ) + + assert model.kwargs["temperature"] == 0.01 + + def test_get_llm_model_positive_temperature_unchanged(self, monkeypatch, tmp_path): + config_path = write_config(tmp_path / "config.toml", MINIMAX_CONFIG_TEMPLATE) + monkeypatch.setattr("langchain_openai.ChatOpenAI", DummyModel) + + model = model_initialization.get_llm_model( + "simple_model", + vendor="minimax", + config_path=str(config_path), + temperature=0.5, + ) + + assert model.kwargs["temperature"] == 0.5 + + +# --------------------------------------------------------------------------- +# get_llm_model_direct factory +# --------------------------------------------------------------------------- + + +class TestMiniMaxLLMModelDirect: + """Tests for get_llm_model_direct with MiniMax vendor.""" + + def test_get_llm_model_direct_uses_provided_model_name( + self, monkeypatch, tmp_path + ): + config_path = write_config(tmp_path / "config.toml", MINIMAX_CONFIG_TEMPLATE) + monkeypatch.setattr("langchain_openai.ChatOpenAI", DummyModel) + + model = model_initialization.get_llm_model_direct( + model_name="MiniMax-M2.7-highspeed", + vendor="minimax", + config_path=str(config_path), + ) + + assert isinstance(model, DummyModel) + assert model.kwargs["model"] == "MiniMax-M2.7-highspeed" + assert model.kwargs["base_url"] == "https://api.minimax.io/v1" + + def test_get_llm_model_direct_clamps_zero_temperature( + self, monkeypatch, tmp_path + ): + config_path = write_config(tmp_path / "config.toml", MINIMAX_CONFIG_TEMPLATE) + monkeypatch.setattr("langchain_openai.ChatOpenAI", DummyModel) + + model = model_initialization.get_llm_model_direct( + model_name="MiniMax-M2.7", + vendor="minimax", + config_path=str(config_path), + temperature=0.0, + ) + + assert model.kwargs["temperature"] == 0.01 + + def test_get_llm_model_direct_reads_api_key(self, monkeypatch, tmp_path): + config_path = write_config(tmp_path / "config.toml", MINIMAX_CONFIG_TEMPLATE) + monkeypatch.setenv("MINIMAX_API_KEY", "direct-key") + monkeypatch.setattr("langchain_openai.ChatOpenAI", DummyModel) + + model = model_initialization.get_llm_model_direct( + model_name="MiniMax-M2.7", + vendor="minimax", + config_path=str(config_path), + ) + + assert model.kwargs["api_key"] == "direct-key" + + +# --------------------------------------------------------------------------- +# Embeddings — MiniMax not supported +# --------------------------------------------------------------------------- + + +class TestMiniMaxEmbeddingsNotSupported: + """MiniMax does not expose a public embeddings API.""" + + def test_get_embeddings_model_raises_for_minimax(self, tmp_path): + minimax_embeddings_config = MINIMAX_CONFIG_TEMPLATE.replace( + 'embeddings_model = "openai"', 'embeddings_model = "minimax"', 1 + ) + config_path = write_config(tmp_path / "config.toml", minimax_embeddings_config) + + with pytest.raises(ValueError, match="MiniMax does not provide a public embeddings API"): + model_initialization.get_embeddings_model(config_path=str(config_path)) From 822e297d4549b7f4813f77975f291748ade490de Mon Sep 17 00:00:00 2001 From: maciejmajek Date: Tue, 7 Apr 2026 13:56:23 +0200 Subject: [PATCH 2/2] chore: pre-commit --- docs/setup/vendors.md | 12 +++++----- .../test_minimax_initialization.py | 24 ++++++++----------- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/docs/setup/vendors.md b/docs/setup/vendors.md index d299a04ac..c4bec6001 100644 --- a/docs/setup/vendors.md +++ b/docs/setup/vendors.md @@ -9,12 +9,12 @@ Alternatively vendors can be configured manually in `config.toml` file. The table summarizes vendor alternative for core AI service and optional RAI modules: -| Module | Open source | Alternative | Why to consider alternative? | More information | -| ----------------------------------------------- | ------------------ | ------------------------------ | ------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| [LLM service](#llm-model-configuration-in-rai) | Ollama | OpenAI, Bedrock, MiniMax | Overall performance of the LLM models, supported modalities and features | [LangChain models](https://docs.langchain4j.dev/integrations/language-models/) | -| **Optional:** [Tracing tool](./tracing.md) | Langfuse | LangSmith | Better integration with LangChain | [Comparison](https://langfuse.com/faq/all/langsmith-alternative) | -| **Optional:** [Text to speech](#text-to-speech) | KokoroTTS, OpenTTS | ElevenLabs | Arguably, significantly better voice synthesis |
  • [KokoroTTS](https://huggingface.co/hexgrad/Kokoro-82M#usage)
  • [OpenTTS GitHub](https://github.com/synesthesiam/opentts)
  • [RAI voice interface][s2s]
  • | -| **Optional:** [Speech to text](#speech-to-text) | Whisper | OpenAI Whisper (hosted) | When suitable local GPU is not an option |
  • [Whisper GitHub](https://github.com/openai/whisper)
  • [RAI voice interface][s2s]
  • | +| Module | Open source | Alternative | Why to consider alternative? | More information | +| ----------------------------------------------- | ------------------ | ------------------------ | ------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [LLM service](#llm-model-configuration-in-rai) | Ollama | OpenAI, Bedrock, MiniMax | Overall performance of the LLM models, supported modalities and features | [LangChain models](https://docs.langchain4j.dev/integrations/language-models/) | +| **Optional:** [Tracing tool](./tracing.md) | Langfuse | LangSmith | Better integration with LangChain | [Comparison](https://langfuse.com/faq/all/langsmith-alternative) | +| **Optional:** [Text to speech](#text-to-speech) | KokoroTTS, OpenTTS | ElevenLabs | Arguably, significantly better voice synthesis |
  • [KokoroTTS](https://huggingface.co/hexgrad/Kokoro-82M#usage)
  • [OpenTTS GitHub](https://github.com/synesthesiam/opentts)
  • [RAI voice interface][s2s]
  • | +| **Optional:** [Speech to text](#speech-to-text) | Whisper | OpenAI Whisper (hosted) | When suitable local GPU is not an option |
  • [Whisper GitHub](https://github.com/openai/whisper)
  • [RAI voice interface][s2s]
  • | > [!TIP] Best-performing AI models > diff --git a/tests/initialization/test_minimax_initialization.py b/tests/initialization/test_minimax_initialization.py index c279b8cd0..64a6ffda3 100644 --- a/tests/initialization/test_minimax_initialization.py +++ b/tests/initialization/test_minimax_initialization.py @@ -20,9 +20,9 @@ clamping (>0.0) is applied before construction. """ -import pytest from pathlib import Path +import pytest from rai.initialization import model_initialization # --------------------------------------------------------------------------- @@ -111,9 +111,9 @@ def test_load_config_defaults_when_minimax_section_absent(self, tmp_path): line for line in MINIMAX_CONFIG_TEMPLATE.splitlines() if not line.startswith("[minimax]") - and not line.startswith("simple_model = \"MiniMax") - and not line.startswith("complex_model = \"MiniMax") - and not line.startswith("base_url = \"https://api.minimax") + and not line.startswith('simple_model = "MiniMax') + and not line.startswith('complex_model = "MiniMax') + and not line.startswith('base_url = "https://api.minimax') ) config_path = write_config(tmp_path / "config.toml", config_without_minimax) config = model_initialization.load_config(str(config_path)) @@ -188,9 +188,7 @@ def test_get_llm_model_complex_uses_m2_7(self, monkeypatch, tmp_path): assert isinstance(model, DummyModel) assert model.kwargs["model"] == "MiniMax-M2.7" - def test_get_llm_model_reads_minimax_api_key_env_var( - self, monkeypatch, tmp_path - ): + def test_get_llm_model_reads_minimax_api_key_env_var(self, monkeypatch, tmp_path): config_path = write_config(tmp_path / "config.toml", MINIMAX_CONFIG_TEMPLATE) monkeypatch.setenv("MINIMAX_API_KEY", "test-minimax-key") monkeypatch.setattr("langchain_openai.ChatOpenAI", DummyModel) @@ -266,9 +264,7 @@ def test_get_llm_model_positive_temperature_unchanged(self, monkeypatch, tmp_pat class TestMiniMaxLLMModelDirect: """Tests for get_llm_model_direct with MiniMax vendor.""" - def test_get_llm_model_direct_uses_provided_model_name( - self, monkeypatch, tmp_path - ): + def test_get_llm_model_direct_uses_provided_model_name(self, monkeypatch, tmp_path): config_path = write_config(tmp_path / "config.toml", MINIMAX_CONFIG_TEMPLATE) monkeypatch.setattr("langchain_openai.ChatOpenAI", DummyModel) @@ -282,9 +278,7 @@ def test_get_llm_model_direct_uses_provided_model_name( assert model.kwargs["model"] == "MiniMax-M2.7-highspeed" assert model.kwargs["base_url"] == "https://api.minimax.io/v1" - def test_get_llm_model_direct_clamps_zero_temperature( - self, monkeypatch, tmp_path - ): + def test_get_llm_model_direct_clamps_zero_temperature(self, monkeypatch, tmp_path): config_path = write_config(tmp_path / "config.toml", MINIMAX_CONFIG_TEMPLATE) monkeypatch.setattr("langchain_openai.ChatOpenAI", DummyModel) @@ -325,5 +319,7 @@ def test_get_embeddings_model_raises_for_minimax(self, tmp_path): ) config_path = write_config(tmp_path / "config.toml", minimax_embeddings_config) - with pytest.raises(ValueError, match="MiniMax does not provide a public embeddings API"): + with pytest.raises( + ValueError, match="MiniMax does not provide a public embeddings API" + ): model_initialization.get_embeddings_model(config_path=str(config_path))