From 839352b132de9e250f76d807871042353005e97a Mon Sep 17 00:00:00 2001 From: Himanshu-Sangshetti Date: Fri, 20 Mar 2026 16:09:35 +0530 Subject: [PATCH] fix: address review feedback for the Minimax LLM provider --- docs/components/llms/models/minimax.mdx | 56 +++++++++++++++++++++++++ docs/components/llms/overview.mdx | 1 + mem0/llms/minimax.py | 7 +++- tests/llms/test_minimax.py | 53 ++++++++++++++++------- 4 files changed, 101 insertions(+), 16 deletions(-) create mode 100644 docs/components/llms/models/minimax.mdx diff --git a/docs/components/llms/models/minimax.mdx b/docs/components/llms/models/minimax.mdx new file mode 100644 index 000000000..63c7bfe15 --- /dev/null +++ b/docs/components/llms/models/minimax.mdx @@ -0,0 +1,56 @@ +--- +title: MiniMax +description: "Configure MiniMax as an LLM provider in Mem0 with API key setup and optional custom endpoint configuration." +--- + +To use MiniMax LLM models, you have to set the `MINIMAX_API_KEY` environment variable. You can also optionally set `MINIMAX_API_BASE` if you need to use a different API endpoint (defaults to "https://api.minimax.io/v1"). + +## Usage + +```python +import os +from mem0 import Memory + +os.environ["MINIMAX_API_KEY"] = "your-api-key" +os.environ["OPENAI_API_KEY"] = "your-api-key" # for embedder model + +config = { + "llm": { + "provider": "minimax", + "config": { + "model": "MiniMax-M2.7", # default model + "temperature": 0.2, + "max_tokens": 2000, + "top_p": 1.0 + } + } +} + +m = Memory.from_config(config) +messages = [ + {"role": "user", "content": "I'm planning to watch a movie tonight. Any recommendations?"}, + {"role": "assistant", "content": "How about thriller movies? They can be quite engaging."}, + {"role": "user", "content": "I'm not a big fan of thriller movies but I love sci-fi movies."}, + {"role": "assistant", "content": "Got it! I'll avoid thriller recommendations and suggest sci-fi movies in the future."} +] +m.add(messages, user_id="alice", metadata={"category": "movies"}) +``` + +You can also configure the API base URL in the config: + +```python +config = { + "llm": { + "provider": "minimax", + "config": { + "model": "MiniMax-M2.7", + "minimax_base_url": "https://your-custom-endpoint.com", + "api_key": "your-api-key" # alternatively to using environment variable + } + } +} +``` + +## Config + +All available parameters for the `minimax` config are present in [Master List of All Params in Config](../config). diff --git a/docs/components/llms/overview.mdx b/docs/components/llms/overview.mdx index 230f9f90b..94a5cc160 100644 --- a/docs/components/llms/overview.mdx +++ b/docs/components/llms/overview.mdx @@ -31,6 +31,7 @@ See the list of supported LLMs below. + diff --git a/mem0/llms/minimax.py b/mem0/llms/minimax.py index d12eeef61..600c615b3 100644 --- a/mem0/llms/minimax.py +++ b/mem0/llms/minimax.py @@ -34,13 +34,13 @@ class MiniMaxLLM(LLMBase): super().__init__(config) if not self.config.model: - self.config.model = "MiniMax-M2.1" + self.config.model = "MiniMax-M2.7" api_key = self.config.api_key or os.getenv("MINIMAX_API_KEY") base_url = ( self.config.minimax_base_url or os.getenv("MINIMAX_API_BASE") - or "https://api.minimaxi.io/v1" + or "https://api.minimax.io/v1" ) self.client = OpenAI(api_key=api_key, base_url=base_url) @@ -103,6 +103,9 @@ class MiniMaxLLM(LLMBase): } ) + if response_format: + params["response_format"] = response_format + if tools: params["tools"] = tools params["tool_choice"] = tool_choice diff --git a/tests/llms/test_minimax.py b/tests/llms/test_minimax.py index c277a58bf..0240f24bd 100644 --- a/tests/llms/test_minimax.py +++ b/tests/llms/test_minimax.py @@ -20,11 +20,11 @@ def mock_minimax_client(): def test_minimax_llm_default_base_url(): """Default config uses MiniMax official base URL.""" config = BaseLlmConfig( - model="MiniMax-M2.1", temperature=0.7, max_tokens=100, top_p=1.0, api_key="api_key" + model="MiniMax-M2.7", temperature=0.7, max_tokens=100, top_p=1.0, api_key="api_key" ) llm = MiniMaxLLM(config) # OpenAI client may normalize URL with trailing slash - assert str(llm.client.base_url).rstrip("/") == "https://api.minimaxi.io/v1" + assert str(llm.client.base_url).rstrip("/") == "https://api.minimax.io/v1" def test_minimax_llm_env_base_url(): @@ -33,7 +33,7 @@ def test_minimax_llm_env_base_url(): os.environ["MINIMAX_API_BASE"] = provider_base_url try: config = MinimaxConfig( - model="MiniMax-M2.1", + model="MiniMax-M2.7", temperature=0.7, max_tokens=100, top_p=1.0, @@ -49,7 +49,7 @@ def test_minimax_llm_config_base_url(): """Config uses minimax_base_url when provided.""" config_base_url = "https://api.config.com/v1/" config = MinimaxConfig( - model="MiniMax-M2.1", + model="MiniMax-M2.7", temperature=0.7, max_tokens=100, top_p=1.0, @@ -61,10 +61,10 @@ def test_minimax_llm_config_base_url(): def test_minimax_llm_default_model(mock_minimax_client): - """Default model is MiniMax-M2.1 when not specified.""" + """Default model is MiniMax-M2.7 when not specified.""" config = MinimaxConfig(temperature=0.7, max_tokens=100, api_key="api_key") llm = MiniMaxLLM(config) - assert llm.config.model == "MiniMax-M2.1" + assert llm.config.model == "MiniMax-M2.7" def test_minimax_llm_env_api_key(): @@ -74,11 +74,11 @@ def test_minimax_llm_env_api_key(): with patch("mem0.llms.minimax.OpenAI") as mock_openai: mock_client = Mock() mock_openai.return_value = mock_client - config = MinimaxConfig(model="MiniMax-M2.1", api_key=None) + config = MinimaxConfig(model="MiniMax-M2.7", api_key=None) MiniMaxLLM(config) mock_openai.assert_called_once_with( api_key="env-api-key", - base_url="https://api.minimaxi.io/v1", + base_url="https://api.minimax.io/v1", ) finally: os.environ.pop("MINIMAX_API_KEY", None) @@ -87,7 +87,7 @@ def test_minimax_llm_env_api_key(): def test_generate_response_without_tools(mock_minimax_client): """generate_response returns text when no tools provided.""" config = BaseLlmConfig( - model="MiniMax-M2.1", temperature=0.7, max_tokens=100, top_p=1.0, api_key="api_key" + model="MiniMax-M2.7", temperature=0.7, max_tokens=100, top_p=1.0, api_key="api_key" ) llm = MiniMaxLLM(config) messages = [ @@ -102,7 +102,7 @@ def test_generate_response_without_tools(mock_minimax_client): response = llm.generate_response(messages) mock_minimax_client.chat.completions.create.assert_called_once_with( - model="MiniMax-M2.1", messages=messages, temperature=0.7, max_tokens=100, top_p=1.0 + model="MiniMax-M2.7", messages=messages, temperature=0.7, max_tokens=100, top_p=1.0 ) assert response == "I'm doing well, thank you for asking!" @@ -110,7 +110,7 @@ def test_generate_response_without_tools(mock_minimax_client): def test_generate_response_with_tools(mock_minimax_client): """generate_response returns tool_calls when tools provided.""" config = BaseLlmConfig( - model="MiniMax-M2.1", temperature=0.7, max_tokens=100, top_p=1.0, api_key="api_key" + model="MiniMax-M2.7", temperature=0.7, max_tokens=100, top_p=1.0, api_key="api_key" ) llm = MiniMaxLLM(config) messages = [ @@ -147,7 +147,7 @@ def test_generate_response_with_tools(mock_minimax_client): response = llm.generate_response(messages, tools=tools) mock_minimax_client.chat.completions.create.assert_called_once_with( - model="MiniMax-M2.1", + model="MiniMax-M2.7", messages=messages, temperature=0.7, max_tokens=100, @@ -162,8 +162,33 @@ def test_generate_response_with_tools(mock_minimax_client): assert response["tool_calls"][0]["arguments"] == {"data": "Today is a sunny day."} +def test_generate_response_with_response_format(mock_minimax_client): + """generate_response passes response_format to the API.""" + config = BaseLlmConfig( + model="MiniMax-M2.7", temperature=0.7, max_tokens=100, top_p=1.0, api_key="api_key" + ) + llm = MiniMaxLLM(config) + messages = [{"role": "user", "content": "Return JSON."}] + response_format = {"type": "json_object"} + + mock_response = Mock() + mock_response.choices = [Mock(message=Mock(content='{"key": "value"}'))] + mock_minimax_client.chat.completions.create.return_value = mock_response + + llm.generate_response(messages, response_format=response_format) + + mock_minimax_client.chat.completions.create.assert_called_once_with( + model="MiniMax-M2.7", + messages=messages, + temperature=0.7, + max_tokens=100, + top_p=1.0, + response_format={"type": "json_object"}, + ) + + def test_factory_creates_minimax_llm(mock_minimax_client): """LlmFactory.create returns MiniMaxLLM for provider 'minimax'.""" - llm = LlmFactory.create("minimax", {"model": "MiniMax-M2.1", "api_key": "test-key"}) + llm = LlmFactory.create("minimax", {"model": "MiniMax-M2.7", "api_key": "test-key"}) assert isinstance(llm, MiniMaxLLM) - assert llm.config.model == "MiniMax-M2.1" + assert llm.config.model == "MiniMax-M2.7"