mirror of
https://github.com/AstrBotDevs/AstrBot.git
synced 2026-09-24 16:39:52 +08:00
feat: 允许添加多个 tavily API Key 进行轮询 (#2725)
* feat: 允许添加多个tavily API Key进行轮询 * perf: 并发安全的从列表中获取并轮换Tavily API密钥 * fix: 自动迁移旧版 websearch_tavily_key 为列表格式并保存
This commit is contained in:
@@ -56,7 +56,7 @@ DEFAULT_CONFIG = {
|
||||
"wake_prefix": "",
|
||||
"web_search": False,
|
||||
"websearch_provider": "default",
|
||||
"websearch_tavily_key": "",
|
||||
"websearch_tavily_key": [],
|
||||
"web_search_link": False,
|
||||
"display_reasoning_text": False,
|
||||
"identifier": False,
|
||||
@@ -1938,7 +1938,9 @@ CONFIG_METADATA_3 = {
|
||||
},
|
||||
"provider_settings.websearch_tavily_key": {
|
||||
"description": "Tavily API Key",
|
||||
"type": "string",
|
||||
"type": "list",
|
||||
"items": {"type": "string"},
|
||||
"hint": "可添加多个 Key 进行轮询。",
|
||||
"condition": {
|
||||
"provider_settings.websearch_provider": "tavily",
|
||||
},
|
||||
|
||||
@@ -26,6 +26,21 @@ class Main(star.Star):
|
||||
|
||||
def __init__(self, context: star.Context) -> None:
|
||||
self.context = context
|
||||
self.tavily_key_index = 0
|
||||
self.tavily_key_lock = asyncio.Lock()
|
||||
|
||||
# 将 str 类型的 key 迁移至 list[str],并保存
|
||||
cfg = self.context.get_config()
|
||||
provider_settings = cfg.get("provider_settings")
|
||||
if provider_settings:
|
||||
tavily_key = provider_settings.get("websearch_tavily_key")
|
||||
if isinstance(tavily_key, str):
|
||||
logger.info("检测到旧版 websearch_tavily_key (字符串格式),自动迁移为列表格式并保存。")
|
||||
if tavily_key:
|
||||
provider_settings["websearch_tavily_key"] = [tavily_key]
|
||||
else:
|
||||
provider_settings["websearch_tavily_key"] = []
|
||||
cfg.save_config()
|
||||
|
||||
self.bing_search = Bing()
|
||||
self.sogo_search = Sogo()
|
||||
@@ -94,13 +109,22 @@ class Main(star.Star):
|
||||
|
||||
return results
|
||||
|
||||
async def _get_tavily_key(self, cfg: AstrBotConfig) -> str:
|
||||
"""并发安全的从列表中获取并轮换Tavily API密钥。"""
|
||||
tavily_keys = cfg.get("provider_settings", {}).get("websearch_tavily_key", [])
|
||||
if not tavily_keys:
|
||||
raise ValueError("错误:Tavily API密钥未在AstrBot中配置。")
|
||||
|
||||
async with self.tavily_key_lock:
|
||||
key = tavily_keys[self.tavily_key_index]
|
||||
self.tavily_key_index = (self.tavily_key_index + 1) % len(tavily_keys)
|
||||
return key
|
||||
|
||||
async def _web_search_tavily(
|
||||
self, cfg: AstrBotConfig, payload: dict
|
||||
) -> list[SearchResult]:
|
||||
"""使用 Tavily 搜索引擎进行搜索"""
|
||||
tavily_key = cfg.get("provider_settings", {}).get("websearch_tavily_key", None)
|
||||
if not tavily_key:
|
||||
raise ValueError("Error: Tavily API key is not configured in AstrBot.")
|
||||
tavily_key = await self._get_tavily_key(cfg)
|
||||
url = "https://api.tavily.com/search"
|
||||
header = {
|
||||
"Authorization": f"Bearer {tavily_key}",
|
||||
@@ -128,9 +152,7 @@ class Main(star.Star):
|
||||
|
||||
async def _extract_tavily(self, cfg: AstrBotConfig, payload: dict) -> list[dict]:
|
||||
"""使用 Tavily 提取网页内容"""
|
||||
tavily_key = cfg.get("provider_settings", {}).get("websearch_tavily_key", None)
|
||||
if not tavily_key:
|
||||
raise ValueError("Error: Tavily API key is not configured in AstrBot.")
|
||||
tavily_key = await self._get_tavily_key(cfg)
|
||||
url = "https://api.tavily.com/extract"
|
||||
header = {
|
||||
"Authorization": f"Bearer {tavily_key}",
|
||||
@@ -235,8 +257,7 @@ class Main(star.Star):
|
||||
logger.info(f"web_searcher - search_from_tavily: {query}")
|
||||
cfg = self.context.get_config(umo=event.unified_msg_origin)
|
||||
websearch_link = cfg["provider_settings"].get("web_search_link", False)
|
||||
tavily_key = cfg.get("provider_settings", {}).get("websearch_tavily_key", None)
|
||||
if not tavily_key:
|
||||
if not cfg.get("provider_settings", {}).get("websearch_tavily_key", []):
|
||||
raise ValueError("Error: Tavily API key is not configured in AstrBot.")
|
||||
|
||||
# build payload
|
||||
@@ -288,8 +309,7 @@ class Main(star.Star):
|
||||
extract_depth(string): Optional. The depth of the extraction, must be one of 'basic', 'advanced'. Default is "basic".
|
||||
"""
|
||||
cfg = self.context.get_config(umo=event.unified_msg_origin)
|
||||
tavily_key = cfg.get("provider_settings", {}).get("websearch_tavily_key", None)
|
||||
if not tavily_key:
|
||||
if not cfg.get("provider_settings", {}).get("websearch_tavily_key", []):
|
||||
raise ValueError("Error: Tavily API key is not configured in AstrBot.")
|
||||
|
||||
if not url:
|
||||
|
||||
Reference in New Issue
Block a user