当前位置: 首页 > news >正文

langgraph sse 用法

目录
  • 一、语法层面:Python 允许函数内定义函数(包含 async)
  • 二、运行时语义:这是一个「闭包 + 工厂函数」模式
    • 1️⃣ event_stream 不是立即执行的
    • 2️⃣ 为什么要嵌套,而不是单独定义?
    • 3️⃣ 如果不嵌套,会发生什么?
  • 三、在 FastAPI + SSE 中,这是「惯用模式」
    • FastAPI 官方与社区常见写法
  • 四、从设计角度看,你的写法是「高质量的」
    • 这是一种明确的设计边界
  • 五、再强调一次:这不是“偷懒写法”,而是刻意设计
  • 一句话总结

这是 Python 的语言特性,而且在你这段代码里,嵌套 async def 是一个非常合理、工程上正确的设计选择。下面我从「语法层面 → 运行时语义 → 为什么在 FastAPI + SSE 中尤其常见」三个层次解释。


一、语法层面:Python 允许函数内定义函数(包含 async)

在 Python 中:

  • def 可以出现在任何可执行作用域
  • async def 本质上仍然是函数定义,只是返回 协程函数
  • 因此:
async def outer():async def inner():...

完全合法的

这和 Java / Go 不同,Python 是支持闭包(Closure)的动态语言。


二、运行时语义:这是一个「闭包 + 工厂函数」模式

关键点在于这一句:

return StreamingResponse(event_stream(),media_type="text/event-stream",
)

1️⃣ event_stream 不是立即执行的

event_stream()

返回的是一个:

AsyncIterator[str](异步生成器)

它会在 FastAPI / ASGI 框架真正开始向客户端写数据时 才被消费。


2️⃣ 为什么要嵌套,而不是单独定义?

因为 event_stream 天然依赖外部上下文变量

外部变量 来源
request HTTP 请求体
thread_id 本次请求生成
last_content 请求最后一条消息
langfuse trace 与当前请求绑定
logger / callback 请求级上下文

这些变量:

thread_id
last_content
request
lf_callback
langfuse

event_stream 内部直接可用,因为:

Python 会把它们捕获为 闭包变量

这是一个非常标准的闭包模式


3️⃣ 如果不嵌套,会发生什么?

你只能写成这样:

async def event_stream(request, thread_id, last_content, ...):...

然后在外部:

return StreamingResponse(event_stream(request, thread_id, last_content, ...),
)

这会带来几个问题:

  1. 参数极多,接口污染
  2. SSE 是强请求绑定逻辑,却变成“公共函数”
  3. trace / callback / logger 很容易被误用成全局态
  4. 可读性显著下降

三、在 FastAPI + SSE 中,这是「惯用模式」

你这段代码本质是:

“为当前 HTTP 请求,动态生成一个只属于它的异步事件流函数”

这是 SSE 的本质需求。

FastAPI 官方与社区常见写法

@app.get("/stream")
async def stream():async def event_generator():for i in range(10):yield f"data: {i}\n\n"await asyncio.sleep(1)return StreamingResponse(event_generator())

你现在做的只是 工程级加强版

  • 多 Agent Graph
  • LangGraph astream
  • Langfuse trace
  • SSE 多事件类型

四、从设计角度看,你的写法是「高质量的」

这是一种明确的设计边界

层级 职责
customer_service_chat HTTP 入口 / 参数校验 / Response 封装
event_stream 本次请求的 执行生命周期
Graph / Agent 业务执行

event_stream生命周期 == 一个 HTTP 连接

这点用嵌套函数表达得非常清楚。


五、再强调一次:这不是“偷懒写法”,而是刻意设计

你这里用嵌套 async def,实际上同时实现了:

  • 闭包(request-scope state)
  • 请求隔离
  • 避免全局状态污染
  • SSE 延迟执行
  • Langfuse trace 正确归属

高并发 + 流式 + 可观测性 场景下,这是推荐做法


一句话总结

customer_service_chat 里嵌套定义 event_stream,是利用 Python 的闭包机制,为每个 HTTP 请求动态创建一个只属于它的异步事件流执行器

在 FastAPI + SSE + LangGraph + Langfuse 这种架构下,这是正确、清晰、可维护的工程实践,而不是语法“怪招”。

如果你愿意,下一步我可以帮你 判断这个 @observe 放在 event_stream 上是否是最佳位置,以及 root trace 是否如你预期那样工作

http://www.jsqmd.com/news/119072/

相关文章:

  • Excalidraw支持哪些导出格式?PNG/SVG/JSON全解析
  • JavaSE——运算符优先级
  • 在上海,如何选择靠谱的防水补漏服务?一份避坑参考 - shruisheng
  • 你真的会导出AutoGLM配置吗?:8个必须掌握的操作要点一次讲清
  • Jupyter是什么?如何安装使用?
  • Open-AutoGLM配置导出全流程解析(从入门到生产级落地)
  • 【攻防世界】reverse | BABYRE 详细题解 WP
  • 为什么你的手势识别总延迟?Open-AutoGLM缩放参数调优指南
  • 为什么90%的Open-AutoGLM部署缺乏有效恢复能力?真相令人震惊
  • Open-AutoGLM部署避坑指南:99%新手都会忽略的3大核心配置
  • 9.23
  • Open-AutoGLM操作手册导出实战指南(99%工程师忽略的核心细节)
  • 13.2 进阶篇:多智能体协作系统设计与实现
  • Vue响应式数据全解析:从Vue2到Vue3,ref与reactive的实战指南
  • 技术文档配图难?试试Excalidraw手绘风格解决方案
  • Excalidraw移动端体验如何?iOS/Android使用评测
  • stm32f103学习笔记-17-STM32 中断应用总结 - 实践
  • 【探索实战】从0到1精通Kurator:分布式云原生平台实战教程
  • GB∕T8446.2-2022电力半导体器件用散热器 第2部分:热阻和流阻测量方法
  • 20251220 - LCA 总结
  • Open-AutoGLM加密存储调优全攻略(从入门到生产级部署)
  • 【限时掌握】Open-AutoGLM新手引导配置:3天内完成项目部署的秘密
  • 14.1 产品设计全流程:从概念到上线的标准作业程序
  • Open-AutoGLM数据保护全链路方案(从备份到自动恢复的实践指南)
  • 揭秘Open-AutoGLM自动化部署:如何5步实现文档智能生成
  • 揭晓2025年:用户评选出的高位货架十大放心品牌,库房仓储货架厂家哪家好/库房货架价钱/家庭库房货架高位货架生产厂家推荐排行榜单 - 品牌推荐师
  • 师夷长技以制夷,二角破壁,五分普惠,AI当雄于地球,今日之责任,不在他人,全在我少年开发者!
  • Open-AutoGLM推理延迟高?:4种优化路径+实测数据对比,立竿见影降本30%
  • 本地数据加密太慢?Open-AutoGLM优化技巧,让你的系统提速8倍
  • Excalidraw安全性分析:数据是否真的本地存储?