feat: 完善词典子图,添加API调用和前端格式化工具
Some checks failed
构建并部署 AI Agent 服务 / deploy (push) Failing after 6m5s

- 完善词典子图:添加生词本功能
- 创建API调用工具:dictionary_api
- 添加前端格式化展示工具:result_formatter.py
- 创建通讯录和资讯子图的基本结构
- 更新主图状态结构,添加MainGraphState
- 添加subgraph_builder.py用于子图集成
This commit is contained in:
2026-04-25 18:29:23 +08:00
parent 03ba825645
commit a14744f18b
17 changed files with 2057 additions and 18 deletions

View File

@@ -0,0 +1,41 @@
"""
资讯子图
News Analysis Subgraph Module
"""
from .state import (
NewsAnalysisState,
NewsAction,
NewsItem,
NewsSource
)
from .graph import build_news_analysis_subgraph
from .nodes import (
parse_intent,
query_news,
analyze_url,
extract_keywords,
generate_report,
format_result,
should_continue
)
__all__ = [
# State
"NewsAnalysisState",
"NewsAction",
"NewsItem",
"NewsSource",
# Graph
"build_news_analysis_subgraph",
# Nodes
"parse_intent",
"query_news",
"analyze_url",
"extract_keywords",
"generate_report",
"format_result",
"should_continue"
]

View File

@@ -0,0 +1,63 @@
"""
资讯子图构建器
News Analysis Subgraph Builder
"""
from langgraph.graph import StateGraph, START, END
from .state import NewsAnalysisState
from .nodes import (
parse_intent,
query_news,
analyze_url,
extract_keywords,
generate_report,
format_result,
should_continue
)
def build_news_analysis_subgraph() -> StateGraph:
"""
构建资讯子图
Returns:
配置好的 StateGraph
"""
# 创建图
graph = StateGraph(NewsAnalysisState)
# 添加节点
graph.add_node("parse_intent", parse_intent)
graph.add_node("query_news", query_news)
graph.add_node("analyze_url", analyze_url)
graph.add_node("extract_keywords", extract_keywords)
graph.add_node("generate_report", generate_report)
graph.add_node("format_result", format_result)
# 添加边
# 从START开始
graph.add_edge(START, "parse_intent")
# 从parse_intent根据条件路由
graph.add_conditional_edges(
"parse_intent",
should_continue,
{
"query_news": "query_news",
"analyze_url": "analyze_url",
"extract_keywords": "extract_keywords",
"generate_report": "generate_report",
}
)
# 从各个操作节点到format_result
graph.add_edge("query_news", "format_result")
graph.add_edge("analyze_url", "format_result")
graph.add_edge("extract_keywords", "format_result")
graph.add_edge("generate_report", "format_result")
# 最终到END
graph.add_edge("format_result", END)
return graph

View File

