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
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,17 @@ For each of these graphs there is the multi version. It allows to make calls of

It is possible to use different LLM through APIs, such as **OpenAI**, **Groq**, **Azure**, **Gemini**, **[MiniMax](docs/minimax.md)** and more, or local models using **Ollama**.

For MiniMax, use `{"llm": {"model_provider": "minimax", "api_key": "YOUR_MINIMAX_API_KEY"}}`
with `SmartScraperGraph` to select `MiniMax-M3.1-Flash` by default. The current catalog
also includes `MiniMax-M3`; explicit saved model IDs remain supported. Both current
models have a 1,000,000-token context window. The adapter uses Chat Completions and
preserves reasoning and tool history; pass `reasoning_effort` (`low`, `medium`,
`high`, `xhigh`, or `max`) to tune Flash thinking. Omit it for the API default of
`max`. Flash does not accept disabled thinking, `reasoning_effort="none"`,
`reasoning_split=false`, or `service_tier`. See the
[MiniMax API reference](https://platform.minimax.io/docs/api-reference/text-openai-api).
Explicit `base_url` / `openai_api_base` and model IDs are passed through unchanged.

Remember to have [Ollama](https://ollama.com/) installed and download the models using the **ollama pull** command, if you want to use local models.


Expand Down
13 changes: 10 additions & 3 deletions scrapegraphai/graphs/abstract_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from pydantic import BaseModel

from ..helpers import models_tokens
from ..helpers.models_tokens import MINIMAX_LEGACY_MODEL_TOKENS
from ..models import XAI, CLoD, DeepSeek, MiniMax, Nvidia, OneApi
from ..utils.logging import get_logger, set_verbosity_info, set_verbosity_warning

Expand Down Expand Up @@ -177,6 +178,9 @@ def _create_llm(self, llm_config: dict) -> object:
"minimax",
}

if llm_params.get("model_provider") == "minimax" and "model" not in llm_params:
llm_params["model"] = next(iter(models_tokens["minimax"]))

if "/" in llm_params["model"]:
split_model_provider = llm_params["model"].split("/", 1)
llm_params["model_provider"] = split_model_provider[0]
Expand All @@ -187,6 +191,8 @@ def _create_llm(self, llm_config: dict) -> object:
for provider, models_d in models_tokens.items()
if llm_params["model"] in models_d
]
if llm_params["model"] in MINIMAX_LEGACY_MODEL_TOKENS:
possible_providers.append("minimax")
if len(possible_providers) <= 0:
raise ValueError(
f"""Provider {llm_params["model_provider"]} is not supported.
Expand All @@ -209,9 +215,10 @@ def _create_llm(self, llm_config: dict) -> object:

if llm_params.get("model_tokens", None) is None:
try:
self.model_token = models_tokens[llm_params["model_provider"]][
llm_params["model"]
]
token_limits = models_tokens[llm_params["model_provider"]]
if llm_params["model_provider"] == "minimax":
token_limits = {**MINIMAX_LEGACY_MODEL_TOKENS, **token_limits}
self.model_token = token_limits[llm_params["model"]]
except KeyError:
logger.warning(
"Max input tokens for model %s/%s not found, "
Expand Down
9 changes: 7 additions & 2 deletions scrapegraphai/helpers/models_tokens.py
Original file line number Diff line number Diff line change
Expand Up @@ -425,8 +425,13 @@
"grok-beta": 128000,
},
"minimax": {
"MiniMax-M3.1-Flash": 1000000,
"MiniMax-M3": 1000000,
"MiniMax-M2.7": 204800,
"MiniMax-M2.7-highspeed": 204800,
},
}

# Saved model IDs remain routable without appearing in the current catalog.
MINIMAX_LEGACY_MODEL_TOKENS = {
"MiniMax-M2.7": 204800,
"MiniMax-M2.7-highspeed": 204800,
}
40 changes: 39 additions & 1 deletion scrapegraphai/models/minimax.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

from langchain_openai import ChatOpenAI


DEFAULT_MINIMAX_OPENAI_BASE_URL = "https://api.minimax.io/v1"


Expand All @@ -19,9 +18,48 @@ class MiniMax(ChatOpenAI):
"""

def __init__(self, **llm_config):
if "model" not in llm_config and "model_name" not in llm_config:
llm_config["model"] = "MiniMax-M3.1-Flash"
if "api_key" in llm_config:
llm_config["openai_api_key"] = llm_config.pop("api_key")
if "base_url" not in llm_config and "openai_api_base" not in llm_config:
llm_config["openai_api_base"] = DEFAULT_MINIMAX_OPENAI_BASE_URL

super().__init__(**llm_config)

def _get_request_payload(self, input_, *, stop=None, **kwargs):
payload = super()._get_request_payload(input_, stop=stop, **kwargs)
# ChatOpenAI only serializes standard message fields. MiniMax requires
# its separate reasoning field to be replayed alongside tool calls.
if "messages" in payload:
messages = self._convert_input(input_).to_messages()
for message, serialized in zip(messages, payload["messages"]):
if serialized["role"] == "assistant":
reasoning = message.additional_kwargs.get("reasoning_content")
if reasoning is not None:
serialized["reasoning_content"] = reasoning
return payload

def _create_chat_result(self, response, generation_info=None):
result = super()._create_chat_result(response, generation_info)
response_dict = (
response if isinstance(response, dict) else response.model_dump()
)
for generation, choice in zip(result.generations, response_dict["choices"]):
reasoning = choice["message"].get("reasoning_content")
if reasoning is not None:
generation.message.additional_kwargs["reasoning_content"] = reasoning
return result

def _convert_chunk_to_generation_chunk(
self, chunk, default_chunk_class, base_generation_info
):
generation = super()._convert_chunk_to_generation_chunk(
chunk, default_chunk_class, base_generation_info
)
choices = chunk.get("choices") or chunk.get("chunk", {}).get("choices", [])
if generation is not None and choices:
reasoning = (choices[0].get("delta") or {}).get("reasoning_content")
if reasoning is not None:
generation.message.additional_kwargs["reasoning_content"] = reasoning
return generation
3 changes: 3 additions & 0 deletions scrapegraphai/utils/model_costs.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
"amazon.titan-text-express-v1": 0.0002,
"amazon.titan-text-lite-v1": 0.00015,
"amazon.titan-text-premier-v1:0": 0.0005,
"MiniMax-M3.1-Flash": 0.00015,
"MiniMax-M2.7": 0.0003,
}

Expand Down Expand Up @@ -103,11 +104,13 @@
"amazon.titan-text-express-v1": 0.0006,
"amazon.titan-text-lite-v1": 0.0002,
"amazon.titan-text-premier-v1:0": 0.0015,
"MiniMax-M3.1-Flash": 0.0006,
"MiniMax-M2.7": 0.0012,
}


MODEL_CACHE_COST_PER_1K_TOKENS = {
"MiniMax-M3.1-Flash": {"read": 0.000015, "write": None},
"MiniMax-M2.7": {"read": 0.00006, "write": 0.000375},
}

Expand Down
Loading
Loading