feat: 完善子图,添加路由函数和审核节点
Some checks failed
构建并部署 AI Agent 服务 / deploy (push) Failing after 6m10s

This commit is contained in:
2026-04-25 20:46:30 +08:00
parent d05a57948c
commit e6337eb0fc
5 changed files with 139 additions and 6 deletions

View File

@@ -3,10 +3,10 @@
提供可复用的基础组件
导出:
- formatter: 格式化输出工具
- intent: 意图理解工具
- human_review: 人工审核工具
- state_base: 状态基类工具
- formatter.py: 格式化输出工具
- intent.py: 意图理解工具
- human_review.py: 人工审核工具
- state_base.py: 状态基类工具
"""
from .formatter import (

View File

@@ -192,6 +192,45 @@ class ContactAPIClient:
"suggestion": "是否添加这些联系人?"
}
# 公共方法
def list_contacts(self, user_id: str = "default") -> List[Contact]:
"""查询联系人列表"""
return self.list_contacts_mock(user_id)
def add_contact(self, user_id: str, contact: Contact) -> bool:
"""添加联系人"""
return self.save_contact_mock(user_id, contact)
def list_emails(self, user_id: str = "default") -> List[Email]:
"""查询邮件列表"""
return self.list_emails_mock()
def generate_email_draft(self, query: str) -> Dict[str, str]:
"""生成邮件草稿"""
return self.generate_email_draft_mock(query)
def send_email(self, user_id: str, recipient: str, subject: str, body: str) -> bool:
"""发送邮件"""
result = self.send_email_mock(recipient, subject, body)
return result.get("success", False)
def sniff_contacts(self, query: str) -> List[Contact]:
"""智能嗅探联系人"""
result = self.sniff_contacts_mock(query)
contact_dicts = result.get("contacts", [])
return [
Contact(
id=str(i+1),
name=c.get("name", ""),
phone=c.get("phone", ""),
email=c.get("email", ""),
company="",
position="",
created_at=datetime.now().isoformat()
)
for i, c in enumerate(contact_dicts)
]
# 单例实例
contact_api = ContactAPIClient()

View File

@@ -172,5 +172,59 @@ def format_result(state: ContactState) -> ContactState:
state.final_result = "\n".join(output_lines)
state.success = True
state.current_phase = "completed"
return state
def human_review(state: ContactState) -> ContactState:
"""
人工审核节点(用于邮件草稿)
"""
state.current_phase = "reviewing"
# 标记需要审核,等待用户决定
state.needs_approval = True
return state
def send_email(state: ContactState) -> ContactState:
"""
发送邮件节点
"""
state.current_phase = "executing"
# 使用 API 客户端发送邮件
success = contact_api.send_email(
state.user_id,
state.draft_recipient,
state.draft_subject,
state.draft_body
)
state.success = success
return state
def should_continue(state: ContactState) -> str:
"""
条件路由函数:根据 action 和状态决定下一个节点
"""
# 如果是从 human_review 来的,根据审核状态决定
if state.current_phase == "reviewing":
if state.needs_approval:
# 这里会等待用户操作,实际运行时通过 checkpointer 或后端 API 处理
return "format_result"
else:
return "send_email"
# 普通路由
action = state.action
if action == ContactAction.CONTACT_LIST:
return "list_contacts"
elif action == ContactAction.CONTACT_ADD:
return "add_contact"
elif action == ContactAction.EMAIL_LIST:
return "list_emails"
elif action == ContactAction.EMAIL_SEND:
return "generate_email_draft"
elif action == ContactAction.SNIFF_CONTACTS:
return "sniff_contacts"
else:
return "format_result"

View File

@@ -250,5 +250,28 @@ def format_result(state: DictionaryState) -> DictionaryState:
state.final_result = "\n".join(output_lines)
state.success = True
state.current_phase = "completed"
return state
def should_continue(state: DictionaryState) -> str:
"""
条件路由函数:根据 action 决定下一个节点
"""
action = state.action
if action == DictionaryAction.QUERY:
return "query_word"
elif action == DictionaryAction.TRANSLATE:
return "translate_text"
elif action == DictionaryAction.EXTRACT:
return "extract_terms"
elif action == DictionaryAction.DAILY_WORD:
return "get_daily_word"
elif action == DictionaryAction.LOOKUP_WORD_BOOK:
return "lookup_word_book"
elif action == DictionaryAction.ADD_TO_WORD_BOOK:
return "add_to_word_book"
else:
return "format_result"
return state

View File

@@ -164,5 +164,22 @@ def format_result(state: NewsAnalysisState) -> NewsAnalysisState:
state.final_result = "\n".join(output_lines)
state.success = True
state.current_phase = "completed"
return state
def should_continue(state: NewsAnalysisState) -> str:
"""
条件路由函数:根据 action 决定下一个节点
"""
action = state.action
if action == NewsAction.QUERY:
return "query_news"
elif action == NewsAction.ANALYZE_URL:
return "analyze_url"
elif action == NewsAction.EXTRACT_KEYWORDS:
return "extract_keywords"
elif action == NewsAction.GENERATE_REPORT:
return "generate_report"
else:
return "format_result"