init: Search Hub - 统一多搜索引擎聚合服务

This commit is contained in:
2026-05-09 18:46:05 +08:00
commit 81d726179c
27 changed files with 3179 additions and 0 deletions

82
hub/config_manager.py Normal file
View File

@@ -0,0 +1,82 @@
"""Search Hub 配置管理器 — 读写本地配置文件"""
import os
import yaml
CONFIG_PATH = '/root/agentspace/projects/search-hub/config.yaml'
def load_hub_config() -> dict:
"""加载本地配置"""
if os.path.exists(CONFIG_PATH):
with open(CONFIG_PATH, 'r') as f:
return yaml.safe_load(f) or {}
return {}
def save_hub_config(cfg: dict):
"""保存配置到文件"""
os.makedirs(os.path.dirname(CONFIG_PATH), exist_ok=True)
with open(CONFIG_PATH, 'w') as f:
yaml.dump(cfg, f, default_flow_style=False, allow_unicode=True)
def get_source_config(name: str) -> dict:
"""获取单个源的配置"""
cfg = load_hub_config()
sources = cfg.get('sources', {})
return sources.get(name, {})
def update_source_config(name: str, updates: dict):
"""更新单个源的配置并保存"""
cfg = load_hub_config()
if 'sources' not in cfg:
cfg['sources'] = {}
if name not in cfg['sources']:
cfg['sources'][name] = {}
cfg['sources'][name].update(updates)
save_hub_config(cfg)
def get_source_schema(name: str) -> list:
"""返回某个源的可配置字段定义"""
schemas = {
'tavily': [
{'key': 'api_key', 'label': 'API Key', 'type': 'password', 'required': True},
{'key': 'base_url', 'label': 'API 地址', 'type': 'text', 'required': False,
'default': 'https://api.tavily.com'},
],
'ai': [
{'key': 'api_key', 'label': 'API Key', 'type': 'password', 'required': True},
{'key': 'base_url', 'label': 'API 地址', 'type': 'text', 'required': False,
'default': 'https://opencode.ai/zen/go/v1'},
{'key': 'model', 'label': '模型名称', 'type': 'text', 'required': False,
'default': 'deepseek-v4-flash'},
],
'baidu': [
{'key': 'api_key', 'label': 'API Key', 'type': 'password', 'required': True},
{'key': 'intelligent_url', 'label': '智能检索接口', 'type': 'text', 'required': False,
'default': 'https://qianfan.baidubce.com/v2/ai_search/chat/completions'},
{'key': 'web_search_url', 'label': '网页搜索接口', 'type': 'text', 'required': False,
'default': 'https://qianfan.baidubce.com/v2/ai_search/web_search'},
{'key': 'vdb_access_key', 'label': 'VDB Access Key', 'type': 'text', 'required': False},
{'key': 'vdb_secret_key', 'label': 'VDB Secret Key', 'type': 'password', 'required': False},
],
'searxng': [
{'key': 'base_url', 'label': 'SearXNG 地址', 'type': 'text', 'required': False,
'default': 'http://localhost:8888'},
],
'baidu-intelligent': [], # 共享 baidu 配置,无需单独字段
'duckduckgo': [],
}
return schemas.get(name, [])
def mask_key(key: str) -> str:
"""脱敏显示密钥"""
if not key:
return ''
if len(key) <= 8:
return key[:2] + '****'
return key[:6] + '****' + key[-4:]