news 2026/8/16 22:30:54

【项目篇】EmailAgent汇总

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【项目篇】EmailAgent汇总

一.项目

1.1 项目定位

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

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

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

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

1.2 技术栈

层级技术选型版本/配置
LLMDashScope qwen3.7-plusOpenAI 兼容模式
Agent 框架LangGraph create_agent + AgentMiddlewarelangchain>=1.3.14
Web 框架FastAPI + uvicornfastapi>=0.141.1
前端原生 HTML/CSS/JS(无框架)SSE + ReadableStream
数据库SQLite 3sessions + messages 两表
CheckpointerInMemorySaver不跨重启持久化
可观测性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 规范

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

2.1.3 路由每次新建空实例

EmailAgent()是空壳——self.agentself.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-thinking20-40s深度推理、代码生成❌ 不适合 SSE 聊天
qwen3.7-plus~2s通用对话、指令跟随✅ 选定
qwen-plus~1s轻量对话备选

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

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

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/16 22:28:28

个人博客建站

为什么改用 Astro 原本的博客基于 Vue 3 FastAPI,有完整的后台管理、评论系统、GitHub OAuth 登录。随着功能的添加,维护成本变高:服务器成本、数据库备份、依赖升级……于是决定改造成纯静态站。 核心改造点 内容源:从 MySQL…

作者头像 李华
网站建设 2026/8/16 22:26:24

Failed to take /etc/passwd lock: Invalid argument解决方案

在 x86 宿主机上构建 ARM64 Ubuntu 24.04 rootfs 时遇到 Failed to take /etc/passwd lock: Invalid argument 的完整解决记录 一、问题现象 环境: 宿主机:VMware Ubuntu 20.04(x86_64,内核 6.6) 构建方式&#xff…

作者头像 李华
网站建设 2026/8/16 22:24:40

Go语言AI Agent极致压缩:从编译优化到容器化部署的工程实践

1. 项目缘起:为什么我们需要一个“极致压缩”的AI Agent?最近在折腾AI Agent,发现一个挺有意思的现象:很多开源项目,功能确实强大,但一上手,资源占用就让人头疼。动辄几个G的内存,启…

作者头像 李华
网站建设 2026/8/16 22:21:13

题解:AtCoder AT_awc0125_a Warehouse Package Inspection

本文分享的必刷题目是从蓝桥云课、洛谷、AcWing等知名刷题平台精心挑选而来,并结合各平台提供的算法标签和难度等级进行了系统分类。题目涵盖了从基础到进阶的多种算法和数据结构,旨在为不同阶段的编程学习者提供一条清晰、平稳的学习提升路径。 欢迎大…

作者头像 李华
网站建设 2026/8/16 22:20:53

AI时代程序员转型:从编码到架构与协作的核心能力重塑

1. 从“码农”到“AI协作者”:一场静默的范式转移最近和几个老同事吃饭,聊起一个挺有意思的现象:十年前,我们这帮人聚在一起,话题离不开“哪个框架性能更好”、“怎么解决高并发”、“数据库索引又调优了”。现在呢&am…

作者头像 李华