From 7fefb4e829ab1fcac736eeeaf9de6d9ac937b872 Mon Sep 17 00:00:00 2001 From: octo-patch <266937838+octo-patch@users.noreply.github.com> Date: Wed, 8 Jul 2026 10:14:22 +0000 Subject: [PATCH 1/2] Add MiniMax LLM adapter --- .../public/icons/adapter-icons/MiniMax.png | Bin 0 -> 29953 bytes .../sdk1/src/unstract/sdk1/adapters/base1.py | 13 ++ .../unstract/sdk1/adapters/llm1/__init__.py | 2 + .../unstract/sdk1/adapters/llm1/minimax.py | 45 +++++++ .../sdk1/adapters/llm1/static/minimax.json | 113 ++++++++++++++++++ .../tests/test_branded_openai_adapters.py | 17 ++- 6 files changed, 188 insertions(+), 2 deletions(-) create mode 100644 frontend/public/icons/adapter-icons/MiniMax.png create mode 100644 unstract/sdk1/src/unstract/sdk1/adapters/llm1/minimax.py create mode 100644 unstract/sdk1/src/unstract/sdk1/adapters/llm1/static/minimax.json diff --git a/frontend/public/icons/adapter-icons/MiniMax.png b/frontend/public/icons/adapter-icons/MiniMax.png new file mode 100644 index 0000000000000000000000000000000000000000..acaabd3da98fb395b9bd89393344ac7045009f14 GIT binary patch literal 29953 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 dict[str, "Any"]: ) +class MiniMaxLLMParameters(OpenAICompatibleLLMParameters): + """OpenAI-compatible adapter for MiniMax models.""" + + # Required str so a directly-constructed instance stays valid. + api_base: str = _MINIMAX_API_BASE + + @staticmethod + def validate(adapter_metadata: dict[str, "Any"]) -> dict[str, "Any"]: + return _validate_branded_openai_compatible(adapter_metadata, _MINIMAX_API_BASE) + + class OpenRouterLLMParameters(BaseChatCompletionParameters): """Adapter for OpenRouter (openrouter.ai). diff --git a/unstract/sdk1/src/unstract/sdk1/adapters/llm1/__init__.py b/unstract/sdk1/src/unstract/sdk1/adapters/llm1/__init__.py index 2d935e218f..a3a03c7da3 100644 --- a/unstract/sdk1/src/unstract/sdk1/adapters/llm1/__init__.py +++ b/unstract/sdk1/src/unstract/sdk1/adapters/llm1/__init__.py @@ -6,6 +6,7 @@ from unstract.sdk1.adapters.llm1.anyscale import AnyscaleLLMAdapter from unstract.sdk1.adapters.llm1.azure_openai import AzureOpenAILLMAdapter from unstract.sdk1.adapters.llm1.bedrock import AWSBedrockLLMAdapter +from unstract.sdk1.adapters.llm1.minimax import MiniMaxLLMAdapter from unstract.sdk1.adapters.llm1.nvidia_build import NvidiaBuildLLMAdapter from unstract.sdk1.adapters.llm1.ollama import OllamaLLMAdapter from unstract.sdk1.adapters.llm1.openai import OpenAILLMAdapter @@ -23,6 +24,7 @@ "AnyscaleLLMAdapter", "AWSBedrockLLMAdapter", "AzureOpenAILLMAdapter", + "MiniMaxLLMAdapter", "NvidiaBuildLLMAdapter", "OllamaLLMAdapter", "OpenAILLMAdapter", diff --git a/unstract/sdk1/src/unstract/sdk1/adapters/llm1/minimax.py b/unstract/sdk1/src/unstract/sdk1/adapters/llm1/minimax.py new file mode 100644 index 0000000000..18f6ee3702 --- /dev/null +++ b/unstract/sdk1/src/unstract/sdk1/adapters/llm1/minimax.py @@ -0,0 +1,45 @@ +from typing import Any + +from unstract.sdk1.adapters.base1 import BaseAdapter, MiniMaxLLMParameters +from unstract.sdk1.adapters.enums import AdapterTypes + +DESCRIPTION = ( + "Adapter for MiniMax's OpenAI-compatible API. " + "Supply a model name and your MiniMax API key; the endpoint is preconfigured." +) + + +class MiniMaxLLMAdapter(MiniMaxLLMParameters, BaseAdapter): + @staticmethod + def get_id() -> str: + return "minimax|4f0e4241-2430-4921-81bf-8b2c6040d8d2" + + @staticmethod + def get_metadata() -> dict[str, Any]: + return { + "name": "MiniMax", + "version": "1.0.0", + "adapter": MiniMaxLLMAdapter, + "description": DESCRIPTION, + "is_active": True, + } + + @staticmethod + def get_name() -> str: + return "MiniMax" + + @staticmethod + def get_description() -> str: + return DESCRIPTION + + @staticmethod + def get_provider() -> str: + return "minimax" + + @staticmethod + def get_icon() -> str: + return "/icons/adapter-icons/MiniMax.png" + + @staticmethod + def get_adapter_type() -> AdapterTypes: + return AdapterTypes.LLM diff --git a/unstract/sdk1/src/unstract/sdk1/adapters/llm1/static/minimax.json b/unstract/sdk1/src/unstract/sdk1/adapters/llm1/static/minimax.json new file mode 100644 index 0000000000..b7769ca42e --- /dev/null +++ b/unstract/sdk1/src/unstract/sdk1/adapters/llm1/static/minimax.json @@ -0,0 +1,113 @@ +{ + "title": "MiniMax", + "type": "object", + "required": [ + "adapter_name", + "api_key", + "model" + ], + "properties": { + "adapter_name": { + "type": "string", + "title": "Name", + "default": "", + "description": "Provide a unique name for this adapter instance. Example: minimax-1" + }, + "api_key": { + "type": "string", + "title": "API Key", + "format": "password", + "description": "Your MiniMax API key from [platform.minimax.io](https://platform.minimax.io)." + }, + "model": { + "type": "string", + "title": "Model", + "default": "MiniMax-M3", + "description": "The MiniMax model name. Example: MiniMax-M3" + }, + "api_base": { + "type": "string", + "format": "url", + "title": "API Base", + "default": "https://api.minimax.io/v1", + "description": "MiniMax OpenAI-compatible endpoint. Pre-filled with the default; change only if MiniMax moves the base URL or you use a regional endpoint." + }, + "max_tokens": { + "type": "number", + "minimum": 0, + "multipleOf": 1, + "title": "Maximum Output Tokens", + "default": 4096, + "description": "Maximum number of output tokens to limit LLM replies. Leave it empty to use the provider default." + }, + "max_retries": { + "type": "number", + "minimum": 0, + "multipleOf": 1, + "title": "Max Retries", + "default": 5, + "description": "The maximum number of times to retry a request if it fails." + }, + "timeout": { + "type": "number", + "minimum": 0, + "multipleOf": 1, + "title": "Timeout", + "default": 900, + "description": "Timeout in seconds." + }, + "enable_reasoning": { + "type": "boolean", + "title": "Enable Reasoning", + "default": false, + "description": "Toggle on for reasoning models to route reasoning_effort via the OpenAI-compatible request body." + } + }, + "allOf": [ + { + "if": { + "properties": { + "enable_reasoning": { + "const": true + } + }, + "required": [ + "enable_reasoning" + ] + }, + "then": { + "properties": { + "reasoning_effort": { + "type": "string", + "enum": [ + "low", + "medium", + "high" + ], + "default": "medium", + "title": "Reasoning Effort", + "description": "Sets the reasoning strength when Enable Reasoning is on." + } + }, + "required": [ + "reasoning_effort" + ] + } + }, + { + "if": { + "properties": { + "enable_reasoning": { + "const": false + } + }, + "required": [ + "enable_reasoning" + ] + }, + "then": { + "properties": {} + } + } + ] +} diff --git a/unstract/sdk1/tests/test_branded_openai_adapters.py b/unstract/sdk1/tests/test_branded_openai_adapters.py index c876698847..eaebcf4f1c 100644 --- a/unstract/sdk1/tests/test_branded_openai_adapters.py +++ b/unstract/sdk1/tests/test_branded_openai_adapters.py @@ -1,7 +1,9 @@ import json import pytest + from unstract.sdk1.adapters.base1 import ( + MiniMaxLLMParameters, NvidiaBuildEmbeddingParameters, NvidiaBuildLLMParameters, OpenAICompatibleEmbeddingParameters, @@ -14,11 +16,13 @@ OpenAICompatibleEmbeddingAdapter, ) from unstract.sdk1.adapters.llm1 import adapters as llm_adapters +from unstract.sdk1.adapters.llm1.minimax import MiniMaxLLMAdapter from unstract.sdk1.adapters.llm1.nvidia_build import NvidiaBuildLLMAdapter from unstract.sdk1.adapters.llm1.openrouter import OpenRouterLLMAdapter _NVIDIA_BUILD_API_BASE = "https://integrate.api.nvidia.com/v1" _OPENROUTER_API_BASE = "https://openrouter.ai/api/v1" +_MINIMAX_API_BASE = "https://api.minimax.io/v1" # --- Branded LLM adapters ------------------------------------------------- @@ -26,7 +30,7 @@ @pytest.mark.parametrize( "adapter", - [NvidiaBuildLLMAdapter, OpenRouterLLMAdapter], + [MiniMaxLLMAdapter, NvidiaBuildLLMAdapter, OpenRouterLLMAdapter], ) def test_branded_llm_adapter_is_registered(adapter: type) -> None: adapter_id = adapter.get_id() @@ -41,6 +45,13 @@ def test_nvidia_llm_prefixes_model_via_custom_openai() -> None: assert validated["api_base"] == _NVIDIA_BUILD_API_BASE +def test_minimax_llm_prefixes_model_via_custom_openai() -> None: + validated = MiniMaxLLMParameters.validate({"model": "MiniMax-M3", "api_key": "k"}) + + assert validated["model"] == "custom_openai/MiniMax-M3" + assert validated["api_base"] == _MINIMAX_API_BASE + + def test_openrouter_llm_routes_via_native_openrouter_provider() -> None: from litellm import get_llm_provider @@ -106,6 +117,7 @@ def test_openrouter_reasoning_survives_revalidation() -> None: @pytest.mark.parametrize( ("params", "default_base"), [ + (MiniMaxLLMParameters, _MINIMAX_API_BASE), (NvidiaBuildLLMParameters, _NVIDIA_BUILD_API_BASE), (OpenRouterLLMParameters, _OPENROUTER_API_BASE), ], @@ -120,7 +132,7 @@ def test_branded_llm_blank_api_base_falls_back_to_default( @pytest.mark.parametrize( "params", - [NvidiaBuildLLMParameters, OpenRouterLLMParameters], + [MiniMaxLLMParameters, NvidiaBuildLLMParameters, OpenRouterLLMParameters], ) def test_branded_llm_honours_api_base_override(params: type) -> None: validated = params.validate( @@ -133,6 +145,7 @@ def test_branded_llm_honours_api_base_override(params: type) -> None: @pytest.mark.parametrize( ("adapter", "default_base"), [ + (MiniMaxLLMAdapter, _MINIMAX_API_BASE), (NvidiaBuildLLMAdapter, _NVIDIA_BUILD_API_BASE), (OpenRouterLLMAdapter, _OPENROUTER_API_BASE), ], From f9964490ad1141abe34f0972167cb96f81c1cb6c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 8 Jul 2026 10:15:20 +0000 Subject: [PATCH 2/2] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- unstract/sdk1/src/unstract/sdk1/adapters/base1.py | 1 - unstract/sdk1/tests/test_branded_openai_adapters.py | 1 - 2 files changed, 2 deletions(-) diff --git a/unstract/sdk1/src/unstract/sdk1/adapters/base1.py b/unstract/sdk1/src/unstract/sdk1/adapters/base1.py index 77cd8609f5..cdb1929e15 100644 --- a/unstract/sdk1/src/unstract/sdk1/adapters/base1.py +++ b/unstract/sdk1/src/unstract/sdk1/adapters/base1.py @@ -12,7 +12,6 @@ from typing import Any from pydantic import BaseModel, Field, model_validator - from unstract.sdk1.adapters.constants import Common from unstract.sdk1.adapters.enums import AdapterTypes diff --git a/unstract/sdk1/tests/test_branded_openai_adapters.py b/unstract/sdk1/tests/test_branded_openai_adapters.py index eaebcf4f1c..b025bfc209 100644 --- a/unstract/sdk1/tests/test_branded_openai_adapters.py +++ b/unstract/sdk1/tests/test_branded_openai_adapters.py @@ -1,7 +1,6 @@ import json import pytest - from unstract.sdk1.adapters.base1 import ( MiniMaxLLMParameters, NvidiaBuildEmbeddingParameters,