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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ CAI is built on the following core principles:
- **Anthropic**: `Claude 3.7`, `Claude 3.5`, `Claude 3`, `Claude 3 Opus`
- **OpenAI**: `O1`, `O1 Mini`, `O3 Mini`, `GPT-4o`, `GPT-4.5 Preview`
- **DeepSeek**: `DeepSeek V3`, `DeepSeek R1`
- **MiniMax**: `MiniMax-M2.7`, `MiniMax-M2.5`, `MiniMax-M2.5-highspeed` ([docs](docs/providers/minimax.md))
- **Ollama**: `Qwen2.5 72B`, `Qwen2.5 14B`, etc


Expand Down
79 changes: 79 additions & 0 deletions docs/providers/minimax.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# MiniMax Configuration

#### [MiniMax AI](https://www.minimax.io/)

MiniMax provides large language models with an OpenAI-compatible API. CAI includes a built-in `MiniMaxProvider` for easy integration.

## Setup

1. Get an API key from [MiniMax](https://platform.minimax.chat/).
2. Set the environment variable:

```bash
export MINIMAX_API_KEY=<your-api-key>
```

## Usage

### Option 1: Using MiniMaxProvider (Recommended)

```python
from cai.sdk.agents import Agent, Runner, RunConfig
from cai.sdk.agents.models.minimax_provider import MiniMaxProvider

provider = MiniMaxProvider()

agent = Agent(
name="assistant",
instructions="You are a helpful assistant.",
)

result = await Runner.run(
agent,
"Hello!",
run_config=RunConfig(model_provider=provider),
)
```

### Option 2: Using environment variables with LiteLLM

```bash
CAI_MODEL=openai/MiniMax-M2.7
MINIMAX_API_KEY=<your-api-key>
OPENAI_API_BASE=https://api.minimax.io/v1
```

### Option 3: Direct model on Agent

```python
from openai import AsyncOpenAI
from cai.sdk.agents import Agent, OpenAIChatCompletionsModel

client = AsyncOpenAI(
api_key="<your-api-key>",
base_url="https://api.minimax.io/v1",
)

agent = Agent(
name="assistant",
instructions="You are a helpful assistant.",
model=OpenAIChatCompletionsModel(
model="MiniMax-M2.7",
openai_client=client,
),
)
```

## Available Models

| Model | Context Window | Description |
|-------|---------------|-------------|
| `MiniMax-M2.7` | 1M tokens | Latest and most capable model |
| `MiniMax-M2.5` | 1M tokens | Strong general-purpose model |
| `MiniMax-M2.5-highspeed` | 204K tokens | Optimized for speed |

## Notes

- MiniMax uses an OpenAI-compatible API, so it works with `OpenAIChatCompletionsModel`.
- Tracing is sent to OpenAI by default. If you don't have an OpenAI API key, disable tracing with `set_tracing_disabled(True)` or set a tracing-specific key.
- Temperature range: `[0.0, 1.0]`.
69 changes: 69 additions & 0 deletions examples/model_providers/minimax_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
"""Example of using MiniMax as an LLM provider with CAI.

Prerequisites:
- Set the MINIMAX_API_KEY environment variable.

Usage:
python examples/model_providers/minimax_example.py
"""

from __future__ import annotations

import asyncio
import os

from agents import (
Agent,
RunConfig,
Runner,
function_tool,
set_tracing_disabled,
)
from agents.models.minimax_provider import MiniMaxProvider

# Disable tracing if you don't have an OpenAI API key for trace uploads
set_tracing_disabled(disabled=True)

# Create the MiniMax provider (reads MINIMAX_API_KEY from env)
minimax_provider = MiniMaxProvider()


@function_tool
def get_weather(city: str) -> str:
"""Get the current weather for a city."""
return f"The weather in {city} is sunny and 22°C."


async def main():
agent = Agent(
name="Assistant",
instructions="You are a helpful assistant. Keep answers concise.",
tools=[get_weather],
)

# Use MiniMax-M2.7 (default)
result = await Runner.run(
agent,
"What's the weather in Tokyo?",
run_config=RunConfig(model_provider=minimax_provider),
)
print("MiniMax-M2.7 response:", result.final_output)

# Use MiniMax-M2.5-highspeed for faster responses
highspeed_provider = MiniMaxProvider()
agent_fast = Agent(
name="Fast Assistant",
instructions="You are a helpful assistant. Keep answers concise.",
model="MiniMax-M2.5-highspeed",
)

result = await Runner.run(
agent_fast,
"Tell me a short joke.",
run_config=RunConfig(model_provider=highspeed_provider),
)
print("MiniMax-M2.5-highspeed response:", result.final_output)


if __name__ == "__main__":
asyncio.run(main())
2 changes: 2 additions & 0 deletions src/cai/sdk/agents/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
from .model_settings import ModelSettings
from .models.interface import Model, ModelProvider, ModelTracing
from .models.openai_chatcompletions import OpenAIChatCompletionsModel
from .models.minimax_provider import MiniMaxProvider
from .models.openai_provider import OpenAIProvider
from .models.openai_responses import OpenAIResponsesModel
from .result import RunResult, RunResultStreaming
Expand Down Expand Up @@ -153,6 +154,7 @@ def enable_verbose_stdout_logging():
"ModelProvider",
"ModelTracing",
"ModelSettings",
"MiniMaxProvider",
"OpenAIChatCompletionsModel",
"OpenAIProvider",
"OpenAIResponsesModel",
Expand Down
95 changes: 95 additions & 0 deletions src/cai/sdk/agents/models/minimax_provider.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
from __future__ import annotations

import os

import httpx
from openai import AsyncOpenAI, DefaultAsyncHttpxClient

from .interface import Model, ModelProvider
from .openai_chatcompletions import OpenAIChatCompletionsModel

MINIMAX_DEFAULT_MODEL: str = "MiniMax-M2.7"
MINIMAX_API_BASE_URL: str = "https://api.minimax.io/v1"

_http_client: httpx.AsyncClient | None = None


def _shared_http_client() -> httpx.AsyncClient:
global _http_client
if _http_client is None:
_http_client = DefaultAsyncHttpxClient()
return _http_client


class MiniMaxProvider(ModelProvider):
"""A model provider that uses MiniMax's OpenAI-compatible API.

MiniMax provides large language models accessible via an OpenAI-compatible
chat completions endpoint. Supported models include MiniMax-M2.7,
MiniMax-M2.5, and MiniMax-M2.5-highspeed.

The provider reads the API key from the ``MINIMAX_API_KEY`` environment
variable by default, or you can pass it explicitly.

Example usage::

from cai.sdk.agents import Agent, Runner, RunConfig
from cai.sdk.agents.models.minimax_provider import MiniMaxProvider

provider = MiniMaxProvider()
agent = Agent(name="assistant", instructions="You are helpful.")
result = await Runner.run(
agent,
"Hello!",
run_config=RunConfig(model_provider=provider),
)
"""

def __init__(
self,
*,
api_key: str | None = None,
base_url: str | None = None,
openai_client: AsyncOpenAI | None = None,
) -> None:
"""Create a new MiniMax provider.

Args:
api_key: The MiniMax API key. If not provided, reads from the
``MINIMAX_API_KEY`` environment variable.
base_url: The base URL for the MiniMax API. Defaults to
``https://api.minimax.io/v1``.
openai_client: An optional pre-configured AsyncOpenAI client.
If provided, ``api_key`` and ``base_url`` are ignored.
"""
if openai_client is not None:
assert api_key is None and base_url is None, (
"Don't provide api_key or base_url if you provide openai_client"
)
self._client: AsyncOpenAI | None = openai_client
else:
self._client = None
self._stored_api_key = api_key
self._stored_base_url = base_url

def _get_client(self) -> AsyncOpenAI:
if self._client is None:
api_key = self._stored_api_key or os.environ.get("MINIMAX_API_KEY")
if not api_key:
raise ValueError(
"MiniMax API key not found. Set the MINIMAX_API_KEY environment "
"variable or pass api_key to MiniMaxProvider()."
)
self._client = AsyncOpenAI(
api_key=api_key,
base_url=self._stored_base_url or MINIMAX_API_BASE_URL,
http_client=_shared_http_client(),
)
return self._client

def get_model(self, model_name: str | None) -> Model:
if model_name is None:
model_name = MINIMAX_DEFAULT_MODEL

client = self._get_client()
return OpenAIChatCompletionsModel(model=model_name, openai_client=client)
10 changes: 10 additions & 0 deletions src/cai/sdk/agents/models/openai_chatcompletions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2830,6 +2830,16 @@ async def _fetch_response(
)
elif "gemini" in model_str:
kwargs.pop("parallel_tool_calls", None)
elif "minimax" in model_str:
# MiniMax uses OpenAI-compatible API at api.minimax.io
litellm.drop_params = True
kwargs["api_base"] = str(self._get_client().base_url).rstrip("/")
kwargs["custom_llm_provider"] = "openai"
kwargs["api_key"] = self._get_client().api_key
kwargs.pop("store", None)
kwargs.pop("parallel_tool_calls", None)
if not converted_tools:
kwargs.pop("tool_choice", None)
elif "qwen" in model_str or ":" in model_str:
# Handle Ollama-served models with custom formats (e.g., alias1)
# These typically need the Ollama provider
Expand Down
Loading