From 6ad0464aca05f5a925dc8ffd8db812ad112b9855 Mon Sep 17 00:00:00 2001 From: Octopus Date: Sat, 14 Mar 2026 11:33:43 -0500 Subject: [PATCH 1/3] feat: add MiniMax LLM extension Add a new LLM extension for MiniMax (https://www.minimaxi.com/), providing support for MiniMax-M2.5 and MiniMax-M2.5-highspeed models with up to 204K context window via an OpenAI-compatible API. Changes: - Add extensions/llms/minimax/ with MiniMax LLM class extending BaseOpenAI - Add unit tests for MiniMax extension (15 tests) - Update LLM documentation with MiniMax setup instructions --- docs/v3/large-language-models.mdx | 31 ++++ extensions/llms/minimax/README.md | 54 +++++++ .../llms/minimax/pandasai_minimax/__init__.py | 3 + .../llms/minimax/pandasai_minimax/minimax.py | 79 +++++++++ extensions/llms/minimax/pyproject.toml | 30 ++++ extensions/llms/minimax/tests/__init__.py | 0 extensions/llms/minimax/tests/test_minimax.py | 153 ++++++++++++++++++ 7 files changed, 350 insertions(+) create mode 100644 extensions/llms/minimax/README.md create mode 100644 extensions/llms/minimax/pandasai_minimax/__init__.py create mode 100644 extensions/llms/minimax/pandasai_minimax/minimax.py create mode 100644 extensions/llms/minimax/pyproject.toml create mode 100644 extensions/llms/minimax/tests/__init__.py create mode 100644 extensions/llms/minimax/tests/test_minimax.py diff --git a/docs/v3/large-language-models.mdx b/docs/v3/large-language-models.mdx index d3f95a659..92e164b9d 100644 --- a/docs/v3/large-language-models.mdx +++ b/docs/v3/large-language-models.mdx @@ -90,6 +90,37 @@ llm = AzureOpenAI(api_base="https://.openai.azure.com/", pai.config.set({"llm": llm}) ``` +## MiniMax models + +[MiniMax](https://www.minimaxi.com/) provides powerful large language models with up to 204K context window. + +Install the pandasai-minimax extension: + +```bash +# Using poetry +poetry add pandasai-minimax + +# Using pip +pip install pandasai-minimax +``` + +In order to use MiniMax models, you need to have a MiniMax API key. You can get one from the [MiniMax platform](https://www.minimaxi.com/). +Once you have an API key, you can use it to instantiate a MiniMax object: + +Configure MiniMax: + +```python +import pandasai as pai +from pandasai_minimax import MiniMax + +llm = MiniMax(api_token="my-minimax-api-key") +# Or set MINIMAX_API_KEY environment variable + +pai.config.set({"llm": llm}) +``` + +Supported models: `MiniMax-M2.5` (default), `MiniMax-M2.5-highspeed`. + ## How to set up any LLM? LiteLLM provides a unified interface to interact with 100+ LLM models from various providers including OpenAI, Azure, Anthropic, Google, AWS, Hugging Face, and many more. This makes it easy to switch between different LLM providers without changing your code. diff --git a/extensions/llms/minimax/README.md b/extensions/llms/minimax/README.md new file mode 100644 index 000000000..4e8e21e42 --- /dev/null +++ b/extensions/llms/minimax/README.md @@ -0,0 +1,54 @@ +# MiniMax Extension for PandasAI + +This extension integrates [MiniMax](https://www.minimaxi.com/) with PandasAI, providing MiniMax LLM support. + +MiniMax offers powerful large language models with up to 204K context window through an OpenAI-compatible API. + +## Installation + +```bash +# Using pip +pip install pandasai-minimax + +# Using poetry +poetry add pandasai-minimax +``` + +## Usage + +```python +import pandasai as pai +from pandasai_minimax import MiniMax + +llm = MiniMax(api_token="your-minimax-api-key") +# Or set MINIMAX_API_KEY environment variable + +pai.config.set({"llm": llm}) +``` + +## Supported Models + +| Model | Context Window | Description | +|-------|---------------|-------------| +| `MiniMax-M2.5` (default) | 204K | Most capable model | +| `MiniMax-M2.5-highspeed` | 204K | Optimized for speed | + +## Configuration + +You can pass additional parameters: + +```python +llm = MiniMax( + api_token="your-minimax-api-key", + model="MiniMax-M2.5-highspeed", + temperature=0.3, + max_tokens=2000, +) +``` + +## Environment Variables + +| Variable | Description | +|----------|-------------| +| `MINIMAX_API_KEY` | Your MiniMax API key | +| `MINIMAX_API_BASE` | Custom API base URL (default: `https://api.minimax.io/v1`) | diff --git a/extensions/llms/minimax/pandasai_minimax/__init__.py b/extensions/llms/minimax/pandasai_minimax/__init__.py new file mode 100644 index 000000000..c7d3e77e2 --- /dev/null +++ b/extensions/llms/minimax/pandasai_minimax/__init__.py @@ -0,0 +1,3 @@ +from .minimax import MiniMax + +__all__ = ["MiniMax"] diff --git a/extensions/llms/minimax/pandasai_minimax/minimax.py b/extensions/llms/minimax/pandasai_minimax/minimax.py new file mode 100644 index 000000000..7dc749c94 --- /dev/null +++ b/extensions/llms/minimax/pandasai_minimax/minimax.py @@ -0,0 +1,79 @@ +import os +from typing import Any, Dict, Optional + +import openai + +from pandasai.exceptions import APIKeyNotFoundError, UnsupportedModelError +from pandasai.helpers import load_dotenv + +from pandasai_openai.base import BaseOpenAI + +load_dotenv() + + +class MiniMax(BaseOpenAI): + """MiniMax LLM using BaseOpenAI Class. + + MiniMax provides an OpenAI-compatible API. This class connects to MiniMax's + API endpoint and supports MiniMax chat models. + + The default model is **MiniMax-M2.5**. + Supported models include: MiniMax-M2.5, MiniMax-M2.5-highspeed. + """ + + _supported_chat_models = [ + "MiniMax-M2.5", + "MiniMax-M2.5-highspeed", + ] + + model: str = "MiniMax-M2.5" + api_base: str = "https://api.minimax.io/v1" + temperature: float = 0.1 + + def __init__( + self, + api_token: Optional[str] = None, + **kwargs, + ): + """ + __init__ method of MiniMax Class. + + Args: + api_token (str): API Token for MiniMax platform. + Can also be set via MINIMAX_API_KEY environment variable. + **kwargs: Extended Parameters inferred from BaseOpenAI class. + """ + self.api_token = api_token or os.getenv("MINIMAX_API_KEY") or None + + if not self.api_token: + raise APIKeyNotFoundError("MiniMax API key is required") + + self.api_base = ( + kwargs.get("api_base") + or os.getenv("MINIMAX_API_BASE") + or self.api_base + ) + + self.openai_proxy = kwargs.get("openai_proxy") or os.getenv("OPENAI_PROXY") + if self.openai_proxy: + openai.proxy = {"http": self.openai_proxy, "https": self.openai_proxy} + + self._set_params(**kwargs) + + if self.model not in self._supported_chat_models: + raise UnsupportedModelError(self.model) + + self._is_chat_model = True + self.client = openai.OpenAI(**self._client_params).chat.completions + + @property + def _default_params(self) -> Dict[str, Any]: + """Get the default parameters for calling MiniMax API.""" + return { + **super()._default_params, + "model": self.model, + } + + @property + def type(self) -> str: + return "minimax" diff --git a/extensions/llms/minimax/pyproject.toml b/extensions/llms/minimax/pyproject.toml new file mode 100644 index 000000000..dbc54c844 --- /dev/null +++ b/extensions/llms/minimax/pyproject.toml @@ -0,0 +1,30 @@ +[tool.poetry] +name = "pandasai-minimax" +version = "0.1.0" +description = "MiniMax integration for PandasAI" +authors = ["PandasAI"] +license = "MIT" +readme = "README.md" + +[tool.poetry.urls] +"Documentation" = "https://docs.pandas-ai.com/" +"Repository" = "https://github.com/sinaptik-ai/pandas-ai" + +[tool.poetry.dependencies] +python = ">=3.8,<3.12" +pandasai = ">=3.0.0b4" +pandasai-openai = ">=0.1.0" +openai = "^1.3.7" +typing-extensions = "^4.0.0" + +[tool.poetry.group.test] +optional = true + +[tool.poetry.group.test.dependencies] +pytest = "^7.4.0" +pytest-cov = "^4.1.0" +pytest-mock = "^3.11.1" + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" diff --git a/extensions/llms/minimax/tests/__init__.py b/extensions/llms/minimax/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/extensions/llms/minimax/tests/test_minimax.py b/extensions/llms/minimax/tests/test_minimax.py new file mode 100644 index 000000000..eba02f918 --- /dev/null +++ b/extensions/llms/minimax/tests/test_minimax.py @@ -0,0 +1,153 @@ +"""Unit tests for the MiniMax LLM class""" + +import os +from unittest import mock + +import openai +import pytest + +from extensions.llms.minimax.pandasai_minimax import MiniMax +from pandasai.core.prompts.base import BasePrompt +from pandasai.exceptions import APIKeyNotFoundError, UnsupportedModelError + + +class OpenAIObject: + def __init__(self, dictionary): + self.__dict__.update(dictionary) + + +class TestMiniMaxLLM: + """Unit tests for the MiniMax LLM class""" + + @pytest.fixture + def prompt(self): + class MockBasePrompt(BasePrompt): + template: str = "instruction" + + return MockBasePrompt() + + def test_type_without_token(self): + with mock.patch.dict(os.environ, clear=True): + with pytest.raises(APIKeyNotFoundError): + MiniMax() + + def test_type_with_token(self): + assert MiniMax(api_token="test").type == "minimax" + + def test_default_model(self): + llm = MiniMax(api_token="test") + assert llm.model == "MiniMax-M2.5" + + def test_default_api_base(self): + llm = MiniMax(api_token="test") + assert llm.api_base == "https://api.minimax.io/v1" + + def test_default_temperature(self): + llm = MiniMax(api_token="test") + assert llm.temperature == 0.1 + + def test_proxy(self): + proxy = "http://proxy.mycompany.com:8080" + client = MiniMax(api_token="test", openai_proxy=proxy) + assert client.openai_proxy == proxy + assert openai.proxy["http"] == proxy + assert openai.proxy["https"] == proxy + + def test_params_setting(self): + llm = MiniMax( + api_token="test", + model="MiniMax-M2.5-highspeed", + temperature=0.5, + max_tokens=50, + top_p=1.0, + frequency_penalty=2.0, + presence_penalty=3.0, + stop=["\n"], + ) + + assert llm.model == "MiniMax-M2.5-highspeed" + assert llm.temperature == 0.5 + assert llm.max_tokens == 50 + assert llm.top_p == 1.0 + assert llm.frequency_penalty == 2.0 + assert llm.presence_penalty == 3.0 + assert llm.stop == ["\n"] + + def test_completion(self, mocker): + expected_text = "This is the generated text." + expected_response = OpenAIObject( + { + "choices": [{"text": expected_text}], + "usage": { + "prompt_tokens": 2, + "completion_tokens": 1, + "total_tokens": 3, + }, + "model": "MiniMax-M2.5", + } + ) + + minimax = MiniMax(api_token="test") + mocker.patch.object(minimax, "chat_completion", return_value=expected_response) + result = minimax.chat_completion("Some prompt.") + + minimax.chat_completion.assert_called_once_with("Some prompt.") + assert result == expected_response + + def test_chat_completion(self, mocker): + minimax = MiniMax(api_token="test") + expected_response = OpenAIObject( + { + "choices": [ + { + "text": "Hello, how can I help you today?", + "index": 0, + "logprobs": None, + "finish_reason": "stop", + "start_text": "", + } + ] + } + ) + + mocker.patch.object( + minimax, "chat_completion", return_value=expected_response + ) + + result = minimax.chat_completion("Hi") + minimax.chat_completion.assert_called_once_with("Hi") + + assert result == expected_response + + def test_call_with_unsupported_model(self, prompt): + with pytest.raises( + UnsupportedModelError, + ): + MiniMax(api_token="test", model="not-a-model") + + def test_call_supported_chat_model(self, mocker, prompt): + minimax = MiniMax(api_token="test", model="MiniMax-M2.5") + mocker.patch.object(minimax, "chat_completion", return_value="response") + + result = minimax.call(instruction=prompt) + assert result == "response" + + def test_call_highspeed_model(self, mocker, prompt): + minimax = MiniMax(api_token="test", model="MiniMax-M2.5-highspeed") + mocker.patch.object(minimax, "chat_completion", return_value="response") + + result = minimax.call(instruction=prompt) + assert result == "response" + + def test_is_chat_model(self): + llm = MiniMax(api_token="test") + assert llm._is_chat_model is True + + def test_env_api_key(self): + with mock.patch.dict(os.environ, {"MINIMAX_API_KEY": "env-test-key"}): + llm = MiniMax() + assert llm.api_token == "env-test-key" + + def test_custom_api_base(self): + llm = MiniMax(api_token="test", api_base="https://custom.api.com/v1") + assert llm.api_base == "https://custom.api.com/v1" From f4a59f9f6ffd5afedaca6aa72b3777983472f2a1 Mon Sep 17 00:00:00 2001 From: Octopus Date: Wed, 18 Mar 2026 11:32:05 -0500 Subject: [PATCH 2/3] feat: upgrade MiniMax default model to M2.7 Add MiniMax-M2.7 and MiniMax-M2.7-highspeed models as the new default, while retaining backward compatibility with M2.5 models. --- docs/v3/large-language-models.mdx | 2 +- extensions/llms/minimax/README.md | 8 +++++--- .../llms/minimax/pandasai_minimax/minimax.py | 9 ++++++--- extensions/llms/minimax/tests/test_minimax.py | 18 ++++++++++++++++-- 4 files changed, 28 insertions(+), 9 deletions(-) diff --git a/docs/v3/large-language-models.mdx b/docs/v3/large-language-models.mdx index 92e164b9d..527345c2f 100644 --- a/docs/v3/large-language-models.mdx +++ b/docs/v3/large-language-models.mdx @@ -119,7 +119,7 @@ llm = MiniMax(api_token="my-minimax-api-key") pai.config.set({"llm": llm}) ``` -Supported models: `MiniMax-M2.5` (default), `MiniMax-M2.5-highspeed`. +Supported models: `MiniMax-M2.7` (default), `MiniMax-M2.7-highspeed`, `MiniMax-M2.5`, `MiniMax-M2.5-highspeed`. ## How to set up any LLM? diff --git a/extensions/llms/minimax/README.md b/extensions/llms/minimax/README.md index 4e8e21e42..0f7181c64 100644 --- a/extensions/llms/minimax/README.md +++ b/extensions/llms/minimax/README.md @@ -30,8 +30,10 @@ pai.config.set({"llm": llm}) | Model | Context Window | Description | |-------|---------------|-------------| -| `MiniMax-M2.5` (default) | 204K | Most capable model | -| `MiniMax-M2.5-highspeed` | 204K | Optimized for speed | +| `MiniMax-M2.7` (default) | 204K | Latest and most capable model | +| `MiniMax-M2.7-highspeed` | 204K | Latest model optimized for speed | +| `MiniMax-M2.5` | 204K | Previous generation model | +| `MiniMax-M2.5-highspeed` | 204K | Previous generation, optimized for speed | ## Configuration @@ -40,7 +42,7 @@ You can pass additional parameters: ```python llm = MiniMax( api_token="your-minimax-api-key", - model="MiniMax-M2.5-highspeed", + model="MiniMax-M2.7-highspeed", temperature=0.3, max_tokens=2000, ) diff --git a/extensions/llms/minimax/pandasai_minimax/minimax.py b/extensions/llms/minimax/pandasai_minimax/minimax.py index 7dc749c94..0646865fb 100644 --- a/extensions/llms/minimax/pandasai_minimax/minimax.py +++ b/extensions/llms/minimax/pandasai_minimax/minimax.py @@ -17,16 +17,19 @@ class MiniMax(BaseOpenAI): MiniMax provides an OpenAI-compatible API. This class connects to MiniMax's API endpoint and supports MiniMax chat models. - The default model is **MiniMax-M2.5**. - Supported models include: MiniMax-M2.5, MiniMax-M2.5-highspeed. + The default model is **MiniMax-M2.7**. + Supported models include: MiniMax-M2.7, MiniMax-M2.7-highspeed, + MiniMax-M2.5, MiniMax-M2.5-highspeed. """ _supported_chat_models = [ + "MiniMax-M2.7", + "MiniMax-M2.7-highspeed", "MiniMax-M2.5", "MiniMax-M2.5-highspeed", ] - model: str = "MiniMax-M2.5" + model: str = "MiniMax-M2.7" api_base: str = "https://api.minimax.io/v1" temperature: float = 0.1 diff --git a/extensions/llms/minimax/tests/test_minimax.py b/extensions/llms/minimax/tests/test_minimax.py index eba02f918..5950526fd 100644 --- a/extensions/llms/minimax/tests/test_minimax.py +++ b/extensions/llms/minimax/tests/test_minimax.py @@ -36,7 +36,7 @@ def test_type_with_token(self): def test_default_model(self): llm = MiniMax(api_token="test") - assert llm.model == "MiniMax-M2.5" + assert llm.model == "MiniMax-M2.7" def test_default_api_base(self): llm = MiniMax(api_token="test") @@ -83,7 +83,7 @@ def test_completion(self, mocker): "completion_tokens": 1, "total_tokens": 3, }, - "model": "MiniMax-M2.5", + "model": "MiniMax-M2.7", } ) @@ -139,6 +139,20 @@ def test_call_highspeed_model(self, mocker, prompt): result = minimax.call(instruction=prompt) assert result == "response" + def test_call_m27_model(self, mocker, prompt): + minimax = MiniMax(api_token="test", model="MiniMax-M2.7") + mocker.patch.object(minimax, "chat_completion", return_value="response") + + result = minimax.call(instruction=prompt) + assert result == "response" + + def test_call_m27_highspeed_model(self, mocker, prompt): + minimax = MiniMax(api_token="test", model="MiniMax-M2.7-highspeed") + mocker.patch.object(minimax, "chat_completion", return_value="response") + + result = minimax.call(instruction=prompt) + assert result == "response" + def test_is_chat_model(self): llm = MiniMax(api_token="test") assert llm._is_chat_model is True From 32184dc1549c8be029553c999aaf51b55260dc6a Mon Sep 17 00:00:00 2001 From: octo-patch Date: Wed, 3 Jun 2026 00:30:51 +0800 Subject: [PATCH 3/3] feat: upgrade MiniMax default model to M3 - Add MiniMax-M3 to model list and set as default - Keep MiniMax-M2.7 and MiniMax-M2.7-highspeed - Remove older models (M2.5/M2.5-highspeed) - Update related tests --- docs/v3/large-language-models.mdx | 2 +- extensions/llms/minimax/README.md | 7 +++---- .../llms/minimax/pandasai_minimax/minimax.py | 11 +++++------ extensions/llms/minimax/tests/test_minimax.py | 19 ++++++------------- 4 files changed, 15 insertions(+), 24 deletions(-) diff --git a/docs/v3/large-language-models.mdx b/docs/v3/large-language-models.mdx index 527345c2f..4b1d8fb26 100644 --- a/docs/v3/large-language-models.mdx +++ b/docs/v3/large-language-models.mdx @@ -119,7 +119,7 @@ llm = MiniMax(api_token="my-minimax-api-key") pai.config.set({"llm": llm}) ``` -Supported models: `MiniMax-M2.7` (default), `MiniMax-M2.7-highspeed`, `MiniMax-M2.5`, `MiniMax-M2.5-highspeed`. +Supported models: `MiniMax-M3` (default), `MiniMax-M2.7`, `MiniMax-M2.7-highspeed`. ## How to set up any LLM? diff --git a/extensions/llms/minimax/README.md b/extensions/llms/minimax/README.md index 0f7181c64..1441af934 100644 --- a/extensions/llms/minimax/README.md +++ b/extensions/llms/minimax/README.md @@ -30,10 +30,9 @@ pai.config.set({"llm": llm}) | Model | Context Window | Description | |-------|---------------|-------------| -| `MiniMax-M2.7` (default) | 204K | Latest and most capable model | -| `MiniMax-M2.7-highspeed` | 204K | Latest model optimized for speed | -| `MiniMax-M2.5` | 204K | Previous generation model | -| `MiniMax-M2.5-highspeed` | 204K | Previous generation, optimized for speed | +| `MiniMax-M3` (default) | 512K | Latest model with 128K max output, supports image input | +| `MiniMax-M2.7` | 204K | Previous generation, most capable | +| `MiniMax-M2.7-highspeed` | 204K | Previous generation, optimized for speed | ## Configuration diff --git a/extensions/llms/minimax/pandasai_minimax/minimax.py b/extensions/llms/minimax/pandasai_minimax/minimax.py index 0646865fb..f656e65ef 100644 --- a/extensions/llms/minimax/pandasai_minimax/minimax.py +++ b/extensions/llms/minimax/pandasai_minimax/minimax.py @@ -17,19 +17,18 @@ class MiniMax(BaseOpenAI): MiniMax provides an OpenAI-compatible API. This class connects to MiniMax's API endpoint and supports MiniMax chat models. - The default model is **MiniMax-M2.7**. - Supported models include: MiniMax-M2.7, MiniMax-M2.7-highspeed, - MiniMax-M2.5, MiniMax-M2.5-highspeed. + The default model is **MiniMax-M3** (512K context, 128K max output, supports + image input). Supported models include: MiniMax-M3, MiniMax-M2.7, + MiniMax-M2.7-highspeed. """ _supported_chat_models = [ + "MiniMax-M3", "MiniMax-M2.7", "MiniMax-M2.7-highspeed", - "MiniMax-M2.5", - "MiniMax-M2.5-highspeed", ] - model: str = "MiniMax-M2.7" + model: str = "MiniMax-M3" api_base: str = "https://api.minimax.io/v1" temperature: float = 0.1 diff --git a/extensions/llms/minimax/tests/test_minimax.py b/extensions/llms/minimax/tests/test_minimax.py index 5950526fd..ddedecdf2 100644 --- a/extensions/llms/minimax/tests/test_minimax.py +++ b/extensions/llms/minimax/tests/test_minimax.py @@ -36,7 +36,7 @@ def test_type_with_token(self): def test_default_model(self): llm = MiniMax(api_token="test") - assert llm.model == "MiniMax-M2.7" + assert llm.model == "MiniMax-M3" def test_default_api_base(self): llm = MiniMax(api_token="test") @@ -56,7 +56,7 @@ def test_proxy(self): def test_params_setting(self): llm = MiniMax( api_token="test", - model="MiniMax-M2.5-highspeed", + model="MiniMax-M2.7-highspeed", temperature=0.5, max_tokens=50, top_p=1.0, @@ -65,7 +65,7 @@ def test_params_setting(self): stop=["\n"], ) - assert llm.model == "MiniMax-M2.5-highspeed" + assert llm.model == "MiniMax-M2.7-highspeed" assert llm.temperature == 0.5 assert llm.max_tokens == 50 assert llm.top_p == 1.0 @@ -83,7 +83,7 @@ def test_completion(self, mocker): "completion_tokens": 1, "total_tokens": 3, }, - "model": "MiniMax-M2.7", + "model": "MiniMax-M3", } ) @@ -125,15 +125,8 @@ def test_call_with_unsupported_model(self, prompt): ): MiniMax(api_token="test", model="not-a-model") - def test_call_supported_chat_model(self, mocker, prompt): - minimax = MiniMax(api_token="test", model="MiniMax-M2.5") - mocker.patch.object(minimax, "chat_completion", return_value="response") - - result = minimax.call(instruction=prompt) - assert result == "response" - - def test_call_highspeed_model(self, mocker, prompt): - minimax = MiniMax(api_token="test", model="MiniMax-M2.5-highspeed") + def test_call_m3_model(self, mocker, prompt): + minimax = MiniMax(api_token="test", model="MiniMax-M3") mocker.patch.object(minimax, "chat_completion", return_value="response") result = minimax.call(instruction=prompt)