Skip to content

[Bug]: astream_events(version="v2") 中导致 SSE updates 事件重复 #48

Description

@LiangMuYuan

Describe the bug

使用 graph.astream_events(version="v2") 时,通过 Send() 启动的并行节点产生的 on_chain_stream 事件中,data.chunk 同时存在两种格式:元组格式 ("updates", {"node_name": data}) 和裸 dict 格式 {"field": data}execute_run 中有两条独立的处理路径分别处理这两种格式,各自调用 apublish_updates_event(),导致同一个节点的输出在 SSE 流中出现两次 event: updates

涉及代码位置

services/run_executor.pyexecute_run() 函数中的 on_chain_stream 处理:

  • 元组路径:处理 ("updates", {"node_name": data})
  • 裸 dict 兜底路径:处理 {"field": data} ← 重复源

Environment

agentseek-api version: 0.1.0
python: 3.12
langgraph: 1.2.1

Fast reproduce steps

  1. 部署一个包含 Send() 并行节点的 LangGraph 应用,某节点返回结构化输出
  2. 调用 /threads/{id}/runs/streamstream_mode=["updates", "messages"]
  3. 观察 SSE 响应中的 event: updates

Expected behavior

每个 Send() 节点的输出在 SSE 流中只出现一次 event: updates,格式与 langgraph-api 一致:{"node_name": {"field": data}}

Actual behavior

同一个节点的输出出现两次 event: updates

event: updates
data: {"templates": {"templates": []}}        ← 字段级(裸 dict 路径)
event: updates
data: {"extract_templates": {"templates": {...}}}  ← 节点级(元组路径,重复)

Additional context

根因: astream_events(version="v2") 对同一个 Send() 节点输出同时触发了内部 astream() 回调(产生 ("updates", data) 元组)和节点输出回调(产生裸 dict)。代码没有过滤重复。

修复建议(二选一):

方案 A——切换为 graph.astream(),与 langgraph-api 对 /threads/{id}/runs/stream 端点的处理一致:

# Before
async for stream_event in graph.astream_events(invocation, config, version="v2"):
    ...

# After
async with aclosing(graph.astream(invocation, config)) as stream:
    while True:
        mode, chunk = await anext(stream, sentinel)
        ...

方案 B——保留 astream_events,删除裸 dict 兜底路径,仅保留元组路径(我未成功)。

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions