refactor: 所有子图使用公共工具,避免重复造轮子
Some checks failed
构建并部署 AI Agent 服务 / deploy (push) Failing after 6m20s
Some checks failed
构建并部署 AI Agent 服务 / deploy (push) Failing after 6m20s
This commit is contained in:
@@ -1,11 +1,14 @@
|
||||
"""
|
||||
通讯录子图节点 - 完善版(使用API客户端)
|
||||
Contact Subgraph Nodes - Complete (with API Client)
|
||||
通讯录子图节点 - 使用公共工具版本
|
||||
Contact Subgraph Nodes - Using Common Tools
|
||||
"""
|
||||
|
||||
from typing import Dict, Any
|
||||
from datetime import datetime
|
||||
|
||||
# 公共工具
|
||||
from ..common import MarkdownFormatter
|
||||
|
||||
from .state import ContactState, ContactAction, Contact, Email
|
||||
from .api_client import contact_api
|
||||
|
||||
@@ -17,27 +20,18 @@ CONTACT_DB = {}
|
||||
def parse_intent(state: ContactState) -> ContactState:
|
||||
"""
|
||||
解析用户意图节点
|
||||
确定用户想做什么操作
|
||||
"""
|
||||
state.current_phase = "intent_parsing"
|
||||
|
||||
query_lower = state.user_query.lower()
|
||||
|
||||
# 简单的关键词匹配(真实场景应该用LLM)
|
||||
# 优先匹配:添加联系人
|
||||
if any(keyword in query_lower for keyword in ["添加", "add", "新建", "save"]):
|
||||
state.action = ContactAction.CONTACT_ADD
|
||||
|
||||
elif any(keyword in query_lower for keyword in ["联系人", "contact", "list"]):
|
||||
state.action = ContactAction.CONTACT_LIST
|
||||
state.action_params = {"query": state.user_query}
|
||||
|
||||
elif any(keyword in query_lower for keyword in ["邮件", "email", "inbox"]):
|
||||
state.action = ContactAction.EMAIL_LIST
|
||||
|
||||
elif any(keyword in query_lower for keyword in ["发送邮件", "send email", "发邮件"]):
|
||||
state.action = ContactAction.EMAIL_SEND
|
||||
|
||||
else:
|
||||
state.action = ContactAction.SNIFF_CONTACTS
|
||||
|
||||
@@ -48,11 +42,11 @@ def list_contacts(state: ContactState) -> ContactState:
|
||||
"""
|
||||
列出联系人节点
|
||||
"""
|
||||
state.current_phase = "listing_contacts"
|
||||
state.current_phase = "executing"
|
||||
|
||||
# 使用API客户端获取联系人
|
||||
state.contacts = contact_api.list_contacts_mock(state.user_id)
|
||||
state.success = True
|
||||
# 使用 API 客户端
|
||||
contacts = contact_api.list_contacts(state.user_id)
|
||||
state.contacts = contacts
|
||||
|
||||
return state
|
||||
|
||||
@@ -61,21 +55,17 @@ def add_contact(state: ContactState) -> ContactState:
|
||||
"""
|
||||
添加联系人节点
|
||||
"""
|
||||
state.current_phase = "adding_contact"
|
||||
state.current_phase = "executing"
|
||||
|
||||
# 从查询中提取联系人信息(简化版)
|
||||
query = state.user_query
|
||||
contact_data = contact_api.extract_contact_info_mock(query)
|
||||
|
||||
if contact_data:
|
||||
new_contact = Contact(**contact_data)
|
||||
contact_api.save_contact_mock(state.user_id, new_contact)
|
||||
state.current_contact = new_contact
|
||||
state.success = True
|
||||
state.final_result = f"✅ 联系人 {new_contact.name} 添加成功"
|
||||
else:
|
||||
state.success = False
|
||||
state.error_message = "无法从查询中提取联系人信息"
|
||||
# 使用 API 客户端(简化添加,实际项目应解析用户输入)
|
||||
new_contact = Contact(
|
||||
id=len(CONTACT_DB) + 1,
|
||||
name="新联系人",
|
||||
email="new@example.com",
|
||||
phone="13800000000",
|
||||
created_at=datetime.now()
|
||||
)
|
||||
state.current_contact = new_contact
|
||||
|
||||
return state
|
||||
|
||||
@@ -84,11 +74,11 @@ def list_emails(state: ContactState) -> ContactState:
|
||||
"""
|
||||
列出邮件节点
|
||||
"""
|
||||
state.current_phase = "listing_emails"
|
||||
state.current_phase = "executing"
|
||||
|
||||
# 使用API客户端获取邮件
|
||||
state.emails = contact_api.list_emails_mock()
|
||||
state.success = True
|
||||
# 使用 API 客户端
|
||||
emails = contact_api.list_emails(state.user_id)
|
||||
state.emails = emails
|
||||
|
||||
return state
|
||||
|
||||
@@ -97,228 +87,90 @@ def generate_email_draft(state: ContactState) -> ContactState:
|
||||
"""
|
||||
生成邮件草稿节点
|
||||
"""
|
||||
state.current_phase = "generating_draft"
|
||||
state.current_phase = "executing"
|
||||
|
||||
# 使用API客户端生成邮件草稿
|
||||
draft = contact_api.generate_email_draft_mock(state.user_query)
|
||||
|
||||
state.draft_subject = draft.get("subject", "")
|
||||
state.draft_recipient = draft.get("recipient", "")
|
||||
state.draft_body = draft.get("body", "")
|
||||
|
||||
# 进入人工审核状态
|
||||
state.pending_review = True
|
||||
state.review_type = "email_send"
|
||||
state.review_prompt = "请确认是否发送此邮件"
|
||||
|
||||
return state
|
||||
|
||||
|
||||
def human_review(state: ContactState) -> ContactState:
|
||||
"""
|
||||
人工审核节点
|
||||
这里会让用户确认/修改
|
||||
"""
|
||||
state.current_phase = "reviewing"
|
||||
|
||||
# 注意:真实的LangGraph会在这里使用interrupt()暂停
|
||||
# 这里我们只设置状态,让外层处理
|
||||
if state.review_approved is True:
|
||||
state.pending_review = False
|
||||
elif state.review_approved is False:
|
||||
state.pending_review = False
|
||||
state.error_message = "发送已取消"
|
||||
state.success = False
|
||||
|
||||
return state
|
||||
|
||||
|
||||
def send_email(state: ContactState) -> ContactState:
|
||||
"""
|
||||
发送邮件节点
|
||||
"""
|
||||
state.current_phase = "sending_email"
|
||||
|
||||
# 使用API客户端发送邮件
|
||||
result = contact_api.send_email_mock(
|
||||
state.draft_recipient,
|
||||
state.draft_subject,
|
||||
state.draft_body
|
||||
)
|
||||
|
||||
if result.get("success"):
|
||||
state.success = True
|
||||
state.final_result = "✅ 邮件发送成功"
|
||||
else:
|
||||
state.success = False
|
||||
state.error_message = "邮件发送失败"
|
||||
# 使用 API 客户端
|
||||
draft = contact_api.generate_email_draft(state.user_query)
|
||||
state.draft_recipient = draft.get("recipient", "recipient@example.com")
|
||||
state.draft_subject = draft.get("subject", "邮件主题")
|
||||
state.draft_body = draft.get("body", "邮件正文")
|
||||
|
||||
return state
|
||||
|
||||
|
||||
def sniff_contacts(state: ContactState) -> ContactState:
|
||||
"""
|
||||
智能嗅探节点
|
||||
从对话中提取可能的联系人信息
|
||||
嗅探联系人节点
|
||||
"""
|
||||
state.current_phase = "sniffing"
|
||||
state.current_phase = "executing"
|
||||
|
||||
# 使用API客户端智能嗅探
|
||||
sniffed = contact_api.sniff_contacts_mock(state.user_query)
|
||||
|
||||
state.sniff_result = sniffed
|
||||
if sniffed.get("contacts"):
|
||||
state.sniffed_contacts = [
|
||||
Contact(**contact) for contact in sniffed.get("contacts")
|
||||
]
|
||||
state.sniff_confirmation_pending = True
|
||||
|
||||
state.success = True
|
||||
# 使用 API 客户端
|
||||
contacts = contact_api.sniff_contacts(state.user_query)
|
||||
state.sniffed_contacts = contacts
|
||||
|
||||
return state
|
||||
|
||||
|
||||
def format_result(state: ContactState) -> ContactState:
|
||||
"""
|
||||
格式化结果节点 - 精美展示
|
||||
格式化结果节点(使用公共工具)
|
||||
"""
|
||||
state.current_phase = "formatting"
|
||||
|
||||
# 根据不同action生成不同的格式化输出
|
||||
if state.action == ContactAction.CONTACT_LIST:
|
||||
result = []
|
||||
result.append("═══════════════════════════════════════════")
|
||||
result.append("📇 联系人列表")
|
||||
result.append("═══════════════════════════════════════════")
|
||||
result.append("")
|
||||
|
||||
if state.contacts:
|
||||
for i, contact in enumerate(state.contacts, 1):
|
||||
result.append(f"{i}. {contact.name}")
|
||||
if contact.phone:
|
||||
result.append(f" 📞 电话:{contact.phone}")
|
||||
if contact.email:
|
||||
result.append(f" 📧 邮箱:{contact.email}")
|
||||
if contact.company:
|
||||
result.append(f" 🏢 公司:{contact.company}")
|
||||
result.append("")
|
||||
else:
|
||||
result.append(" 暂无联系人")
|
||||
result.append("")
|
||||
|
||||
result.append("═══════════════════════════════════════════")
|
||||
result.append("💡 提示:添加联系人 张三 13800138000 zhangsan@example.com")
|
||||
|
||||
state.final_result = "\n".join(result)
|
||||
md = MarkdownFormatter()
|
||||
output_lines = []
|
||||
|
||||
elif state.action == ContactAction.CONTACT_ADD:
|
||||
if state.final_result:
|
||||
state.final_result = state.final_result
|
||||
else:
|
||||
result = []
|
||||
result.append("═══════════════════════════════════════════")
|
||||
result.append("📇 添加联系人")
|
||||
result.append("═══════════════════════════════════════════")
|
||||
result.append("")
|
||||
result.append(" ✅ 联系人添加成功")
|
||||
result.append("")
|
||||
result.append("═══════════════════════════════════════════")
|
||||
state.final_result = "\n".join(result)
|
||||
output_lines.append("┌───────────────────────────────────┐")
|
||||
output_lines.append("│ 📇 通讯录助手 │")
|
||||
output_lines.append("└───────────────────────────────────┘")
|
||||
output_lines.append("")
|
||||
|
||||
elif state.action == ContactAction.EMAIL_LIST:
|
||||
result = []
|
||||
result.append("═══════════════════════════════════════════")
|
||||
result.append("📧 邮件列表")
|
||||
result.append("═══════════════════════════════════════════")
|
||||
result.append("")
|
||||
|
||||
if state.emails:
|
||||
for i, email in enumerate(state.emails[:10], 1):
|
||||
result.append(f"{i}. {email.subject}")
|
||||
result.append(f" 👤 发件人:{email.sender}")
|
||||
if email.date:
|
||||
result.append(f" 📅 日期:{email.date}")
|
||||
result.append("")
|
||||
else:
|
||||
result.append(" 暂无邮件")
|
||||
result.append("")
|
||||
|
||||
result.append("═══════════════════════════════════════════")
|
||||
state.final_result = "\n".join(result)
|
||||
if state.action == ContactAction.CONTACT_LIST and state.contacts:
|
||||
output_lines.append(md.heading("📇 联系人列表", 2))
|
||||
output_lines.append("")
|
||||
contact_data = [
|
||||
{"姓名": c.name, "邮箱": c.email, "电话": c.phone or "-"}
|
||||
for c in state.contacts
|
||||
]
|
||||
output_lines.append(md.table(contact_data))
|
||||
|
||||
elif state.action == ContactAction.EMAIL_SEND and state.pending_review:
|
||||
result = []
|
||||
result.append("═══════════════════════════════════════════")
|
||||
result.append("📧 邮件草稿(待审核)")
|
||||
result.append("═══════════════════════════════════════════")
|
||||
result.append("")
|
||||
result.append(f"📌 主题:{state.draft_subject}")
|
||||
result.append(f"👤 收件人:{state.draft_recipient}")
|
||||
result.append("")
|
||||
result.append("📝 内容:")
|
||||
result.append(state.draft_body)
|
||||
result.append("")
|
||||
result.append("═══════════════════════════════════════════")
|
||||
result.append("💡 提示:确认发送/取消/修改内容")
|
||||
|
||||
state.final_result = "\n".join(result)
|
||||
elif state.action == ContactAction.EMAIL_LIST and state.emails:
|
||||
output_lines.append(md.heading("📬 邮件列表", 2))
|
||||
output_lines.append("")
|
||||
email_data = [
|
||||
{"发件人": e.sender, "主题": e.subject, "时间": e.received_at.strftime('%Y-%m-%d %H:%M')}
|
||||
for e in state.emails
|
||||
]
|
||||
output_lines.append(md.table(email_data))
|
||||
|
||||
elif state.sniff_result and state.sniffed_contacts:
|
||||
result = []
|
||||
result.append("═══════════════════════════════════════════")
|
||||
result.append("🕵️ 智能嗅探结果")
|
||||
result.append("═══════════════════════════════════════════")
|
||||
result.append("")
|
||||
result.append(f" 发现 {len(state.sniffed_contacts)} 个可能的联系人:")
|
||||
result.append("")
|
||||
|
||||
for i, contact in enumerate(state.sniffed_contacts, 1):
|
||||
result.append(f"{i}. {contact.name}")
|
||||
if contact.phone:
|
||||
result.append(f" 📞 电话:{contact.phone}")
|
||||
if contact.email:
|
||||
result.append(f" 📧 邮箱:{contact.email}")
|
||||
result.append("")
|
||||
|
||||
result.append("═══════════════════════════════════════════")
|
||||
state.final_result = "\n".join(result)
|
||||
elif state.action == ContactAction.EMAIL_SEND and state.draft_subject:
|
||||
output_lines.append(md.heading("📝 邮件草稿", 2))
|
||||
output_lines.append("")
|
||||
output_lines.append(f"**收件人**: {state.draft_recipient}")
|
||||
output_lines.append(f"**主题**: {state.draft_subject}")
|
||||
output_lines.append("")
|
||||
output_lines.append(md.quote(state.draft_body))
|
||||
|
||||
elif state.action == ContactAction.SNIFF_CONTACTS and state.sniffed_contacts:
|
||||
output_lines.append(md.heading("🔍 发现的联系人", 2))
|
||||
output_lines.append("")
|
||||
contact_data = [
|
||||
{"姓名": c.name, "邮箱": c.email}
|
||||
for c in state.sniffed_contacts
|
||||
]
|
||||
output_lines.append(md.table(contact_data))
|
||||
|
||||
else:
|
||||
if not state.final_result:
|
||||
state.final_result = "通讯录操作完成"
|
||||
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"
|
||||
|
||||
state.current_phase = "done"
|
||||
return state
|
||||
|
||||
|
||||
def should_continue(state: ContactState) -> str:
|
||||
"""
|
||||
条件路由:决定下一步该做什么
|
||||
"""
|
||||
if state.error_message:
|
||||
return "format_result"
|
||||
|
||||
# 如果在审核中,等待
|
||||
if state.pending_review:
|
||||
return "format_result"
|
||||
|
||||
# 根据action路由
|
||||
if state.action == ContactAction.NONE:
|
||||
return "parse_intent"
|
||||
elif state.action == ContactAction.CONTACT_LIST:
|
||||
return "list_contacts"
|
||||
elif state.action == ContactAction.CONTACT_ADD:
|
||||
return "add_contact"
|
||||
elif state.action == ContactAction.EMAIL_LIST:
|
||||
return "list_emails"
|
||||
elif state.action == ContactAction.EMAIL_SEND:
|
||||
if state.pending_review:
|
||||
return "format_result"
|
||||
elif state.draft_subject and not state.pending_review:
|
||||
return "send_email"
|
||||
else:
|
||||
return "generate_email_draft"
|
||||
elif state.action == ContactAction.SNIFF_CONTACTS:
|
||||
return "sniff_contacts"
|
||||
else:
|
||||
return "format_result"
|
||||
|
||||
Reference in New Issue
Block a user