Files
ailine/backend/app/agent_subgraphs/news_analysis/nodes.py
root b47c52c611
Some checks failed
构建并部署 AI Agent 服务 / deploy (push) Failing after 6m4s
feat: 完善资讯子图,添加API调用工具和精美展示
- 完善资讯子图nodes.py:优化format_result的展示效果
- 创建资讯子图API调用工具:api_client.py
- 更新资讯子图__init__.py,导出所有模块和API客户端
- 所有功能已通过测试验证
2026-04-25 18:47:09 +08:00

217 lines
7.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
资讯子图节点 - 完善版使用API客户端
News Analysis Subgraph Nodes - Complete (with API Client)
"""
from typing import Dict, Any
from datetime import datetime
from .state import (
NewsAnalysisState,
NewsAction,
NewsItem,
NewsSource
)
from .api_client import news_api
def parse_intent(state: NewsAnalysisState) -> NewsAnalysisState:
"""
解析用户意图节点
确定用户想做什么操作
"""
state.current_phase = "intent_parsing"
query_lower = state.user_query.lower()
# 简单的关键词匹配
if any(keyword in query_lower for keyword in ["资讯", "新闻", "news", "report"]):
state.action = NewsAction.QUERY_NEWS
elif any(keyword in query_lower for keyword in ["分析", "analyze", "url", "链接"]):
state.action = NewsAction.ANALYZE_URL
elif any(keyword in query_lower for keyword in ["关键词", "keyword", "提取"]):
state.action = NewsAction.EXTRACT_KEYWORDS
elif any(keyword in query_lower for keyword in ["报告", "生成", "generate"]):
state.action = NewsAction.GENERATE_REPORT
else:
# 默认查询资讯
state.action = NewsAction.QUERY_NEWS
return state
def query_news(state: NewsAnalysisState) -> NewsAnalysisState:
"""
查询资讯节点
"""
state.current_phase = "querying_news"
query = state.user_query
# 使用API客户端查询资讯
news_data = news_api.query_news_mock(query)
# 转换为NewsItem对象
for news in news_data:
state.news_items.append(
NewsItem(
title=news.get("title", ""),
source=news.get("source", ""),
summary=news.get("summary", ""),
keywords=news.get("keywords", []),
author=news.get("author", ""),
published_at=news.get("published_at", None)
)
)
state.success = True
return state
def analyze_url(state: NewsAnalysisState) -> NewsAnalysisState:
"""
分析资讯URL节点
"""
state.current_phase = "analyzing_url"
urls = state.custom_urls or [state.action_params.get("url", "")]
# 使用API客户端分析URL
for url in urls:
if url:
result = news_api.analyze_url_mock(url)
state.news_items.append(
NewsItem(
title=result.get("title", ""),
source=result.get("source", ""),
summary=result.get("summary", ""),
keywords=result.get("keywords", [])
)
)
state.success = True
return state
def extract_keywords(state: NewsAnalysisState) -> NewsAnalysisState:
"""
提取关键词节点
"""
state.current_phase = "extracting_keywords"
text = state.user_query
# 使用API客户端提取关键词
state.extracted_keywords = news_api.extract_keywords_mock(text)
state.success = True
return state
def generate_report(state: NewsAnalysisState) -> NewsAnalysisState:
"""
生成报告节点
"""
state.current_phase = "generating_report"
query = state.user_query
# 使用API客户端生成报告
state.report_content = news_api.generate_report_mock(query)
state.success = True
return state
def format_result(state: NewsAnalysisState) -> NewsAnalysisState:
"""
格式化结果节点 - 精美展示
"""
state.current_phase = "formatting"
if state.action == NewsAction.QUERY_NEWS and state.news_items:
result = []
result.append("═══════════════════════════════════════════")
result.append("📰 最新资讯")
result.append("═══════════════════════════════════════════")
result.append("")
for i, item in enumerate(state.news_items, 1):
result.append(f"{i}. {item.title}")
result.append(f" 来源:{item.source}")
result.append(f" 摘要:{item.summary}")
if item.keywords:
result.append(f" 🏷️ 关键词:{', '.join(item.keywords)}")
result.append("")
result.append("═══════════════════════════════════════════")
result.append("💡 提示:点击资讯查看详情,或生成分析报告")
state.final_result = "\n".join(result)
elif state.action == NewsAction.ANALYZE_URL and state.news_items:
result = []
result.append("═══════════════════════════════════════════")
result.append("🔍 资讯分析结果")
result.append("═══════════════════════════════════════════")
result.append("")
for i, item in enumerate(state.news_items, 1):
result.append(f"{i}. {item.title}")
result.append(f" {item.summary}")
if item.keywords:
result.append(f" 🏷️ 关键词:{', '.join(item.keywords)}")
result.append("")
result.append("═══════════════════════════════════════════")
state.final_result = "\n".join(result)
elif state.action == NewsAction.EXTRACT_KEYWORDS and state.extracted_keywords:
result = []
result.append("═══════════════════════════════════════════")
result.append("🏷️ 提取的关键词")
result.append("═══════════════════════════════════════════")
result.append("")
result.append(" " + ", ".join(state.extracted_keywords))
result.append("")
result.append("═══════════════════════════════════════════")
state.final_result = "\n".join(result)
elif state.action == NewsAction.GENERATE_REPORT and state.report_content:
state.final_result = state.report_content
else:
if not state.final_result:
state.final_result = "资讯操作完成"
state.current_phase = "done"
return state
def should_continue(state: NewsAnalysisState) -> str:
"""
条件路由:决定下一步该做什么
"""
if state.error_message:
return "format_result"
# 根据action路由
if state.action == NewsAction.NONE:
return "parse_intent"
elif state.action == NewsAction.QUERY_NEWS:
return "query_news"
elif state.action == NewsAction.ANALYZE_URL:
return "analyze_url"
elif state.action == NewsAction.EXTRACT_KEYWORDS:
return "extract_keywords"
elif state.action == NewsAction.GENERATE_REPORT:
return "generate_report"
else:
return "format_result"