deer-flow/scripts/wizard/providers.py

529 lines
17 KiB
Python

"""LLM and search provider definitions for the Setup Wizard."""
from __future__ import annotations
from dataclasses import dataclass, field
@dataclass
class LLMProvider:
name: str
display_name: str
description: str
use: str
models: list[str]
default_model: str
env_var: str | None
package: str | None
# Optional: some providers use a different field name for the API key in YAML
api_key_field: str = "api_key"
# Extra config fields beyond the common ones (merged into YAML)
extra_config: dict = field(default_factory=dict)
auth_hint: str | None = None
base_url_prompt: str | None = None
model_prompt: str | None = None
@dataclass
class WebProvider:
name: str
display_name: str
description: str
use: str
env_var: str | None # None = no API key required
tool_name: str
extra_config: dict = field(default_factory=dict)
@dataclass
class SearchProvider:
name: str
display_name: str
description: str
use: str
env_var: str | None # None = no API key required
tool_name: str = "web_search"
extra_config: dict = field(default_factory=dict)
OPENAI_COMPAT_THINKING_CONFIG = {
"supports_thinking": True,
"when_thinking_enabled": {
"extra_body": {
"thinking": {
"type": "enabled",
}
}
},
"when_thinking_disabled": {
"extra_body": {
"thinking": {
"type": "disabled",
}
}
},
}
ANTHROPIC_THINKING_CONFIG = {
"supports_thinking": True,
"when_thinking_enabled": {
"thinking": {
"type": "enabled",
"budget_tokens": 4096,
}
},
"when_thinking_disabled": {
"thinking": {
"type": "disabled",
}
},
}
LLM_PROVIDERS: list[LLMProvider] = [
LLMProvider(
name="volcengine",
display_name="Volcengine Doubao",
description="Doubao Seed with thinking support",
use="deerflow.models.patched_deepseek:PatchedChatDeepSeek",
models=["doubao-seed-1-8-251228"],
default_model="doubao-seed-1-8-251228",
env_var="VOLCENGINE_API_KEY",
package="langchain-deepseek",
extra_config={
"api_base": "https://ark.cn-beijing.volces.com/api/v3",
"timeout": 600.0,
"max_retries": 2,
"supports_vision": True,
"supports_reasoning_effort": True,
**OPENAI_COMPAT_THINKING_CONFIG,
},
),
LLMProvider(
name="openai",
display_name="OpenAI",
description="GPT-5, GPT-4.1, GPT-4o",
use="langchain_openai:ChatOpenAI",
models=["gpt-5", "gpt-5-mini", "gpt-4.1", "gpt-4o"],
default_model="gpt-5",
env_var="OPENAI_API_KEY",
package="langchain-openai",
extra_config={
"request_timeout": 600.0,
"max_retries": 2,
"max_tokens": 4096,
"temperature": 0.7,
"supports_vision": True,
},
),
LLMProvider(
name="openai_responses",
display_name="OpenAI Responses API",
description="GPT-5 via /v1/responses",
use="langchain_openai:ChatOpenAI",
models=["gpt-5", "gpt-5-mini"],
default_model="gpt-5",
env_var="OPENAI_API_KEY",
package="langchain-openai",
extra_config={
"request_timeout": 600.0,
"max_retries": 2,
"use_responses_api": True,
"output_version": "responses/v1",
"supports_vision": True,
},
),
LLMProvider(
name="anthropic",
display_name="Anthropic",
description="Claude Sonnet 4 with extended thinking",
use="langchain_anthropic:ChatAnthropic",
models=["claude-sonnet-4-20250514", "claude-opus-4-5", "claude-sonnet-4-5"],
default_model="claude-sonnet-4-20250514",
env_var="ANTHROPIC_API_KEY",
package="langchain-anthropic",
extra_config={
"default_request_timeout": 600.0,
"max_retries": 2,
"max_tokens": 16000,
"supports_vision": True,
**ANTHROPIC_THINKING_CONFIG,
},
),
LLMProvider(
name="deepseek",
display_name="DeepSeek",
description="DeepSeek Reasoner with thinking support",
use="deerflow.models.patched_deepseek:PatchedChatDeepSeek",
models=["deepseek-reasoner", "deepseek-chat"],
default_model="deepseek-reasoner",
env_var="DEEPSEEK_API_KEY",
package="langchain-deepseek",
extra_config={
"timeout": 600.0,
"max_retries": 2,
"max_tokens": 8192,
"supports_vision": False,
**OPENAI_COMPAT_THINKING_CONFIG,
},
),
LLMProvider(
name="google",
display_name="Google Gemini",
description="Native Gemini SDK, no thinking support",
use="langchain_google_genai:ChatGoogleGenerativeAI",
models=["gemini-2.5-pro", "gemini-2.0-flash"],
default_model="gemini-2.5-pro",
env_var="GEMINI_API_KEY",
package="langchain-google-genai",
api_key_field="gemini_api_key",
extra_config={
"timeout": 600.0,
"max_retries": 2,
"max_tokens": 8192,
"supports_vision": True,
},
),
LLMProvider(
name="gemini_openai_gateway",
display_name="Gemini OpenAI-compatible",
description="Gemini thinking via an OpenAI-compatible gateway",
use="deerflow.models.patched_openai:PatchedChatOpenAI",
models=["google/gemini-2.5-pro-preview"],
default_model="google/gemini-2.5-pro-preview",
env_var="GEMINI_API_KEY",
package="langchain-openai",
extra_config={
"request_timeout": 600.0,
"max_retries": 2,
"max_tokens": 16384,
"supports_vision": True,
**OPENAI_COMPAT_THINKING_CONFIG,
},
base_url_prompt="Gateway base URL (e.g. https://your-gateway.example/v1)",
),
LLMProvider(
name="ollama_qwen",
display_name="Ollama Qwen3",
description="Native local Ollama provider with thinking support",
use="langchain_ollama:ChatOllama",
models=["qwen3:32b"],
default_model="qwen3:32b",
env_var=None,
package="langchain-ollama",
extra_config={
"base_url": "http://localhost:11434",
"num_predict": 8192,
"temperature": 0.7,
"reasoning": True,
"supports_thinking": True,
"supports_vision": False,
},
auth_hint="No API key is required. Ensure Ollama is running and the model is pulled.",
),
LLMProvider(
name="ollama_gemma",
display_name="Ollama Gemma",
description="Native local Ollama provider with vision support",
use="langchain_ollama:ChatOllama",
models=["gemma4:27b"],
default_model="gemma4:27b",
env_var=None,
package="langchain-ollama",
extra_config={
"base_url": "http://localhost:11434",
"num_predict": 8192,
"temperature": 0.7,
"reasoning": True,
"supports_thinking": True,
"supports_vision": True,
},
auth_hint="No API key is required. Ensure Ollama is running and the model is pulled.",
),
LLMProvider(
name="mimo",
display_name="Xiaomi MiMo",
description="MiMo thinking models with reasoning replay",
use="deerflow.models.patched_mimo:PatchedChatMiMo",
models=["mimo-v2.5-pro", "mimo-v2.5", "mimo-v2-pro", "mimo-v2-omni", "mimo-v2-flash"],
default_model="mimo-v2.5-pro",
env_var="MIMO_API_KEY",
package="langchain-openai",
extra_config={
"base_url": "https://api.xiaomimimo.com/v1",
"request_timeout": 600.0,
"max_retries": 2,
"max_tokens": 8192,
"supports_vision": False,
**OPENAI_COMPAT_THINKING_CONFIG,
},
),
LLMProvider(
name="kimi",
display_name="Moonshot Kimi",
description="Kimi K2.5 with thinking support",
use="deerflow.models.patched_deepseek:PatchedChatDeepSeek",
models=["kimi-k2.5"],
default_model="kimi-k2.5",
env_var="MOONSHOT_API_KEY",
package="langchain-deepseek",
extra_config={
"api_base": "https://api.moonshot.cn/v1",
"timeout": 600.0,
"max_retries": 2,
"max_tokens": 32768,
"supports_vision": True,
**OPENAI_COMPAT_THINKING_CONFIG,
},
),
LLMProvider(
name="novita",
display_name="Novita AI",
description="DeepSeek V3.2 via OpenAI-compatible API",
use="langchain_openai:ChatOpenAI",
models=["deepseek/deepseek-v3.2"],
default_model="deepseek/deepseek-v3.2",
env_var="NOVITA_API_KEY",
package="langchain-openai",
extra_config={
"base_url": "https://api.novita.ai/openai",
"request_timeout": 600.0,
"max_retries": 2,
"max_tokens": 4096,
"temperature": 0.7,
"supports_vision": True,
**OPENAI_COMPAT_THINKING_CONFIG,
},
),
LLMProvider(
name="minimax",
display_name="MiniMax",
description="International OpenAI-compatible endpoint",
use="langchain_openai:ChatOpenAI",
models=["MiniMax-M3", "MiniMax-M2.7", "MiniMax-M2.7-highspeed"],
default_model="MiniMax-M3",
env_var="MINIMAX_API_KEY",
package="langchain-openai",
extra_config={
"base_url": "https://api.minimax.io/v1",
"request_timeout": 600.0,
"max_retries": 2,
"max_tokens": 4096,
"temperature": 1.0,
"supports_vision": True,
"supports_thinking": True,
},
),
LLMProvider(
name="minimax_cn",
display_name="MiniMax CN",
description="China OpenAI-compatible endpoint",
use="langchain_openai:ChatOpenAI",
models=["MiniMax-M3", "MiniMax-M2.7", "MiniMax-M2.7-highspeed"],
default_model="MiniMax-M3",
env_var="MINIMAX_API_KEY",
package="langchain-openai",
extra_config={
"base_url": "https://api.minimaxi.com/v1",
"request_timeout": 600.0,
"max_retries": 2,
"max_tokens": 4096,
"temperature": 1.0,
"supports_vision": True,
"supports_thinking": True,
},
),
LLMProvider(
name="openrouter",
display_name="OpenRouter",
description="OpenAI-compatible gateway with broad model catalog",
use="langchain_openai:ChatOpenAI",
models=["google/gemini-2.5-flash-preview", "openai/gpt-5-mini", "anthropic/claude-sonnet-4"],
default_model="google/gemini-2.5-flash-preview",
env_var="OPENROUTER_API_KEY",
package="langchain-openai",
extra_config={
"base_url": "https://openrouter.ai/api/v1",
"request_timeout": 600.0,
"max_retries": 2,
"max_tokens": 8192,
"temperature": 0.7,
},
),
LLMProvider(
name="vllm",
display_name="vLLM",
description="Self-hosted OpenAI-compatible serving",
use="deerflow.models.vllm_provider:VllmChatModel",
models=["Qwen/Qwen3-32B", "Qwen/Qwen2.5-Coder-32B-Instruct"],
default_model="Qwen/Qwen3-32B",
env_var="VLLM_API_KEY",
package=None,
extra_config={
"base_url": "http://localhost:8000/v1",
"request_timeout": 600.0,
"max_retries": 2,
"max_tokens": 8192,
"supports_thinking": True,
"supports_vision": False,
"when_thinking_enabled": {
"extra_body": {
"chat_template_kwargs": {
"enable_thinking": True,
}
}
},
"when_thinking_disabled": {
"extra_body": {
"chat_template_kwargs": {
"enable_thinking": False,
}
}
},
},
),
LLMProvider(
name="mindie",
display_name="MindIE",
description="Qwen3-Coder on MindIE Engine",
use="deerflow.models.mindie_provider:MindIEChatModel",
models=["Qwen3-Coder-480B-A35B-Instruct-Client"],
default_model="Qwen3-Coder-480B-A35B-Instruct-Client",
env_var="OPENAI_API_KEY",
package=None,
extra_config={
"base_url": "http://localhost:8989/v1",
"temperature": 0,
"max_retries": 1,
"supports_thinking": False,
"supports_vision": False,
"supports_reasoning_effort": False,
"read_timeout": 900.0,
"connect_timeout": 30.0,
"write_timeout": 60.0,
"pool_timeout": 30.0,
},
),
LLMProvider(
name="codex",
display_name="Codex CLI",
description="Uses Codex CLI local auth (~/.codex/auth.json)",
use="deerflow.models.openai_codex_provider:CodexChatModel",
models=["gpt-5.4", "gpt-5-mini"],
default_model="gpt-5.4",
env_var=None,
package=None,
api_key_field="api_key",
extra_config={"supports_thinking": True, "supports_reasoning_effort": True},
auth_hint="Uses existing Codex CLI auth from ~/.codex/auth.json",
),
LLMProvider(
name="claude_code",
display_name="Claude Code OAuth",
description="Uses Claude Code local OAuth credentials",
use="deerflow.models.claude_provider:ClaudeChatModel",
models=["claude-sonnet-4-6", "claude-opus-4-1"],
default_model="claude-sonnet-4-6",
env_var=None,
package=None,
extra_config={"max_tokens": 4096, "supports_thinking": True},
auth_hint="Uses Claude Code OAuth credentials from your local machine",
),
LLMProvider(
name="other",
display_name="Other OpenAI-compatible",
description="Custom gateway with base_url and model name",
use="langchain_openai:ChatOpenAI",
models=["gpt-4o"],
default_model="gpt-4o",
env_var="OPENAI_API_KEY",
package="langchain-openai",
base_url_prompt="Base URL (e.g. https://api.openai.com/v1)",
model_prompt="Model name",
),
]
SEARCH_PROVIDERS: list[SearchProvider] = [
SearchProvider(
name="ddg",
display_name="DuckDuckGo (free, no key needed)",
description="No API key required",
use="deerflow.community.ddg_search.tools:web_search_tool",
env_var=None,
extra_config={"max_results": 5},
),
SearchProvider(
name="tavily",
display_name="Tavily",
description="Recommended, free tier available",
use="deerflow.community.tavily.tools:web_search_tool",
env_var="TAVILY_API_KEY",
extra_config={"max_results": 5},
),
SearchProvider(
name="infoquest",
display_name="InfoQuest",
description="Higher quality vertical search, API key required",
use="deerflow.community.infoquest.tools:web_search_tool",
env_var="INFOQUEST_API_KEY",
extra_config={"search_time_range": 10},
),
SearchProvider(
name="exa",
display_name="Exa",
description="Neural + keyword web search, API key required",
use="deerflow.community.exa.tools:web_search_tool",
env_var="EXA_API_KEY",
extra_config={
"max_results": 5,
"search_type": "auto",
"contents_max_characters": 1000,
},
),
SearchProvider(
name="firecrawl",
display_name="Firecrawl",
description="Search + crawl via Firecrawl API",
use="deerflow.community.firecrawl.tools:web_search_tool",
env_var="FIRECRAWL_API_KEY",
extra_config={"max_results": 5},
),
]
WEB_FETCH_PROVIDERS: list[WebProvider] = [
WebProvider(
name="jina_ai",
display_name="Jina AI Reader",
description="Good default reader, no API key required",
use="deerflow.community.jina_ai.tools:web_fetch_tool",
env_var=None,
tool_name="web_fetch",
extra_config={"timeout": 10},
),
WebProvider(
name="exa",
display_name="Exa",
description="API key required",
use="deerflow.community.exa.tools:web_fetch_tool",
env_var="EXA_API_KEY",
tool_name="web_fetch",
),
WebProvider(
name="infoquest",
display_name="InfoQuest",
description="API key required",
use="deerflow.community.infoquest.tools:web_fetch_tool",
env_var="INFOQUEST_API_KEY",
tool_name="web_fetch",
extra_config={"timeout": 10, "fetch_time": 10, "navigation_timeout": 30},
),
WebProvider(
name="firecrawl",
display_name="Firecrawl",
description="Search-grade crawl with markdown output, API key required",
use="deerflow.community.firecrawl.tools:web_fetch_tool",
env_var="FIRECRAWL_API_KEY",
tool_name="web_fetch",
),
]