Files
Zone-Roam-ComfyUI-Live-Search/api_loader.py
T

254 lines
7.9 KiB
Python

"""
LiveSearch API Loader Node
Handles LLM API configuration separately from the main search logic
"""
import os
from .config_manager import ConfigManager
config_manager = ConfigManager()
# Expanded model configurations
MODEL_CONFIGS = {
"OpenAI": {
"base_url": "https://api.openai.com/v1",
"models": [
"gpt-5.1",
"gpt-5",
"gpt-5-mini",
"gpt-5-nano",
"gpt-5-pro",
"gpt-4.1",
"gpt-4.1-mini",
"gpt-4.1-nano",
"gpt-4o",
"gpt-4o-mini",
"gpt-4-turbo",
"gpt-4",
"gpt-3.5-turbo",
"o3",
"o3-pro",
"o3-mini",
"o3-deep-research",
"o4-mini-deep-research",
"o1",
"o1-pro"
]
},
"DeepSeek (Official)": {
"base_url": "https://api.deepseek.com",
"models": [
"deepseek-chat",
"deepseek-reasoner",
"deepseek-v3"
]
},
"DeepSeek (Aliyun)": {
"base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1",
"models": [
"deepseek-v3",
"deepseek-v2.5",
"deepseek-chat"
]
},
"Gemini (OpenAI-Format)": {
"base_url": "https://generativelanguage.googleapis.com/v1beta/openai",
"models": [
"gemini-3-pro",
"gemini-2.5-pro",
"gemini-2.5-flash",
"gemini-2.5-flash-lite",
"gemini-2.0-flash",
"gemini-2.0-flash-lite",
"gemini-1.5-pro",
"gemini-1.5-flash",
"gemini-1.5-flash-8b"
]
},
"Anthropic (Claude)": {
"base_url": "https://api.anthropic.com/v1",
"models": [
"claude-sonnet-4-5-20250929",
"claude-sonnet-4-5",
"claude-haiku-4-5-20251001",
"claude-haiku-4-5",
"claude-opus-4-1-20250805",
"claude-opus-4-1"
]
},
"Grok": {
"base_url": "https://api.x.ai/v1",
"models": [
"grok-2-1212",
"grok-2-vision-1212",
"grok-2",
"grok-beta"
]
},
"Volcengine (Doubao)": {
"base_url": "https://ark.cn-beijing.volces.com/api/v3",
"models": [
# 豆包主力模型 (Model ID)
"doubao-seed-1-6-251015", # doubao-seed-1.6 (最新)
"doubao-seed-1-6-250615", # doubao-seed-1.6 (稳定)
"doubao-seed-1-6-lite-251015", # doubao-seed-1.6-lite
"doubao-seed-1-6-flash-250828",# doubao-seed-1.6-flash
"doubao-seed-1-6-thinking-250715", # doubao-seed-1.6-thinking
"doubao-seed-code-preview-251028", # doubao-seed-code
"doubao-seed-1-6-vision-250815", # doubao-seed-1.6-vision
# DeepSeek (火山引擎托管)
"deepseek-v3-1-terminus",
"deepseek-v3-1-250821",
# 第三方兼容 (如需自定义)
"custom-endpoint-id"
]
},
"Qwen (Aliyun)": {
"base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1",
"models": [
"qwen3-max",
"qwen3-max-preview",
"qwen-plus",
"qwen-plus-latest",
"qwen-flash",
"qwen-max",
"qwen-turbo"
]
},
"SiliconFlow (硅基流动)": {
"base_url": "https://api.siliconflow.cn/v1",
"models": [
# DeepSeek 系列
"deepseek-chat",
"deepseek-reasoner",
"deepseek-v3",
# Qwen 系列(通用对话)
"Qwen/Qwen2.5-72B-Instruct",
"Qwen/Qwen2.5-32B-Instruct",
"Qwen/Qwen2.5-14B-Instruct",
"Qwen/Qwen2.5-7B-Instruct",
"Qwen/Qwen2.5-1.5B-Instruct",
# Qwen 代码模型
"Qwen/Qwen2.5-Coder-32B-Instruct",
"Qwen/Qwen2.5-Coder-7B-Instruct",
# Qwen 多模态
"Qwen/QVQ-72B-Preview",
"Qwen/Qwen-VL-72B-Instruct",
# Llama 系列
"meta-llama/Llama-3.1-70B-Instruct",
"meta-llama/Llama-3.1-8B-Instruct",
"meta-llama/Llama-3-70B-Instruct",
"meta-llama/Llama-3-8B-Instruct",
# Yi 系列
"01-ai/Yi-1.5-34B-Chat",
"01-ai/Yi-1.5-9B-Chat",
"01-ai/Yi-1.5-6B-Chat",
# GLM 系列
"THUDM/glm-4-9b-chat",
"THUDM/glm-4-9b-chat-1m",
# Mistral 系列
"mistralai/Mistral-7B-Instruct-v0.3",
# InternLM 系列
"internlm/internlm2_5-20b-chat",
"internlm/internlm2_5-7b-chat"
]
},
"Ollama (Local)": {
"base_url": "http://127.0.0.1:11434/v1",
"models": [
"llama4",
"llama3.3",
"llama3.2",
"qwen3",
"qwen2.5",
"deepseek-r1",
"deepseek-v3",
"phi4"
]
},
"Custom": {
"base_url": "",
"models": ["custom-model"]
}
}
class LiveSearch_API_Loader:
"""
API Configuration Loader Node
Separated from main search logic for better organization
"""
def __init__(self):
pass
@classmethod
def INPUT_TYPES(s):
# Get all providers
providers = list(MODEL_CONFIGS.keys())
# Get all unique models
all_models = []
for config in MODEL_CONFIGS.values():
all_models.extend(config["models"])
unique_models = list(dict.fromkeys(all_models)) # Preserve order, remove duplicates
return {
"required": {
"provider": (providers, {"default": "DeepSeek (Official)"}),
"model": (unique_models, {"default": "deepseek-chat"}),
},
"optional": {
"api_key": ("STRING", {"default": "", "placeholder": "Leave empty to use .env or config file"}),
"base_url": ("STRING", {"default": "", "placeholder": "Leave empty to use default"}),
"temperature": ("FLOAT", {"default": 0.7, "min": 0.0, "max": 2.0, "step": 0.1}),
"max_tokens": ("INT", {"default": 2048, "min": 1, "max": 128000, "step": 1}),
"timeout": ("INT", {"default": 120, "min": 10, "max": 600, "step": 10}),
}
}
RETURN_TYPES = ("LLM_CONFIG",)
RETURN_NAMES = ("llm_config",)
FUNCTION = "load_api"
CATEGORY = "LiveSearch"
def load_api(self, provider, model, api_key="", base_url="", temperature=0.7, max_tokens=2048, timeout=120):
"""
Load and validate API configuration
Returns a config dict that can be passed to other nodes
"""
# Resolve API key with priority: input > env > config file
resolved_api_key = api_key.strip() if api_key else ""
if not resolved_api_key:
resolved_api_key = config_manager.get_api_key(provider, "")
# Resolve base URL
resolved_base_url = base_url.strip() if base_url else MODEL_CONFIGS.get(provider, {}).get("base_url", "")
# Special handling for Aliyun providers
if provider == "DeepSeek (Aliyun)" and model == "deepseek-chat":
model = "deepseek-v3"
# Build configuration dict
llm_config = {
"provider": provider,
"model": model,
"api_key": resolved_api_key,
"base_url": resolved_base_url,
"temperature": temperature,
"max_tokens": max_tokens,
"timeout": timeout
}
print(f"[LiveSearch API Loader] Configured: {provider} / {model}")
return (llm_config,)
NODE_CLASS_MAPPINGS = {
"LiveSearch_API_Loader": LiveSearch_API_Loader
}
NODE_DISPLAY_NAME_MAPPINGS = {
"LiveSearch_API_Loader": "🔑 Live Search API Loader"
}