The multimodal agent has been basically completed.

This commit is contained in:
戒酒的李白
2025-08-22 23:39:11 +08:00
parent 062f66cb2e
commit 431cf6a12c
5 changed files with 99 additions and 144 deletions
+51 -85
View File
@@ -19,7 +19,7 @@ from .nodes import (
ReportFormattingNode
)
from .state import State
from .tools import TavilyNewsAgency, TavilyResponse
from .tools import BochaMultimodalSearch, BochaResponse
from .utils import Config, load_config, format_search_results_for_prompt
@@ -40,7 +40,7 @@ class DeepSearchAgent:
self.llm_client = self._initialize_llm()
# 初始化搜索工具集
self.search_agency = TavilyNewsAgency(api_key=self.config.tavily_api_key)
self.search_agency = BochaMultimodalSearch(api_key=self.config.bocha_api_key)
# 初始化节点
self._initialize_nodes()
@@ -53,7 +53,7 @@ class DeepSearchAgent:
print(f"Deep Search Agent 已初始化")
print(f"使用LLM: {self.llm_client.get_model_info()}")
print(f"搜索工具集: TavilyNewsAgency (支持6种搜索工具)")
print(f"搜索工具集: BochaMultimodalSearch (支持5种多模态搜索工具)")
def _initialize_llm(self) -> BaseLLM:
"""初始化LLM客户端"""
@@ -103,46 +103,40 @@ class DeepSearchAgent:
except ValueError:
return False
def execute_search_tool(self, tool_name: str, query: str, **kwargs) -> TavilyResponse:
def execute_search_tool(self, tool_name: str, query: str, **kwargs) -> BochaResponse:
"""
执行指定的搜索工具
Args:
tool_name: 工具名称,可选值:
- "basic_search_news": 基础新闻搜索(快速、通用
- "deep_search_news": 深度新闻分析
- "search_news_last_24_hours": 24小时内最新新闻
- "search_news_last_week": 本周新闻
- "search_images_for_news": 新闻图片搜索
- "search_news_by_date": 按日期范围搜索新闻
- "comprehensive_search": 全面综合搜索(默认
- "web_search_only": 纯网页搜索
- "search_for_structured_data": 结构化数据查询
- "search_last_24_hours": 24小时内最新信息
- "search_last_week": 本周信息
query: 搜索查询
**kwargs: 额外参数(如start_date, end_date, max_results
**kwargs: 额外参数(如max_results
Returns:
TavilyResponse对象
BochaResponse对象
"""
print(f" → 执行搜索工具: {tool_name}")
if tool_name == "basic_search_news":
max_results = kwargs.get("max_results", 7)
return self.search_agency.basic_search_news(query, max_results)
elif tool_name == "deep_search_news":
return self.search_agency.deep_search_news(query)
elif tool_name == "search_news_last_24_hours":
return self.search_agency.search_news_last_24_hours(query)
elif tool_name == "search_news_last_week":
return self.search_agency.search_news_last_week(query)
elif tool_name == "search_images_for_news":
return self.search_agency.search_images_for_news(query)
elif tool_name == "search_news_by_date":
start_date = kwargs.get("start_date")
end_date = kwargs.get("end_date")
if not start_date or not end_date:
raise ValueError("search_news_by_date工具需要start_date和end_date参数")
return self.search_agency.search_news_by_date(query, start_date, end_date)
if tool_name == "comprehensive_search":
max_results = kwargs.get("max_results", 10)
return self.search_agency.comprehensive_search(query, max_results)
elif tool_name == "web_search_only":
max_results = kwargs.get("max_results", 15)
return self.search_agency.web_search_only(query, max_results)
elif tool_name == "search_for_structured_data":
return self.search_agency.search_for_structured_data(query)
elif tool_name == "search_last_24_hours":
return self.search_agency.search_last_24_hours(query)
elif tool_name == "search_last_week":
return self.search_agency.search_last_week(query)
else:
print(f" ⚠️ 未知的搜索工具: {tool_name},使用默认基础搜索")
return self.search_agency.basic_search_news(query)
print(f" ⚠️ 未知的搜索工具: {tool_name},使用默认综合搜索")
return self.search_agency.comprehensive_search(query)
def research(self, query: str, save_report: bool = True) -> str:
"""
@@ -231,7 +225,7 @@ class DeepSearchAgent:
print(" - 生成搜索查询...")
search_output = self.first_search_node.run(search_input)
search_query = search_output["search_query"]
search_tool = search_output.get("search_tool", "basic_search_news") # 默认工具
search_tool = search_output.get("search_tool", "comprehensive_search") # 默认工具
reasoning = search_output["reasoning"]
print(f" - 搜索查询: {search_query}")
@@ -241,41 +235,27 @@ class DeepSearchAgent:
# 执行搜索
print(" - 执行网络搜索...")
# 处理search_news_by_date的特殊参数
# 处理特殊参数(新的工具集不需要日期参数处理)
search_kwargs = {}
if search_tool == "search_news_by_date":
start_date = search_output.get("start_date")
end_date = search_output.get("end_date")
if start_date and end_date:
# 验证日期格式
if self._validate_date_format(start_date) and self._validate_date_format(end_date):
search_kwargs["start_date"] = start_date
search_kwargs["end_date"] = end_date
print(f" - 时间范围: {start_date}{end_date}")
else:
print(f" ⚠️ 日期格式错误(应为YYYY-MM-DD),改用基础搜索")
print(f" 提供的日期: start_date={start_date}, end_date={end_date}")
search_tool = "basic_search_news"
else:
print(f" ⚠️ search_news_by_date工具缺少时间参数,改用基础搜索")
search_tool = "basic_search_news"
if search_tool in ["comprehensive_search", "web_search_only"]:
# 这些工具支持max_results参数
search_kwargs["max_results"] = 10
search_response = self.execute_search_tool(search_tool, search_query, **search_kwargs)
# 转换为兼容格式
search_results = []
if search_response and search_response.results:
if search_response and search_response.webpages:
# 每种搜索工具都有其特定的结果数量,这里取前10个作为上限
max_results = min(len(search_response.results), 10)
for result in search_response.results[:max_results]:
max_results = min(len(search_response.webpages), 10)
for result in search_response.webpages[:max_results]:
search_results.append({
'title': result.title,
'title': result.name,
'url': result.url,
'content': result.content,
'score': result.score,
'raw_content': result.raw_content,
'published_date': result.published_date # 新增字段
'content': result.snippet,
'score': None, # Bocha API不提供score
'raw_content': result.snippet,
'published_date': result.date_last_crawled # 使用爬取日期
})
if search_results:
@@ -324,7 +304,7 @@ class DeepSearchAgent:
# 生成反思搜索查询
reflection_output = self.reflection_node.run(reflection_input)
search_query = reflection_output["search_query"]
search_tool = reflection_output.get("search_tool", "basic_search_news") # 默认工具
search_tool = reflection_output.get("search_tool", "comprehensive_search") # 默认工具
reasoning = reflection_output["reasoning"]
print(f" 反思查询: {search_query}")
@@ -332,41 +312,27 @@ class DeepSearchAgent:
print(f" 反思推理: {reasoning}")
# 执行反思搜索
# 处理search_news_by_date的特殊参数
# 处理特殊参数
search_kwargs = {}
if search_tool == "search_news_by_date":
start_date = reflection_output.get("start_date")
end_date = reflection_output.get("end_date")
if start_date and end_date:
# 验证日期格式
if self._validate_date_format(start_date) and self._validate_date_format(end_date):
search_kwargs["start_date"] = start_date
search_kwargs["end_date"] = end_date
print(f" 时间范围: {start_date}{end_date}")
else:
print(f" ⚠️ 日期格式错误(应为YYYY-MM-DD),改用基础搜索")
print(f" 提供的日期: start_date={start_date}, end_date={end_date}")
search_tool = "basic_search_news"
else:
print(f" ⚠️ search_news_by_date工具缺少时间参数,改用基础搜索")
search_tool = "basic_search_news"
if search_tool in ["comprehensive_search", "web_search_only"]:
# 这些工具支持max_results参数
search_kwargs["max_results"] = 10
search_response = self.execute_search_tool(search_tool, search_query, **search_kwargs)
# 转换为兼容格式
search_results = []
if search_response and search_response.results:
if search_response and search_response.webpages:
# 每种搜索工具都有其特定的结果数量,这里取前10个作为上限
max_results = min(len(search_response.results), 10)
for result in search_response.results[:max_results]:
max_results = min(len(search_response.webpages), 10)
for result in search_response.webpages[:max_results]:
search_results.append({
'title': result.title,
'title': result.name,
'url': result.url,
'content': result.content,
'score': result.score,
'raw_content': result.raw_content,
'published_date': result.published_date
'content': result.snippet,
'score': None, # Bocha API不提供score
'raw_content': result.snippet,
'published_date': result.date_last_crawled
})
if search_results: