2026-04-25 18:29:23 +08:00
|
|
|
|
"""
|
2026-04-25 20:02:20 +08:00
|
|
|
|
资讯子图节点 - 使用公共工具版本
|
|
|
|
|
|
News Analysis Subgraph Nodes - Using Common Tools
|
2026-04-25 18:29:23 +08:00
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
from typing import Dict, Any
|
|
|
|
|
|
from datetime import datetime
|
|
|
|
|
|
|
2026-04-25 20:02:20 +08:00
|
|
|
|
# 公共工具
|
|
|
|
|
|
from ..common import MarkdownFormatter
|
|
|
|
|
|
|
2026-04-25 18:29:23 +08:00
|
|
|
|
from .state import (
|
|
|
|
|
|
NewsAnalysisState,
|
|
|
|
|
|
NewsAction,
|
|
|
|
|
|
NewsItem,
|
|
|
|
|
|
NewsSource
|
|
|
|
|
|
)
|
2026-04-25 18:47:09 +08:00
|
|
|
|
from .api_client import news_api
|
2026-04-25 18:29:23 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def parse_intent(state: NewsAnalysisState) -> NewsAnalysisState:
|
|
|
|
|
|
"""
|
|
|
|
|
|
解析用户意图节点
|
|
|
|
|
|
确定用户想做什么操作
|
|
|
|
|
|
"""
|
|
|
|
|
|
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:
|
|
|
|
|
|
"""
|
|
|
|
|
|
查询资讯节点
|
|
|
|
|
|
"""
|
2026-04-25 20:02:20 +08:00
|
|
|
|
state.current_phase = "executing"
|
2026-04-25 18:29:23 +08:00
|
|
|
|
|
2026-04-25 20:02:20 +08:00
|
|
|
|
# 使用 API 客户端
|
|
|
|
|
|
news_items = news_api.query_news(state.user_query)
|
|
|
|
|
|
state.news_items = news_items
|
2026-04-25 18:29:23 +08:00
|
|
|
|
|
|
|
|
|
|
return state
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def analyze_url(state: NewsAnalysisState) -> NewsAnalysisState:
|
|
|
|
|
|
"""
|
2026-04-25 20:02:20 +08:00
|
|
|
|
分析 URL 节点
|
2026-04-25 18:29:23 +08:00
|
|
|
|
"""
|
2026-04-25 20:02:20 +08:00
|
|
|
|
state.current_phase = "executing"
|
|
|
|
|
|
|
|
|
|
|
|
# 从用户输入中提取 URL(简单处理)
|
|
|
|
|
|
query = state.user_query
|
|
|
|
|
|
url = query
|
|
|
|
|
|
for keyword in ["分析", "analyze", "url", "链接"]:
|
|
|
|
|
|
url = url.replace(keyword, "").strip()
|
|
|
|
|
|
|
|
|
|
|
|
if not url:
|
|
|
|
|
|
url = "https://example.com/news/article"
|
|
|
|
|
|
|
|
|
|
|
|
state.custom_urls = [url]
|
|
|
|
|
|
|
|
|
|
|
|
# 使用 API 客户端
|
|
|
|
|
|
analysis = news_api.analyze_url(url)
|
|
|
|
|
|
state.analysis = analysis
|
2026-04-25 18:29:23 +08:00
|
|
|
|
|
|
|
|
|
|
return state
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def extract_keywords(state: NewsAnalysisState) -> NewsAnalysisState:
|
|
|
|
|
|
"""
|
|
|
|
|
|
提取关键词节点
|
|
|
|
|
|
"""
|
2026-04-25 20:02:20 +08:00
|
|
|
|
state.current_phase = "executing"
|
2026-04-25 18:29:23 +08:00
|
|
|
|
|
2026-04-25 20:02:20 +08:00
|
|
|
|
# 使用 API 客户端
|
|
|
|
|
|
keywords = news_api.extract_keywords(state.user_query)
|
|
|
|
|
|
state.extracted_keywords = keywords
|
2026-04-25 18:29:23 +08:00
|
|
|
|
|
|
|
|
|
|
return state
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def generate_report(state: NewsAnalysisState) -> NewsAnalysisState:
|
|
|
|
|
|
"""
|
|
|
|
|
|
生成报告节点
|
|
|
|
|
|
"""
|
2026-04-25 20:02:20 +08:00
|
|
|
|
state.current_phase = "executing"
|
2026-04-25 18:29:23 +08:00
|
|
|
|
|
2026-04-25 20:02:20 +08:00
|
|
|
|
# 使用 API 客户端
|
|
|
|
|
|
report = news_api.generate_report(state.user_query)
|
|
|
|
|
|
state.report_content = report
|
2026-04-25 18:29:23 +08:00
|
|
|
|
|
|
|
|
|
|
return state
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def format_result(state: NewsAnalysisState) -> NewsAnalysisState:
|
|
|
|
|
|
"""
|
2026-04-25 20:02:20 +08:00
|
|
|
|
格式化结果节点(使用公共工具)
|
2026-04-25 18:29:23 +08:00
|
|
|
|
"""
|
|
|
|
|
|
state.current_phase = "formatting"
|
|
|
|
|
|
|
2026-04-25 20:02:20 +08:00
|
|
|
|
md = MarkdownFormatter()
|
|
|
|
|
|
output_lines = []
|
|
|
|
|
|
|
|
|
|
|
|
output_lines.append("┌───────────────────────────────────┐")
|
|
|
|
|
|
output_lines.append("│ 📰 资讯助手 │")
|
|
|
|
|
|
output_lines.append("└───────────────────────────────────┘")
|
|
|
|
|
|
output_lines.append("")
|
|
|
|
|
|
|
2026-04-25 18:29:23 +08:00
|
|
|
|
if state.action == NewsAction.QUERY_NEWS and state.news_items:
|
2026-04-25 20:02:20 +08:00
|
|
|
|
output_lines.append(md.heading("📰 最新资讯", 2))
|
|
|
|
|
|
output_lines.append("")
|
2026-04-25 18:29:23 +08:00
|
|
|
|
|
2026-04-25 20:02:20 +08:00
|
|
|
|
for item in state.news_items:
|
|
|
|
|
|
output_lines.append(md.heading(item.title, 3))
|
|
|
|
|
|
output_lines.append(f"> 来源: {item.source.value}")
|
|
|
|
|
|
output_lines.append(f"> 时间: {item.published_at.strftime('%Y-%m-%d %H:%M')}")
|
|
|
|
|
|
if item.summary:
|
|
|
|
|
|
output_lines.append("")
|
|
|
|
|
|
output_lines.append(item.summary)
|
|
|
|
|
|
if item.url:
|
|
|
|
|
|
output_lines.append(f"🔗 链接: {md.link(item.title, item.url)}")
|
|
|
|
|
|
output_lines.append("")
|
2026-04-25 18:29:23 +08:00
|
|
|
|
|
|
|
|
|
|
elif state.action == NewsAction.EXTRACT_KEYWORDS and state.extracted_keywords:
|
2026-04-25 20:02:20 +08:00
|
|
|
|
output_lines.append(md.heading("🏷️ 提取的关键词", 2))
|
|
|
|
|
|
output_lines.append("")
|
|
|
|
|
|
keywords_data = [
|
|
|
|
|
|
{"关键词": k, "权重": f"{w:.2f}"}
|
|
|
|
|
|
for k, w in state.extracted_keywords.items()
|
|
|
|
|
|
]
|
|
|
|
|
|
output_lines.append(md.table(keywords_data))
|
2026-04-25 18:29:23 +08:00
|
|
|
|
|
|
|
|
|
|
elif state.action == NewsAction.GENERATE_REPORT and state.report_content:
|
2026-04-25 20:02:20 +08:00
|
|
|
|
output_lines.append(md.heading("📊 分析报告", 2))
|
|
|
|
|
|
output_lines.append("")
|
|
|
|
|
|
output_lines.append(state.report_content)
|
|
|
|
|
|
|
|
|
|
|
|
elif state.action == NewsAction.ANALYZE_URL and state.analysis:
|
|
|
|
|
|
output_lines.append(md.heading("🔍 URL 分析", 2))
|
|
|
|
|
|
output_lines.append("")
|
|
|
|
|
|
output_lines.append(f"> URL: {state.custom_urls[0]}")
|
|
|
|
|
|
output_lines.append("")
|
|
|
|
|
|
output_lines.append(state.analysis)
|
2026-04-25 18:29:23 +08:00
|
|
|
|
|
|
|
|
|
|
else:
|
2026-04-25 20:02:20 +08:00
|
|
|
|
output_lines.append(md.heading("✨ 操作完成", 2))
|
|
|
|
|
|
output_lines.append("您的请求已处理。")
|
|
|
|
|
|
|
|
|
|
|
|
# 页脚提示
|
|
|
|
|
|
output_lines.append("")
|
|
|
|
|
|
output_lines.append("---")
|
|
|
|
|
|
output_lines.append("💡 提示:您可以继续查询资讯、提取关键词或者生成报告!")
|
|
|
|
|
|
|
|
|
|
|
|
state.final_result = "\n".join(output_lines)
|
|
|
|
|
|
state.success = True
|
|
|
|
|
|
state.current_phase = "completed"
|
2026-04-25 18:29:23 +08:00
|
|
|
|
|
|
|
|
|
|
return state
|