diff --git a/LLM.md b/LLM.md
index 69c08cccc..c97564070 100644
--- a/LLM.md
+++ b/LLM.md
@@ -273,7 +273,7 @@ config = MemoryConfig(
### Supported Providers
-#### LLM Providers (19 supported)
+#### LLM Providers (20 supported)
- **openai** - OpenAI GPT models (default)
- **anthropic** - Claude models
- **gemini** - Google Gemini
@@ -284,6 +284,7 @@ config = MemoryConfig(
- **azure_openai** - Azure OpenAI
- **litellm** - LiteLLM proxy
- **deepseek** - DeepSeek models
+- **minimax** - MiniMax models
- **xai** - xAI models
- **sarvam** - Sarvam AI
- **lmstudio** - LM Studio local server
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/docs/docs.json b/docs/docs.json
index 84b83e3b7..623d42fbb 100644
--- a/docs/docs.json
+++ b/docs/docs.json
@@ -188,6 +188,7 @@
"components/llms/models/google_AI",
"components/llms/models/aws_bedrock",
"components/llms/models/deepseek",
+ "components/llms/models/minimax",
"components/llms/models/xAI",
"components/llms/models/sarvam",
"components/llms/models/lmstudio",
diff --git a/mem0/configs/llms/minimax.py b/mem0/configs/llms/minimax.py
new file mode 100644
index 000000000..93b813a40
--- /dev/null
+++ b/mem0/configs/llms/minimax.py
@@ -0,0 +1,56 @@
+from typing import Optional
+
+from mem0.configs.llms.base import BaseLlmConfig
+
+
+class MinimaxConfig(BaseLlmConfig):
+ """
+ Configuration class for MiniMax-specific parameters.
+ Inherits from BaseLlmConfig and adds MiniMax-specific settings.
+ """
+
+ def __init__(
+ self,
+ # Base parameters
+ model: Optional[str] = None,
+ temperature: float = 0.1,
+ api_key: Optional[str] = None,
+ max_tokens: int = 2000,
+ top_p: float = 0.1,
+ top_k: int = 1,
+ enable_vision: bool = False,
+ vision_details: Optional[str] = "auto",
+ http_client_proxies: Optional[dict] = None,
+ # MiniMax-specific parameters
+ minimax_base_url: Optional[str] = None,
+ ):
+ """
+ Initialize MiniMax configuration.
+
+ Args:
+ model: MiniMax model to use, defaults to None
+ temperature: Controls randomness, defaults to 0.1
+ api_key: MiniMax API key, defaults to None
+ max_tokens: Maximum tokens to generate, defaults to 2000
+ top_p: Nucleus sampling parameter, defaults to 0.1
+ top_k: Top-k sampling parameter, defaults to 1
+ enable_vision: Enable vision capabilities, defaults to False
+ vision_details: Vision detail level, defaults to "auto"
+ http_client_proxies: HTTP client proxy settings, defaults to None
+ minimax_base_url: MiniMax API base URL, defaults to None
+ """
+ # Initialize base parameters
+ super().__init__(
+ model=model,
+ temperature=temperature,
+ api_key=api_key,
+ max_tokens=max_tokens,
+ top_p=top_p,
+ top_k=top_k,
+ enable_vision=enable_vision,
+ vision_details=vision_details,
+ http_client_proxies=http_client_proxies,
+ )
+
+ # MiniMax-specific parameters
+ self.minimax_base_url = minimax_base_url
diff --git a/mem0/llms/configs.py b/mem0/llms/configs.py
index 694ef2719..11d5880da 100644
--- a/mem0/llms/configs.py
+++ b/mem0/llms/configs.py
@@ -23,6 +23,7 @@ class LlmConfig(BaseModel):
"azure_openai_structured",
"gemini",
"deepseek",
+ "minimax",
"xai",
"sarvam",
"lmstudio",
diff --git a/mem0/llms/minimax.py b/mem0/llms/minimax.py
new file mode 100644
index 000000000..82f6f2622
--- /dev/null
+++ b/mem0/llms/minimax.py
@@ -0,0 +1,114 @@
+import json
+import os
+from typing import Dict, List, Optional, Union
+
+from openai import OpenAI
+
+from mem0.configs.llms.base import BaseLlmConfig
+from mem0.configs.llms.minimax import MinimaxConfig
+from mem0.llms.base import LLMBase
+from mem0.memory.utils import extract_json
+
+
+class MiniMaxLLM(LLMBase):
+ def __init__(self, config: Optional[Union[BaseLlmConfig, MinimaxConfig, Dict]] = None):
+ # Convert to MinimaxConfig if needed
+ if config is None:
+ config = MinimaxConfig()
+ elif isinstance(config, dict):
+ config = MinimaxConfig(**config)
+ elif isinstance(config, BaseLlmConfig) and not isinstance(config, MinimaxConfig):
+ # Convert BaseLlmConfig to MinimaxConfig
+ config = MinimaxConfig(
+ model=config.model,
+ temperature=config.temperature,
+ api_key=config.api_key,
+ max_tokens=config.max_tokens,
+ top_p=config.top_p,
+ top_k=config.top_k,
+ enable_vision=config.enable_vision,
+ vision_details=config.vision_details,
+ http_client_proxies=config.http_client,
+ )
+
+ super().__init__(config)
+
+ if not self.config.model:
+ 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.minimax.io/v1"
+ )
+ self.client = OpenAI(api_key=api_key, base_url=base_url)
+
+ def _parse_response(self, response, tools):
+ """
+ Process the response based on whether tools are used or not.
+
+ Args:
+ response: The raw response from API.
+ tools: The list of tools provided in the request.
+
+ Returns:
+ str or dict: The processed response.
+ """
+ if tools:
+ processed_response = {
+ "content": response.choices[0].message.content,
+ "tool_calls": [],
+ }
+
+ if response.choices[0].message.tool_calls:
+ for tool_call in response.choices[0].message.tool_calls:
+ processed_response["tool_calls"].append(
+ {
+ "name": tool_call.function.name,
+ "arguments": json.loads(extract_json(tool_call.function.arguments)),
+ }
+ )
+
+ return processed_response
+ else:
+ return response.choices[0].message.content
+
+ def generate_response(
+ self,
+ messages: List[Dict[str, str]],
+ response_format=None,
+ tools: Optional[List[Dict]] = None,
+ tool_choice: str = "auto",
+ **kwargs,
+ ):
+ """
+ Generate a response based on the given messages using MiniMax.
+
+ Args:
+ messages (list): List of message dicts containing 'role' and 'content'.
+ response_format (str or object, optional): Format of the response. Defaults to None.
+ tools (list, optional): List of tools that the model can call. Defaults to None.
+ tool_choice (str, optional): Tool choice method. Defaults to "auto".
+ **kwargs: Additional MiniMax-specific parameters.
+
+ Returns:
+ str: The generated response.
+ """
+ params = self._get_supported_params(messages=messages, **kwargs)
+ params.update(
+ {
+ "model": self.config.model,
+ "messages": messages,
+ }
+ )
+
+ if response_format:
+ params["response_format"] = response_format
+
+ if tools:
+ params["tools"] = tools
+ params["tool_choice"] = tool_choice
+
+ response = self.client.chat.completions.create(**params)
+ return self._parse_response(response, tools)
diff --git a/mem0/utils/factory.py b/mem0/utils/factory.py
index ab3fc77a3..afbd8263f 100644
--- a/mem0/utils/factory.py
+++ b/mem0/utils/factory.py
@@ -6,6 +6,7 @@ from mem0.configs.llms.anthropic import AnthropicConfig
from mem0.configs.llms.azure import AzureOpenAIConfig
from mem0.configs.llms.base import BaseLlmConfig
from mem0.configs.llms.deepseek import DeepSeekConfig
+from mem0.configs.llms.minimax import MinimaxConfig
from mem0.configs.llms.lmstudio import LMStudioConfig
from mem0.configs.llms.ollama import OllamaConfig
from mem0.configs.llms.openai import OpenAIConfig
@@ -45,6 +46,7 @@ class LlmFactory:
"azure_openai_structured": ("mem0.llms.azure_openai_structured.AzureOpenAIStructuredLLM", AzureOpenAIConfig),
"gemini": ("mem0.llms.gemini.GeminiLLM", BaseLlmConfig),
"deepseek": ("mem0.llms.deepseek.DeepSeekLLM", DeepSeekConfig),
+ "minimax": ("mem0.llms.minimax.MiniMaxLLM", MinimaxConfig),
"xai": ("mem0.llms.xai.XAILLM", BaseLlmConfig),
"sarvam": ("mem0.llms.sarvam.SarvamLLM", BaseLlmConfig),
"lmstudio": ("mem0.llms.lmstudio.LMStudioLLM", LMStudioConfig),
diff --git a/tests/llms/test_minimax.py b/tests/llms/test_minimax.py
new file mode 100644
index 000000000..0240f24bd
--- /dev/null
+++ b/tests/llms/test_minimax.py
@@ -0,0 +1,194 @@
+import os
+from unittest.mock import Mock, patch
+
+import pytest
+
+from mem0.configs.llms.base import BaseLlmConfig
+from mem0.configs.llms.minimax import MinimaxConfig
+from mem0.llms.minimax import MiniMaxLLM
+from mem0.utils.factory import LlmFactory
+
+
+@pytest.fixture
+def mock_minimax_client():
+ with patch("mem0.llms.minimax.OpenAI") as mock_openai:
+ mock_client = Mock()
+ mock_openai.return_value = mock_client
+ yield mock_client
+
+
+def test_minimax_llm_default_base_url():
+ """Default config uses MiniMax official base URL."""
+ config = BaseLlmConfig(
+ 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.minimax.io/v1"
+
+
+def test_minimax_llm_env_base_url():
+ """Config uses MINIMAX_API_BASE env variable when set."""
+ provider_base_url = "https://api.provider.com/v1/"
+ os.environ["MINIMAX_API_BASE"] = provider_base_url
+ try:
+ config = MinimaxConfig(
+ model="MiniMax-M2.7",
+ temperature=0.7,
+ max_tokens=100,
+ top_p=1.0,
+ api_key="api_key",
+ )
+ llm = MiniMaxLLM(config)
+ assert str(llm.client.base_url).rstrip("/") == provider_base_url.rstrip("/")
+ finally:
+ os.environ.pop("MINIMAX_API_BASE", None)
+
+
+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.7",
+ temperature=0.7,
+ max_tokens=100,
+ top_p=1.0,
+ api_key="api_key",
+ minimax_base_url=config_base_url,
+ )
+ llm = MiniMaxLLM(config)
+ assert str(llm.client.base_url).rstrip("/") == config_base_url.rstrip("/")
+
+
+def test_minimax_llm_default_model(mock_minimax_client):
+ """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.7"
+
+
+def test_minimax_llm_env_api_key():
+ """Uses MINIMAX_API_KEY env when api_key not in config."""
+ os.environ["MINIMAX_API_KEY"] = "env-api-key"
+ try:
+ with patch("mem0.llms.minimax.OpenAI") as mock_openai:
+ mock_client = Mock()
+ mock_openai.return_value = mock_client
+ 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.minimax.io/v1",
+ )
+ finally:
+ os.environ.pop("MINIMAX_API_KEY", None)
+
+
+def test_generate_response_without_tools(mock_minimax_client):
+ """generate_response returns text when no tools provided."""
+ 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": "system", "content": "You are a helpful assistant."},
+ {"role": "user", "content": "Hello, how are you?"},
+ ]
+
+ mock_response = Mock()
+ mock_response.choices = [Mock(message=Mock(content="I'm doing well, thank you for asking!"))]
+ mock_minimax_client.chat.completions.create.return_value = mock_response
+
+ response = llm.generate_response(messages)
+
+ 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
+ )
+ assert response == "I'm doing well, thank you for asking!"
+
+
+def test_generate_response_with_tools(mock_minimax_client):
+ """generate_response returns tool_calls when tools provided."""
+ 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": "system", "content": "You are a helpful assistant."},
+ {"role": "user", "content": "Add a new memory: Today is a sunny day."},
+ ]
+ tools = [
+ {
+ "type": "function",
+ "function": {
+ "name": "add_memory",
+ "description": "Add a memory",
+ "parameters": {
+ "type": "object",
+ "properties": {"data": {"type": "string", "description": "Data to add to memory"}},
+ "required": ["data"],
+ },
+ },
+ }
+ ]
+
+ mock_response = Mock()
+ mock_message = Mock()
+ mock_message.content = "I've added the memory for you."
+
+ mock_tool_call = Mock()
+ mock_tool_call.function.name = "add_memory"
+ mock_tool_call.function.arguments = '{"data": "Today is a sunny day."}'
+
+ mock_message.tool_calls = [mock_tool_call]
+ mock_response.choices = [Mock(message=mock_message)]
+ mock_minimax_client.chat.completions.create.return_value = mock_response
+
+ response = llm.generate_response(messages, tools=tools)
+
+ 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,
+ tools=tools,
+ tool_choice="auto",
+ )
+
+ assert response["content"] == "I've added the memory for you."
+ assert len(response["tool_calls"]) == 1
+ assert response["tool_calls"][0]["name"] == "add_memory"
+ 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.7", "api_key": "test-key"})
+ assert isinstance(llm, MiniMaxLLM)
+ assert llm.config.model == "MiniMax-M2.7"