Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions docs/v3/large-language-models.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,37 @@ llm = AzureOpenAI(api_base="https://<your-endpoint>.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-M3` (default), `MiniMax-M2.7`, `MiniMax-M2.7-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.
Expand Down
55 changes: 55 additions & 0 deletions extensions/llms/minimax/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# 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-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

You can pass additional parameters:

```python
llm = MiniMax(
api_token="your-minimax-api-key",
model="MiniMax-M2.7-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`) |
3 changes: 3 additions & 0 deletions extensions/llms/minimax/pandasai_minimax/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from .minimax import MiniMax

__all__ = ["MiniMax"]
81 changes: 81 additions & 0 deletions extensions/llms/minimax/pandasai_minimax/minimax.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
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-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",
]

model: str = "MiniMax-M3"
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"
30 changes: 30 additions & 0 deletions extensions/llms/minimax/pyproject.toml
Original file line number Diff line number Diff line change
@@ -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"
Empty file.
160 changes: 160 additions & 0 deletions extensions/llms/minimax/tests/test_minimax.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
"""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-M3"

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.7-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.7-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-M3",
}
)

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_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)
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

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"