2026-05-05 00:54:04 +08:00
|
|
|
|
"""
|
|
|
|
|
|
联网搜索节点 - 执行搜索并将结果保存到状态
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
2026-05-05 23:17:00 +08:00
|
|
|
|
from typing import Optional
|
2026-05-05 00:54:04 +08:00
|
|
|
|
from datetime import datetime
|
2026-05-05 23:17:00 +08:00
|
|
|
|
from langchain_core.runnables.config import RunnableConfig
|
2026-05-05 00:54:04 +08:00
|
|
|
|
|
2026-05-05 23:17:00 +08:00
|
|
|
|
from ...main_graph.state import MainGraphState, ErrorRecord, ErrorSeverity
|
2026-05-06 01:15:52 +08:00
|
|
|
|
from backend.app.logger import info
|
2026-05-05 00:54:04 +08:00
|
|
|
|
|
|
|
|
|
|
|
2026-05-05 23:17:00 +08:00
|
|
|
|
async def web_search_node(state: MainGraphState, config: Optional[RunnableConfig] = None) -> MainGraphState:
|
2026-05-05 00:54:04 +08:00
|
|
|
|
"""
|
|
|
|
|
|
联网搜索节点:执行搜索并将结果保存到状态
|
|
|
|
|
|
"""
|
|
|
|
|
|
state.current_phase = "web_searching"
|
|
|
|
|
|
|
|
|
|
|
|
# 发送开始事件
|
|
|
|
|
|
if config:
|
|
|
|
|
|
try:
|
|
|
|
|
|
from langchain_core.callbacks.manager import adispatch_custom_event
|
|
|
|
|
|
callbacks = config.get("callbacks")
|
|
|
|
|
|
if callbacks:
|
|
|
|
|
|
await adispatch_custom_event(
|
|
|
|
|
|
"react_reasoning",
|
|
|
|
|
|
{
|
|
|
|
|
|
"step": state.reasoning_step,
|
|
|
|
|
|
"action": "web_search_start",
|
|
|
|
|
|
"confidence": 1.0,
|
|
|
|
|
|
"reasoning": "开始执行联网搜索..."
|
|
|
|
|
|
},
|
|
|
|
|
|
callbacks=callbacks
|
|
|
|
|
|
)
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
info(f"[web_search_node] 无法发送开始事件: {e}")
|
|
|
|
|
|
|
|
|
|
|
|
# 获取搜索查询
|
|
|
|
|
|
reasoning_result = state.debug_info.get("reasoning_result")
|
|
|
|
|
|
search_query = reasoning_result.metadata.get("search_query", state.user_query) if reasoning_result else state.user_query
|
|
|
|
|
|
|
|
|
|
|
|
try:
|
2026-05-05 23:17:00 +08:00
|
|
|
|
from backend.app.core import web_search
|
2026-05-05 00:54:04 +08:00
|
|
|
|
|
|
|
|
|
|
print(f"[WebSearch] 搜索: {search_query}")
|
|
|
|
|
|
search_result = web_search(search_query, max_results=5)
|
|
|
|
|
|
|
|
|
|
|
|
# 保存搜索结果到状态
|
|
|
|
|
|
if not hasattr(state, "web_search_results"):
|
|
|
|
|
|
state.web_search_results = []
|
|
|
|
|
|
state.web_search_results.append(search_result)
|
|
|
|
|
|
|
|
|
|
|
|
# 将搜索结果添加到 rag_context,供 LLM 使用
|
|
|
|
|
|
if state.rag_context:
|
|
|
|
|
|
state.rag_context = f"{state.rag_context}\n\n---\n\n## 🌐 联网搜索结果:\n{search_result}"
|
|
|
|
|
|
else:
|
|
|
|
|
|
state.rag_context = f"## 🌐 联网搜索结果:\n{search_result}"
|
|
|
|
|
|
|
|
|
|
|
|
state.success = True
|
|
|
|
|
|
print(f"[WebSearch] 搜索完成")
|
|
|
|
|
|
|
|
|
|
|
|
# 发送完成事件
|
|
|
|
|
|
if config:
|
|
|
|
|
|
try:
|
|
|
|
|
|
from langchain_core.callbacks.manager import adispatch_custom_event
|
|
|
|
|
|
callbacks = config.get("callbacks")
|
|
|
|
|
|
if callbacks:
|
|
|
|
|
|
await adispatch_custom_event(
|
|
|
|
|
|
"react_reasoning",
|
|
|
|
|
|
{
|
|
|
|
|
|
"step": state.reasoning_step,
|
|
|
|
|
|
"action": "web_search_complete",
|
|
|
|
|
|
"confidence": 1.0,
|
|
|
|
|
|
"reasoning": f"联网搜索完成,找到 {len(search_result) if isinstance(search_result, list) else 1} 条结果"
|
|
|
|
|
|
},
|
|
|
|
|
|
callbacks=callbacks
|
|
|
|
|
|
)
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
info(f"[web_search_node] 无法发送完成事件: {e}")
|
|
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
error_record = ErrorRecord(
|
|
|
|
|
|
error_type="WebSearchError",
|
|
|
|
|
|
error_message=str(e),
|
|
|
|
|
|
severity=ErrorSeverity.WARNING,
|
|
|
|
|
|
source="web_search_node",
|
|
|
|
|
|
timestamp=datetime.now().isoformat(),
|
|
|
|
|
|
retry_count=0,
|
|
|
|
|
|
max_retries=2,
|
|
|
|
|
|
context={"search_query": search_query}
|
|
|
|
|
|
)
|
|
|
|
|
|
state.errors.append(error_record)
|
|
|
|
|
|
state.current_error = error_record
|
|
|
|
|
|
state.current_phase = "error_handling"
|
|
|
|
|
|
state.success = False
|
|
|
|
|
|
|
|
|
|
|
|
# 发送错误事件
|
|
|
|
|
|
if config:
|
|
|
|
|
|
try:
|
|
|
|
|
|
from langchain_core.callbacks.manager import adispatch_custom_event
|
|
|
|
|
|
callbacks = config.get("callbacks")
|
|
|
|
|
|
if callbacks:
|
|
|
|
|
|
await adispatch_custom_event(
|
|
|
|
|
|
"react_reasoning",
|
|
|
|
|
|
{
|
|
|
|
|
|
"step": state.reasoning_step,
|
|
|
|
|
|
"action": "web_search_error",
|
|
|
|
|
|
"confidence": 1.0,
|
|
|
|
|
|
"reasoning": f"联网搜索失败: {str(e)}"
|
|
|
|
|
|
},
|
|
|
|
|
|
callbacks=callbacks
|
|
|
|
|
|
)
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
info(f"[web_search_node] 无法发送错误事件: {e}")
|
|
|
|
|
|
|
|
|
|
|
|
return state
|