fix: address review feedback for the Minimax LLM provider
This commit is contained in:
@@ -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).
|
||||||
@@ -31,6 +31,7 @@ See the list of supported LLMs below.
|
|||||||
<Card title="Google AI" href="/components/llms/models/google_AI" />
|
<Card title="Google AI" href="/components/llms/models/google_AI" />
|
||||||
<Card title="AWS bedrock" href="/components/llms/models/aws_bedrock" />
|
<Card title="AWS bedrock" href="/components/llms/models/aws_bedrock" />
|
||||||
<Card title="DeepSeek" href="/components/llms/models/deepseek" />
|
<Card title="DeepSeek" href="/components/llms/models/deepseek" />
|
||||||
|
<Card title="MiniMax" href="/components/llms/models/minimax" />
|
||||||
<Card title="xAI" href="/components/llms/models/xAI" />
|
<Card title="xAI" href="/components/llms/models/xAI" />
|
||||||
<Card title="Sarvam AI" href="/components/llms/models/sarvam" />
|
<Card title="Sarvam AI" href="/components/llms/models/sarvam" />
|
||||||
<Card title="LM Studio" href="/components/llms/models/lmstudio" />
|
<Card title="LM Studio" href="/components/llms/models/lmstudio" />
|
||||||
|
|||||||
@@ -34,13 +34,13 @@ class MiniMaxLLM(LLMBase):
|
|||||||
super().__init__(config)
|
super().__init__(config)
|
||||||
|
|
||||||
if not self.config.model:
|
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")
|
api_key = self.config.api_key or os.getenv("MINIMAX_API_KEY")
|
||||||
base_url = (
|
base_url = (
|
||||||
self.config.minimax_base_url
|
self.config.minimax_base_url
|
||||||
or os.getenv("MINIMAX_API_BASE")
|
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)
|
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:
|
if tools:
|
||||||
params["tools"] = tools
|
params["tools"] = tools
|
||||||
params["tool_choice"] = tool_choice
|
params["tool_choice"] = tool_choice
|
||||||
|
|||||||
+39
-14
@@ -20,11 +20,11 @@ def mock_minimax_client():
|
|||||||
def test_minimax_llm_default_base_url():
|
def test_minimax_llm_default_base_url():
|
||||||
"""Default config uses MiniMax official base URL."""
|
"""Default config uses MiniMax official base URL."""
|
||||||
config = BaseLlmConfig(
|
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)
|
llm = MiniMaxLLM(config)
|
||||||
# OpenAI client may normalize URL with trailing slash
|
# 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():
|
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
|
os.environ["MINIMAX_API_BASE"] = provider_base_url
|
||||||
try:
|
try:
|
||||||
config = MinimaxConfig(
|
config = MinimaxConfig(
|
||||||
model="MiniMax-M2.1",
|
model="MiniMax-M2.7",
|
||||||
temperature=0.7,
|
temperature=0.7,
|
||||||
max_tokens=100,
|
max_tokens=100,
|
||||||
top_p=1.0,
|
top_p=1.0,
|
||||||
@@ -49,7 +49,7 @@ def test_minimax_llm_config_base_url():
|
|||||||
"""Config uses minimax_base_url when provided."""
|
"""Config uses minimax_base_url when provided."""
|
||||||
config_base_url = "https://api.config.com/v1/"
|
config_base_url = "https://api.config.com/v1/"
|
||||||
config = MinimaxConfig(
|
config = MinimaxConfig(
|
||||||
model="MiniMax-M2.1",
|
model="MiniMax-M2.7",
|
||||||
temperature=0.7,
|
temperature=0.7,
|
||||||
max_tokens=100,
|
max_tokens=100,
|
||||||
top_p=1.0,
|
top_p=1.0,
|
||||||
@@ -61,10 +61,10 @@ def test_minimax_llm_config_base_url():
|
|||||||
|
|
||||||
|
|
||||||
def test_minimax_llm_default_model(mock_minimax_client):
|
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")
|
config = MinimaxConfig(temperature=0.7, max_tokens=100, api_key="api_key")
|
||||||
llm = MiniMaxLLM(config)
|
llm = MiniMaxLLM(config)
|
||||||
assert llm.config.model == "MiniMax-M2.1"
|
assert llm.config.model == "MiniMax-M2.7"
|
||||||
|
|
||||||
|
|
||||||
def test_minimax_llm_env_api_key():
|
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:
|
with patch("mem0.llms.minimax.OpenAI") as mock_openai:
|
||||||
mock_client = Mock()
|
mock_client = Mock()
|
||||||
mock_openai.return_value = mock_client
|
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)
|
MiniMaxLLM(config)
|
||||||
mock_openai.assert_called_once_with(
|
mock_openai.assert_called_once_with(
|
||||||
api_key="env-api-key",
|
api_key="env-api-key",
|
||||||
base_url="https://api.minimaxi.io/v1",
|
base_url="https://api.minimax.io/v1",
|
||||||
)
|
)
|
||||||
finally:
|
finally:
|
||||||
os.environ.pop("MINIMAX_API_KEY", None)
|
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):
|
def test_generate_response_without_tools(mock_minimax_client):
|
||||||
"""generate_response returns text when no tools provided."""
|
"""generate_response returns text when no tools provided."""
|
||||||
config = BaseLlmConfig(
|
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)
|
llm = MiniMaxLLM(config)
|
||||||
messages = [
|
messages = [
|
||||||
@@ -102,7 +102,7 @@ def test_generate_response_without_tools(mock_minimax_client):
|
|||||||
response = llm.generate_response(messages)
|
response = llm.generate_response(messages)
|
||||||
|
|
||||||
mock_minimax_client.chat.completions.create.assert_called_once_with(
|
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!"
|
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):
|
def test_generate_response_with_tools(mock_minimax_client):
|
||||||
"""generate_response returns tool_calls when tools provided."""
|
"""generate_response returns tool_calls when tools provided."""
|
||||||
config = BaseLlmConfig(
|
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)
|
llm = MiniMaxLLM(config)
|
||||||
messages = [
|
messages = [
|
||||||
@@ -147,7 +147,7 @@ def test_generate_response_with_tools(mock_minimax_client):
|
|||||||
response = llm.generate_response(messages, tools=tools)
|
response = llm.generate_response(messages, tools=tools)
|
||||||
|
|
||||||
mock_minimax_client.chat.completions.create.assert_called_once_with(
|
mock_minimax_client.chat.completions.create.assert_called_once_with(
|
||||||
model="MiniMax-M2.1",
|
model="MiniMax-M2.7",
|
||||||
messages=messages,
|
messages=messages,
|
||||||
temperature=0.7,
|
temperature=0.7,
|
||||||
max_tokens=100,
|
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."}
|
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):
|
def test_factory_creates_minimax_llm(mock_minimax_client):
|
||||||
"""LlmFactory.create returns MiniMaxLLM for provider 'minimax'."""
|
"""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 isinstance(llm, MiniMaxLLM)
|
||||||
assert llm.config.model == "MiniMax-M2.1"
|
assert llm.config.model == "MiniMax-M2.7"
|
||||||
|
|||||||
Reference in New Issue
Block a user