mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-11-05 16:57:32 +00:00
## 设计口径(用户裁定,2026-11-03)
「我的设计是 l1 渲染出来就是传统式的上下文排列,
难怪指代消解能力这么差」
## 之前错在哪
buildMessages 把**全部历史事件拼成一条 system 消息**:
system: 系统提示词
system: [Conversation timeline]
[15:04:05] 用户: 帮我找月租<400的房子
[15:04:05] 助手: ...
[15:04:05] 工具(qq_get_message): ...
user: 当前输入
说话人身份靠**文本前缀**表达。模型对它拿到的是"背景资料"式的注意力
结构,而不是"我说过的对话"——指代消解因此失效(用户回"新乡"接不上
上一句"帮我找月租<400…")。
★ 0f98f36 那次只改了**文本渲染格式**(把日志样式换成对话样式),
底层"一条 system 承载全部历史"的结构一动没动,所以问题还在。
## 现在的形态
system 系统提示词
user 帮我找一套月租<400 水电常价带独卫的单间
assistant 好的,我去找。
user 新乡
assistant 新乡这边有几套。
user 当前输入
工具轮按协议展开:
user 帮我看看天气
assistant (content + tool_calls=[c1,c2])
tool (tool_call_id=c1) 晴 26 度
tool (tool_call_id=c2) 他说新乡
user 继续
实现要点:
- 新增 renderL1Messages:一个 ContextEvent 展开为
user → assistant(calls) → tool... 消息;
- tool_call 与 tool 按 CallID 严格配对(CallID 优先,缺失退化到工具名);
- InactivePages 剔除**完整的工具页**:assistant 上对应的 tool_call 与
紧随的 tool 消息一起消失,绝不留下"有 call 无 result"(上游必 400);
- 超长工具结果仍渲染为句柄(toolresult_read 取回);
- 保留 timelineUserText 的中断轮处理:从聊天工具回执里取真实原话,
不让注入样板冒充用户发言;
- 保留 token 预算裁剪,事件级按消息粒度计入。
## 清理(无生产调用方的旧渲染路径)
删除:
- formatMergedTimeline(旧 system-timeline 唯一生产者)
- renderedToolResultsOf(旧截断风格渲染,已被原生序列取代)
- timelineToolLines(仅上面两者使用)
- timelineUserLabel / timelineAssistantLabel
- toolResultTimelineChars / toolResultTimelineCharsChat /
toolResultTimelineMax / isChatCorpusTool
删除对应已失效判据:timeline_contract_test.go、timeline_toolresult_test.go
保留 toolResultPageIndex:overflow.go 的 eventTokens 仍在用,
且统计侧与渲染侧必须共用同一份配对规则(否则"渲染少了、统计没少"
会让裁剪永远裁不动,2026-11-02 实测事故)。
## 判据(新增,均已变异验证)
l1_native_sequence_test.go:
- TestL1RendersNativeMessageSequence
断言 role 序列 system/user/assistant/user/assistant/user,
且 system 消息中不得再出现 "[Conversation timeline]" 或 "用户:"
- TestL1ExpandsToolCallsAsPairedMessages
断言 assistant.ToolCalls[i].ID 与紧随 tool.ToolCallID 一一配对
- TestL1InactivePageDropsWholePair
剔除页时 call 与 result 必须同时消失
变异验证:把实现退回旧 system-timeline ⇒ 三条全红,恢复后全绿。
## 验证
go build ./... → 0
go vet ./... → 0
gofmt -l internal/ → 干净
go test ./... -count=1 -race → 62 ok / 0 FAIL / 0 DATA RACE