Replies: 3 comments
|
Excellent causal-chain analysis — I independently verified every link against alpha.2 ( All three source claims confirmed.
The precise piece worth noting: the writer-side choke point is the shared root. This is the same identity-loss family as #5247 (duplicate
This matters because a single fix should not blur them:
Suggested small regression test: feed two 整体判断:你的因果链完全成立,而且这正好暴露了 harness 在"LLM 回传 id 不可信"这一层缺少一个 dedup 卫兵—— |
|
这个分析我基本同意,尤其是 writer-side 是共同 choke point 这一点。 不过我觉得这里可能还能再往下拆一层:问题不只是缺一个 duplicate-id guard,而是现在 现在大致是: 也就是说,一个来自 provider 的外部 ID,直接变成了 Harness 内部的 canonical invocation identity。 这次 GLM 的 same-response duplicate 把这个假设打破了,但 #5247 的 cross-turn reuse、#5182 的 empty id、#4427 的 stream-index reuse,我感觉其实都在说明同一个更基础的问题:
我更倾向于把它拆成至少两层: stream 这样即使 provider 返回: Harness 仍然可以得到: 两次调用在内部从一开始就是不同事件,而不是等 reader 发现冲突以后再容错。 所以我赞成在 writer / assembler boundary 修,但可能会比: 再多走一步:把 external provider ID 和 internal invocation ID 正式分离。
一个 regression test 我会再加一层: 这样测试锁住的就不只是 GLM 这个具体异常,而是「LLM/provider 回传 identity 不可信,Harness 自己负责内部 identity」这个边界。 当然还有一个 provider-protocol 细节需要单独处理:如果下一次请求必须把 tool result 关联回 provider 的原始 call id,那么 re-key 不能简单覆盖原始值;这也正是把两个 ID 分开的理由。 |
|
你这个 layer 站得住,我同意把 我这边补充三个实现层面的约束,可能是这个设计真正要预算的成本: 1. 这是 session event schema 的 breaking change,不是纯 writer 内部改动。 当前 'tool/call': { turn: number; step: number; callId: ToolCallId; name: string; arguments: string }
2. 两条 id 各自的正确性边界要划清楚。
3. 重放一致性 + 迁移是隐藏成本。 回归测试建议(在你那句之上再锁一层): 第 4 条是把"格式改动不破坏重放"也钉住,否则只锁住 writer 生成、没锁住 reader 回放。 整体判断:分离是正确方向, |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
我的场景 确实 需要 大模型 一次response多次调用同一个工具,但是工具参数是不同的,这应该被当成不同的 工具调用,目前看起来无法被区分开 进而导致界面异常
错误链路:
LLM 生成重复的 tool call ID:maas-glm-5.2-aliyun 在同一个 response 中对同名工具返回了相同的 callId(如 call_a947292...|fc_call_a947292...)
dsh 记录了重复的 tool/call 事件:tool-calls.ts 的 appendToolCall() 直接用 block.id(来自 LLM)作为 callId 写入 session 事件流
ConversationNodeAssembler.replaceWindow() 崩溃:trajectory-tool-definition.ts 的 match() 函数对每个 tool/call 事件返回
{ id: callId, role: 'start' }。当第二个相同 callId 的 tool/call 到达时,acceptMatch() 发现 context.start !== undefined,抛出:conversation Context ... received more than one start Match
整个对话窗口替换失败:replaceWindow() 抛出后,BoundConversation.replace() → MutableSessionEventSource.publish() 全链路失败,UI 没有任何
conversation node 可渲染。
经过深入探索 D:\ai\deepseek-harness 代码,确认了完整的因果链:
All reactions