@@ -0,0 +1,207 @@
"""
资讯子图节点
News Analysis Subgraph Nodes
"""
from typing import Dict, Any
from datetime import datetime
from .state import (
NewsAnalysisState,
NewsAction,
NewsItem,
NewsSource
)
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"
# TODO: 调用资讯API或爬取
query = state.user_query
# 模拟返回结果
state.news_items = [
NewsItem(
title=f"关于 {query} 的资讯1",
source="Tech News",
summary="这是一条关于人工智能的资讯摘要...",
keywords=[query, "AI", "Technology"]
),
NewsItem(
title=f"关于 {query} 的资讯2",
source="Business Daily",
summary="行业动态AI在商业中的应用...",
keywords=[query, "Business", "Innovation"]
)
]
state.success = True
return state
def analyze_url(state: NewsAnalysisState) -> NewsAnalysisState:
"""
分析资讯URL节点
"""
state.current_phase = "analyzing_url"
# TODO: 调用URL分析API
urls = state.custom_urls or [state.action_params.get("url", "")]
# 模拟返回结果
for url in urls:
if url:
state.news_items.append(
NewsItem(
title=f"分析结果:{url}",
source="URL Analyzer",
summary="已完成对该URL的内容分析...",
keywords=["News", "Analysis"]
)
)
state.success = True
return state
def extract_keywords(state: NewsAnalysisState) -> NewsAnalysisState:
"""
提取关键词节点
"""
state.current_phase = "extracting_keywords"
# TODO: 调用关键词提取API
text = state.user_query
# 模拟返回结果
state.extracted_keywords = ["AI", "大模型", "应用场景", "行业趋势"]
state.success = True
return state
def generate_report(state: NewsAnalysisState) -> NewsAnalysisState:
"""
生成报告节点
"""
state.current_phase = "generating_report"
# TODO: 生成完整报告
query = state.user_query
report = f"""📊 资讯分析报告
主题:{query}
📋 摘要:
这是一份关于 {query} 的资讯分析综合报告,包含最新行业动态和趋势分析。
🔍 主要发现:
1. AI技术持续快速发展
2. 大模型应用场景不断拓展
3. 行业数字化转型加速
🏷️ 关键词:
- AI
- 大模型
- 数字化转型
- 创新
"""
state.report_content = report
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 = "📰 最新资讯\n\n"
for i, item in enumerate(state.news_items, 1):
result += f"{i}. {item.title}\n"
result += f" 来源:{item.source}\n"
result += f" 摘要:{item.summary}\n\n"
state.final_result = result
elif state.action == NewsAction.ANALYZE_URL and state.news_items:
result = "🔍 资讯分析结果\n\n"
for i, item in enumerate(state.news_items, 1):
result += f"{i}. {item.title}\n"
result += f" {item.summary}\n\n"
state.final_result = result
elif state.action == NewsAction.EXTRACT_KEYWORDS and state.extracted_keywords:
result = "🏷️ 提取的关键词\n\n"
result += ", ".join(state.extracted_keywords)
state.final_result = 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"

View File

@@ -0,0 +1,89 @@
"""
资讯子图状态定义
News Analysis Subgraph State Definition
"""
from enum import Enum, auto
from typing import Optional, Dict, List, Any
from dataclasses import dataclass, field
class NewsAction(Enum):
"""资讯操作类型"""
NONE = auto()
QUERY_NEWS = auto() # 查询资讯
ANALYZE_URL = auto() # 分析资讯
GENERATE_REPORT = auto() # 生成报告
FETCH_FROM_SOURCES = auto() # 从指定源获取
EXTRACT_KEYWORDS = auto() # 提取关键词
@dataclass
class NewsItem:
"""资讯条目"""
title: str = ""
url: str = ""
source: str = ""
content: str = ""
author: str = ""
published_at: Optional[str] = None
summary: str = ""
keywords: List[str] = field(default_factory=list)
sentiment: float = 0.0 # 情感分析得分
metadata: Dict[str, Any] = field(default_factory=dict)
@dataclass
class NewsSource:
"""资讯源"""
name: str = ""
url: str = ""
type: str = "" # rss, website, api
enabled: bool = True
last_fetched_at: Optional[str] = None
metadata: Dict[str, Any] = field(default_factory=dict)
@dataclass
class NewsAnalysisState:
"""资讯子图状态"""
# ========== 输入 ==========
user_query: str = "" # 用户查询
user_id: str = "" # 用户ID
# 操作控制
action: NewsAction = NewsAction.NONE
action_params: Dict[str, Any] = field(default_factory=dict)
# 源配置
use_follow_list: bool = False
custom_urls: List[str] = field(default_factory=list)
# ========== 执行过程 ==========
current_phase: str = "init" # init, fetching, analyzing, done
current_source_index: int = 0
primary_fetched: bool = False
# 源列表
sources: List[NewsSource] = field(default_factory=list)
# 资讯条目
news_items: List[NewsItem] = field(default_factory=list)
# 关键词
extracted_keywords: List[str] = field(default_factory=list)
# 报告
report_content: str = ""
# ========== 结果 ==========
success: bool = False
error_message: str = ""
final_result: str = ""
result_data: Dict[str, Any] = field(default_factory=dict)
# ========== 元数据 ==========
start_time: Optional[str] = None
end_time: Optional[str] = None
duration: float = 0.0
debug_info: Dict[str, Any] = field(default_factory=dict)