一.项目

1.1 项目定位

EmailAgent(MailFriend)是一个基于 LangGraph AgentMiddleware 的智能邮件助手系统,核心目标是:

通过自然语言对话完成邮箱认证、收件检查、邮件发送

演示 LangGraph 中间件机制(动态工具选择 + 动态提示词切换)

提供类 ChatGPT 的 SSE 流式交互体验

1.2 技术栈

层级 技术选型 版本/配置
LLM DashScope qwen3.7-plus OpenAI 兼容模式
Agent 框架 LangGraph create_agent + AgentMiddleware langchain>=1.3.14
Web 框架 FastAPI + uvicorn fastapi>=0.141.1
前端 原生 HTML/CSS/JS(无框架) SSE + ReadableStream
数据库 SQLite 3 sessions + messages 两表
Checkpointer InMemorySaver 不跨重启持久化
可观测性 LangSmith Tracing 已接入

1.3 核心功能(当前全为 mock)

# 功能 工具函数 当前实现 真实需要
1 邮箱认证 authenticate(email, password) 硬编码 xxx@qq.com/123456 数据库查询 + bcrypt 哈希
2 检查收件箱 check_email() 固定返回 "No new emails" IMAP 协议拉取真实邮件
3 发送邮件 send_email(email, subject, body) 固定返回 "Email sent successfully" SMTP 协议真实发送

1.4 项目效果

二.问题解决汇总

核心问题详解:

2.1 会话发起无响应

SSE 无回应 — 后端三个叠加 Bug

修改前

# Bug 1 — 错误 key
event_type = chunk.get("event_type")  # 永远 None

# Bug 2 — yield dict
yield {"event": "message", "data": payload}

# Bug 3 — 路由内 new
@router.post("/stream")
async def chat_stream(request):
    agent = EmailAgent()
    return StreamingResponse(agent.generate_sse(...))

2.1.1 chunk key 混淆

LangGraph v2 的 stream chunk 结构为:

{"type": "messages"|"updates", "ns": [...], "data": ...}

最初代码用 chunk.get("event_type") 取事件类型,但正确的 key 是 typeevent_type 永远返回 None,所有 chunk 都被跳过。

2.1.2 yield 格式不符合 SSE 规范

FastAPI StreamingResponse 期望的是字符串/字节。yield dict 后被 str() 转成 {'event': 'message', ...}(Python repr 格式),前端 JSON.parse 全部失败。

2.1.3 路由每次新建空实例

EmailAgent() 是空壳——self.agent 和 self.checkpointer 都是 None。虽然 generate_sse 内部有 if not self.agent: await self.init() 兜底,但每次请求都重新初始化意味着 checkpointer 不共享、对话状态不保留。

修改后

# Bug 1 — 正确 key
event_type = chunk.get("type")  # "messages" | "updates"

# Bug 2 — yield SSE 格式字符串
yield f"data: {json.dumps({'event': 'message', 'data': payload}, ensure_ascii=False)}\n\n"

# Bug 3 — 使用 lifespan 单例
from app.agents.email_agent import email_agent  # 模块级单例

@router.post("/stream")
async def chat_stream(request: ChatRequest):
    return StreamingResponse(
        email_agent.generate_sse(
            thread_id=request.thread_id,
            message=request.message or "",
            interrupt_decision=request.interrupt_decision,
        ),
        media_type="text/event-stream",
    )

2.2 电子邮件密码均正确但未收到回复

原本使用thinking 模型延迟 40s+ → 首响应极慢

模型 首 token 延迟 适用场景 决策
qwen3-vl-32b-thinking 20-40s 深度推理、代码生成 ❌ 不适合 SSE 聊天
qwen3.7-plus ~2s 通用对话、指令跟随 ✅ 选定
qwen-plus ~1s 轻量对话 备选

2.3 邮件显示成功发送,但实际该邮箱并未收到

架构机制是成品,业务功能是空壳。

Middleware 动态工具选择 + 动态提示词 + SSE 流式三件套已跑通,但 authenticate/check_email/send_email 三个核心工具全是 mock,需要分别接入数据库认证、IMAP、SMTP 才能真正可用。

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