Version: 0.9.13.dev.260410
后端: 1. Memory Day1 链路打通(chat_history -> outbox -> memory_jobs) - 更新 service/events/chat_history_persist.go:聊天消息落库同事务追加 memory.extract.requested 事件(仅 user 消息,失败回滚后由 outbox 重试) - 新建 service/events/memory_extract_requested.go:消费 memory.extract.requested 并幂等入队 memory_jobs,补齐 payload 校验、文本截断与 idempotency key - 更新 cmd/start.go:注册 RegisterMemoryExtractRequestedHandler 2. Memory 模块骨架落地(先跑通状态机,再接入真实抽取) - 新建 memory/model、repo、service、orchestrator、worker、utils 目录与 Day1 mock 抽取执行链 - 新建 model/memory.go:补齐 memory_items / memory_jobs / memory_audit_logs / memory_user_settings 与事件 payload 模型 - 更新 inits/mysql.go:接入 4 张 memory 相关表 AutoMigrate 3. RAG 复用基础设施预埋(依赖可替换) - 新建 infra/rag:core pipeline + chunk/embed/retrieve/rerank/store/corpus/config 分层实现 - 默认接入 MockEmbedder + InMemoryStore,预留 Milvus / Eino 适配实现 - 新增 infra/rag/RAG复用接口实施计划.md 4. 本地依赖与交接文档同步 - 更新 docker-compose.yml:新增 etcd / minio / milvus / attu 服务与数据卷 - 删除 newAgent/HANDOFF_工具研究与运行态重置.md、newAgent/阶段3_上下文瘦身设计.md - 新增 newAgent/HANDOFF_WebSearch两阶段实施计划.md、memory/HANDOFF-RAG复用后续实施计划.md、memory/README.md 前端:无 仓库:无
This commit is contained in:
142
backend/newAgent/HANDOFF_WebSearch两阶段实施计划.md
Normal file
142
backend/newAgent/HANDOFF_WebSearch两阶段实施计划.md
Normal file
@@ -0,0 +1,142 @@
|
||||
# WebSearch 两阶段实施计划(newAgent)
|
||||
|
||||
## 1. 目标与范围
|
||||
|
||||
本文用于把 `newAgent` 的 WebSearch 能力按两阶段落地:
|
||||
|
||||
1. 第一阶段:先接入可用的检索与抓取能力(低风险、快交付)。
|
||||
2. 第二阶段:在第一阶段基础上升级为 WebRAG 语义召回链路(提升复杂问题命中率与可解释性)。
|
||||
|
||||
约束:
|
||||
|
||||
1. 不走 `infra/smartflow-mcp-server`,直接走 `newAgent/tools` 工具注册链路。
|
||||
2. 保持现有执行模式不变:读操作 `action=continue + tool_call`。
|
||||
3. 第一阶段只接单供应商;第二阶段再考虑 provider fallback。
|
||||
|
||||
---
|
||||
|
||||
## 2. 第一阶段(V1):WebSearch + 简单抓取
|
||||
|
||||
### 2.1 交付目标
|
||||
|
||||
让模型可以:
|
||||
|
||||
1. 通过 `web_search` 获得结构化检索结果(标题、摘要、URL、来源域名、时间)。
|
||||
2. 通过 `web_fetch` 拉取指定 URL 正文并做最小清洗。
|
||||
3. 在不改主流程的前提下,把结果作为标准 `tool observation` 写回历史。
|
||||
|
||||
### 2.2 计划新增工具
|
||||
|
||||
1. `web_search`
|
||||
- 输入:`query`、`top_k`、`domain_allow`、`recency_days` 等。
|
||||
- 输出:JSON 字符串(`tool`、`query`、`count`、`items[]`)。
|
||||
2. `web_fetch`
|
||||
- 输入:`url`、`max_chars`。
|
||||
- 输出:JSON 字符串(`tool`、`url`、`title`、`content`、`truncated`)。
|
||||
|
||||
### 2.3 代码落点
|
||||
|
||||
新增文件:
|
||||
|
||||
1. `backend/newAgent/tools/web_tools.go`:工具参数解析、输出组装、错误兜底。
|
||||
2. `backend/newAgent/tools/web_provider.go`:搜索供应商抽象接口与通用数据结构。
|
||||
3. `backend/newAgent/tools/web_provider_tavily.go`(或 `web_provider_brave.go`):首个 provider 实现。
|
||||
4. `backend/newAgent/tools/web_fetcher.go`:URL 抓取与 HTML 最小清洗。
|
||||
|
||||
修改文件:
|
||||
|
||||
1. `backend/newAgent/tools/registry.go`:注册 `web_search`、`web_fetch` 两个读工具。
|
||||
2. `backend/cmd/start.go`:初始化 provider 配置并注入 registry(或通过包级配置读取)。
|
||||
3. `backend/newAgent/prompt/execute_context.go`:补充新工具的 schema 说明与示例。
|
||||
|
||||
### 2.4 V1 验收标准
|
||||
|
||||
1. 模型能稳定调用 `web_search` 并拿到可解析 JSON 结果。
|
||||
2. `web_fetch` 在正文可达时返回正文,在失败时返回明确错误码与原因。
|
||||
3. 工具超时、429、5xx 均不会打断主流程,只返回可恢复 observation。
|
||||
4. 日志可定位:query、tool、耗时、结果数、失败原因。
|
||||
|
||||
---
|
||||
|
||||
## 3. 第二阶段(V2):WebRAG 语义召回
|
||||
|
||||
### 3.1 交付目标
|
||||
|
||||
新增 `web_rag_search`,把“检索 + 抓取 + 分块 + 召回 + 重排 + 证据返回”收敛为一个读工具,提升复杂问答质量。
|
||||
|
||||
### 3.2 链路设计
|
||||
|
||||
1. 查询改写:把用户问题改写为 1~3 个检索子查询。
|
||||
2. WebSearch 召回:拿到候选 URL 集合。
|
||||
3. 抓取清洗:抽正文,去噪。
|
||||
4. 分块:按段落与 token 预算切块。
|
||||
5. 召回:向量召回 + 关键词召回(混合召回)。
|
||||
6. 重排:按 query 相关性重排 chunk。
|
||||
7. 输出:返回答案所需证据片段、来源 URL、片段得分。
|
||||
|
||||
### 3.3 代码落点
|
||||
|
||||
新增文件:
|
||||
|
||||
1. `backend/newAgent/tools/web_rag_tools.go`:`web_rag_search` 工具入口。
|
||||
2. `backend/newAgent/tools/web_rag_chunker.go`:清洗后分块。
|
||||
3. `backend/newAgent/tools/web_rag_retriever.go`:混合召回。
|
||||
4. `backend/newAgent/tools/web_rag_rerank.go`:重排层。
|
||||
5. `backend/newAgent/tools/web_rag_store.go`:会话级索引缓存(先内存/Redis TTL)。
|
||||
|
||||
修改文件:
|
||||
|
||||
1. `backend/newAgent/tools/registry.go`:注册 `web_rag_search`。
|
||||
2. `backend/newAgent/prompt/execute_context.go`:增加 `web_rag_search` 使用规范。
|
||||
|
||||
### 3.4 V2 验收标准
|
||||
|
||||
1. 同类复杂问题下,回答引用质量和相关性明显高于 V1。
|
||||
2. 返回至少包含:`answer_evidence[]`(片段+URL+score)。
|
||||
3. 召回或重排失败时可降级到 V1(`web_search + web_fetch`)路径。
|
||||
4. 提供基础评估指标:命中率、延迟、成本、失败率。
|
||||
|
||||
---
|
||||
|
||||
## 4. 与记忆系统的关系
|
||||
|
||||
`WebRAG` 与记忆系统 RAG 高度重合,建议“共用内核、分语料适配”:
|
||||
|
||||
1. 共用:chunk / embed / retrieve / rerank 的通用接口与实现。
|
||||
2. 分开:`MemoryCorpus`(私有数据)与 `WebCorpus`(公网数据)的数据源适配层。
|
||||
3. 在工具层保持两个入口:`memory_search` 与 `web_rag_search`,返回结构尽量统一。
|
||||
|
||||
---
|
||||
|
||||
## 5. 上线顺序与回滚策略
|
||||
|
||||
### 5.1 上线顺序
|
||||
|
||||
1. 先灰度 V1:仅开放 `web_search`、`web_fetch`。
|
||||
2. 观察稳定性与成本后再灰度 V2:`web_rag_search`。
|
||||
3. V2 稳定后再考虑 provider fallback 与更长周期缓存。
|
||||
|
||||
### 5.2 回滚策略
|
||||
|
||||
1. `web_rag_search` 异常时,快速降级为 V1 工具集。
|
||||
2. V1 供应商异常时,返回“检索暂不可用”的结构化 observation,不阻断主流程。
|
||||
3. 保留 feature flag:按工具级别开关,支持秒级关闭。
|
||||
|
||||
---
|
||||
|
||||
## 6. 风险清单
|
||||
|
||||
1. 供应商配额/限流导致查询失败。
|
||||
2. 页面反爬与正文抽取质量不稳定。
|
||||
3. RAG 链路成本上升(抓取+embedding+重排)。
|
||||
4. 引用片段与最终答案不一致(需要强制证据对齐策略)。
|
||||
|
||||
---
|
||||
|
||||
## 7. 里程碑建议
|
||||
|
||||
1. M1(1~2 天):V1 工具跑通,联调 Execute 节点可调用。
|
||||
2. M2(2~4 天):V1 稳定性优化(超时/限流/日志/错误码)。
|
||||
3. M3(4~7 天):V2 WebRAG MVP(混合召回+基础重排+证据输出)。
|
||||
4. M4(后续):统一 RAG Core,打通记忆系统复用。
|
||||
|
||||
@@ -1,814 +0,0 @@
|
||||
# Handoff(工具研究与运行态重置)
|
||||
|
||||
以下内容可直接交给下一位助理继续做。
|
||||
|
||||
本文档更新时间:2026-04-08
|
||||
|
||||
## 0. 当前结论先说清
|
||||
|
||||
当前可以明确分成三段看:
|
||||
|
||||
1. 第 1-2 阶段已完成
|
||||
粗排链路和 `abort -> deliver` 正式终止协议已打通,真实链路已验证可跑。
|
||||
|
||||
2. 第 3 阶段第一版已落地
|
||||
`execute` 上下文已改成固定 4 消息结构,并接入当轮 ReAct 窗口压缩(按工具去重保留最新 observation);
|
||||
工具结果在执行链路中已改为不截断,prompt 也已加硬约束(JSON、参数名、读写动作、重复读约束等)。
|
||||
|
||||
3. 当前主矛盾已转移到“工具收敛能力”
|
||||
最新日志显示:不是上下文失控,而是工具输出对“何时停止微调”支持不足,导致模型持续 `list_tasks/find_first_free/move` 小步循环。
|
||||
|
||||
一句话总结:
|
||||
|
||||
- 粗排和执行框架已经能跑;
|
||||
- 上下文瘦身第一版已经到位;
|
||||
- 下一棒应优先改工具层的“冲突表达 + 候选位质量 + 结束判据”,而不是再回头补粗排。
|
||||
|
||||
---
|
||||
|
||||
## 1. 用户已经明确确认的业务语义
|
||||
|
||||
这些结论已经和用户对齐,后续不要再摇摆:
|
||||
|
||||
1. 第一轮实现优先参考旧 agent 链路,不能闭门造车。
|
||||
|
||||
2. 对排程场景来说,LLM 的角色是“粗排后的优化器”,不是“粗排漏排后的人工补排器”。
|
||||
|
||||
3. 如果粗排完成后仍有真实 `pending` 任务,这不是正常状态,而是异常状态。
|
||||
正确处理是:
|
||||
- 直接终止本轮
|
||||
- 明确报错
|
||||
- 不再引导 LLM 去一个个 `place`
|
||||
|
||||
4. `always_execute`、是否自动放行、是否写库,这些都是后端执行层语义,不应该写进 prompt 让 LLM 判断。
|
||||
|
||||
5. prompt 必须可插拔,不能写死成“排程专用 prompt”。
|
||||
|
||||
6. prompt 必须保留明确编号结构,例如 `1. / 1.1 / 2.1`,不能写成一坨说明文。
|
||||
|
||||
7. prompt 里要保留最小可用 JSON 示例,否则 LLM 很容易输出跑偏。
|
||||
|
||||
---
|
||||
|
||||
## 2. 第 1 阶段:粗排链路修复,已完成
|
||||
|
||||
### 2.1 已完成的核心修复
|
||||
|
||||
#### A. 粗排结果来源修正
|
||||
|
||||
位置:
|
||||
|
||||
- `backend/service/agentsvc/agent_newagent.go`
|
||||
|
||||
已做:
|
||||
|
||||
- `makeRoughBuildFunc()` 不再只看 `[]TaskClassItem`
|
||||
- 改为使用 `HybridScheduleWithPlanMulti()` 返回的 `[]HybridScheduleEntry`
|
||||
- 只提取 `status="suggested"` 且 `task_item_id>0` 的条目
|
||||
|
||||
意义:
|
||||
|
||||
- 旧问题是:只会拿到有 `EmbeddedTime` 的一部分结果,普通 suggested 条目会丢
|
||||
- 现在粗排 placement 来源和旧 agent 主链路一致
|
||||
|
||||
#### B. 作用域修正:只按本轮 `task_class_ids` 看 pending
|
||||
|
||||
位置:
|
||||
|
||||
- `backend/newAgent/tools/status.go`
|
||||
- `backend/newAgent/model/graph_run_state.go`
|
||||
- `backend/newAgent/node/rough_build.go`
|
||||
|
||||
已做:
|
||||
|
||||
- 新增按 `task_class_ids` 判断 task 是否属于本轮范围
|
||||
- `EnsureScheduleState()` 会对 `ScheduleState` / `OriginalScheduleState` 做域内裁剪
|
||||
- `countPendingTasks()` 只统计本轮任务类范围内的真实 pending
|
||||
|
||||
意义:
|
||||
|
||||
- 修掉“用户所有任务类的 pending 被误算进本轮粗排结果”的问题
|
||||
|
||||
#### C. 窗口修正:ScheduleState 的 DayMapping 改为优先按本轮任务类加载
|
||||
|
||||
位置:
|
||||
|
||||
- `backend/newAgent/model/state_store.go`
|
||||
- `backend/newAgent/model/graph_run_state.go`
|
||||
- `backend/conv/schedule_provider.go`
|
||||
|
||||
已做:
|
||||
|
||||
- 新增可选接口 `ScopedScheduleStateProvider`
|
||||
- `AgentGraphState.EnsureScheduleState()` 首次加载时,若 provider 支持 scoped 加载,则优先走 `LoadScheduleStateForTaskClasses()`
|
||||
- `ScheduleProvider` 实现了按本轮 `task_class_ids` 精确加载 `ScheduleState`
|
||||
- `buildWindowFromTaskClasses()` 改成逐个任务类做日期转换,坏日期/超学期日期会被忽略,不再把整轮窗口拖坏
|
||||
|
||||
这次修的是一个真实 bug:
|
||||
|
||||
- 用户真实日志里曾出现:
|
||||
- `placements=44`
|
||||
- `pending_in_scope=44`
|
||||
- 这说明 placement 已经出来了,但一个都没写回 state
|
||||
- 根因不是粗排没算出来,而是 `DayMapping` 窗口被全量任务类脏日期污染,导致 `WeekDayToDay()` 映射失败
|
||||
|
||||
现在这个问题已经修掉,用户已确认“粗排跑通了”。
|
||||
|
||||
#### D. 粗排落位语义改成 `suggested`
|
||||
|
||||
位置:
|
||||
|
||||
- `backend/newAgent/node/rough_build.go`
|
||||
- `backend/newAgent/tools/read_tools.go`
|
||||
- `backend/newAgent/tools/read_helpers.go`
|
||||
- `backend/newAgent/tools/write_tools.go`
|
||||
- `backend/newAgent/tools/SCHEDULE_TOOLS.md`
|
||||
|
||||
已做:
|
||||
|
||||
- 粗排成功写回后,任务状态会从真实 pending 变成 `suggested`
|
||||
- 不再使用“pending + slots”的旧兼容语义作为主路径
|
||||
- 工具读写层已经统一支持 `existing / suggested / pending`
|
||||
|
||||
意义:
|
||||
|
||||
- 粗排结果是“建议落位”,后续应使用 `move / swap / unplace`
|
||||
- 不应该再让 LLM 把这些任务当作待补排任务来 `place`
|
||||
|
||||
#### E. 粗排节点增加了可观测 debug
|
||||
|
||||
位置:
|
||||
|
||||
- `backend/newAgent/node/rough_build.go`
|
||||
|
||||
现在会打这些日志:
|
||||
|
||||
- `placements`
|
||||
- `applied`
|
||||
- `day_mapping_miss`
|
||||
- `task_item_match_miss`
|
||||
- `pending_in_scope`
|
||||
- `window_days`
|
||||
- 少量 miss 样本
|
||||
|
||||
意义:
|
||||
|
||||
- 下次如果粗排再挂,不需要再靠猜
|
||||
- 能直接区分是:
|
||||
- DayMapping 没命中
|
||||
- 还是 `task_item_id` 没命中
|
||||
|
||||
### 2.2 粗排阶段当前的真实状态
|
||||
|
||||
当前真实结论:
|
||||
|
||||
- 粗排已经能跑通
|
||||
- 用户已在真实链路确认这一点
|
||||
|
||||
所以粗排这条线当前不是主矛盾了。
|
||||
|
||||
---
|
||||
|
||||
## 3. 第 2 阶段:正式 abort/terminal 协议,已完成
|
||||
|
||||
### 3.1 已完成的核心改动
|
||||
|
||||
#### A. CommonState 引入统一 terminal outcome
|
||||
|
||||
位置:
|
||||
|
||||
- `backend/newAgent/model/common_state.go`
|
||||
|
||||
已做:
|
||||
|
||||
- 新增:
|
||||
- `FlowTerminalStatus`
|
||||
- `FlowTerminalOutcome`
|
||||
- 新增方法:
|
||||
- `Abort(...)`
|
||||
- `Exhaust(...)`
|
||||
- `HasTerminalOutcome()`
|
||||
- `TerminalStatus()`
|
||||
- `IsCompleted()`
|
||||
- `IsAborted()`
|
||||
- `IsExhaustedTerminal()`
|
||||
- `ClearTerminalOutcome()`
|
||||
|
||||
意义:
|
||||
|
||||
- 后续 graph / execute / deliver 不再各自猜“当前算不算结束”
|
||||
- 统一围绕一份终止结果收口
|
||||
|
||||
#### B. execute contract 正式支持 `abort`
|
||||
|
||||
位置:
|
||||
|
||||
- `backend/newAgent/model/execute_contract.go`
|
||||
- `backend/newAgent/prompt/execute.go`
|
||||
|
||||
已做:
|
||||
|
||||
- 新增 `ExecuteActionAbort = "abort"`
|
||||
- `ExecuteDecision` 新增 `Abort *AbortIntent`
|
||||
- `Validate()` 已补齐互斥/必填规则
|
||||
- execute prompt / react prompt 都已加入 `abort` 契约和 JSON 示例
|
||||
|
||||
#### C. rough_build 异常会正式 abort,而不是让 LLM 补排
|
||||
|
||||
位置:
|
||||
|
||||
- `backend/newAgent/node/rough_build.go`
|
||||
|
||||
已做:
|
||||
|
||||
- 若粗排后仍有真实 pending:
|
||||
- 发失败状态
|
||||
- `flowState.Abort(...)`
|
||||
- 直接交给 deliver 收口
|
||||
|
||||
这部分已经和用户确认过业务语义,是对的。
|
||||
|
||||
#### D. execute 层接入 abort / exhausted 正式语义
|
||||
|
||||
位置:
|
||||
|
||||
- `backend/newAgent/node/execute.go`
|
||||
|
||||
已做:
|
||||
|
||||
- execute 轮次耗尽时,不再伪装成 `done`
|
||||
- 改为 `flowState.Exhaust(...)`
|
||||
- 新增 `handleExecuteActionAbort(...)`
|
||||
- `abort` 不在 execute 内直接最终答复,而是交给 deliver
|
||||
|
||||
#### E. graph 路由改成看正式 terminal outcome
|
||||
|
||||
位置:
|
||||
|
||||
- `backend/newAgent/graph/common_graph.go`
|
||||
|
||||
已做:
|
||||
|
||||
- `RoughBuild -> Execute` 改为 branch
|
||||
- 粗排异常终止时可以直接 `RoughBuild -> Deliver`
|
||||
- `branchAfterExecute()` 不再因为“刚好最后一轮”就提前 deliver
|
||||
- 必须等 execute 正式写入终止结果
|
||||
|
||||
#### F. deliver 收口统一按 terminal outcome 输出
|
||||
|
||||
位置:
|
||||
|
||||
- `backend/newAgent/node/deliver.go`
|
||||
- `backend/newAgent/node/agent_nodes.go`
|
||||
|
||||
已做:
|
||||
|
||||
- deliver 不再无脑 `Done()`
|
||||
- deliver summary 会优先看 terminal outcome
|
||||
- 新增:
|
||||
- `buildAbortSummary`
|
||||
- `buildExhaustedSummary`
|
||||
- 只有 `completed` 路径才写 schedule preview
|
||||
- `aborted / exhausted` 跳过 preview
|
||||
|
||||
### 3.2 第 2 阶段的验证情况
|
||||
|
||||
本地已跑通过:
|
||||
|
||||
```bash
|
||||
go test ./conv ./newAgent/node ./newAgent/model ./newAgent/graph ./newAgent/tools ./service/agentsvc
|
||||
```
|
||||
|
||||
注意:
|
||||
|
||||
- 每次 `go test` 后都已清理根目录 `.gocache`
|
||||
- 过程中使用过临时 `*_test.go` 验证窗口问题和粗排写回问题,跑完后已全部删除
|
||||
|
||||
---
|
||||
|
||||
## 4. 非常重要:当前“上下文”到底改没改
|
||||
|
||||
这个点后续助理很容易误判,这里单独写清楚。
|
||||
|
||||
### 4.1 没做的事
|
||||
|
||||
这轮**没有**做第 3 阶段那种“系统性的上下文瘦身”。
|
||||
|
||||
也就是说,以下这些东西没有被系统重构:
|
||||
|
||||
- `ConversationContext` 的整体装配框架
|
||||
- 历史恢复/回填主流程
|
||||
- 历史裁剪策略
|
||||
- token budget 接入
|
||||
- “把 history 从流水账改成摘要流”的体系化工程
|
||||
|
||||
### 4.2 但确实改了会进入模型上下文的内容
|
||||
|
||||
为了适配新的粗排/abort 语义,这轮确实改了“上下文内容本身”,主要包括:
|
||||
|
||||
1. 粗排完成后的 pinned block 文案变了
|
||||
位置:
|
||||
- `backend/newAgent/node/rough_build.go`
|
||||
|
||||
2. execute 的提示词/输出契约变了
|
||||
位置:
|
||||
- `backend/newAgent/prompt/execute.go`
|
||||
|
||||
3. 工具层的状态语义从 `pending/existing` 扩成了 `pending/suggested/existing`
|
||||
位置:
|
||||
- `backend/newAgent/tools/read_tools.go`
|
||||
- `backend/newAgent/tools/write_tools.go`
|
||||
|
||||
4. state summary 会展示 terminal outcome
|
||||
位置:
|
||||
- `backend/newAgent/prompt/base.go`
|
||||
|
||||
### 4.3 所以当前准确结论是
|
||||
|
||||
可以这样理解:
|
||||
|
||||
- **没有做上下文瘦身**
|
||||
- **但确实改了进入模型的上下文内容**
|
||||
|
||||
所以如果下游 `execute` 现在表现依旧很差,不能简单说:
|
||||
|
||||
- “是第 1-2 阶段没做好”
|
||||
|
||||
更准确的说法是:
|
||||
|
||||
- 第 1-2 阶段把粗排和终止语义打通了
|
||||
- 但下游本来就被上下文噪音淹着
|
||||
- 现在必须进入第 3 阶段,先瘦身,再评价整体效果
|
||||
|
||||
---
|
||||
|
||||
## 5. 当前主矛盾:不是粗排,而是 execute 上下文过胖
|
||||
|
||||
用户已经明确表达:
|
||||
|
||||
- “下游本来就基本跑不通”
|
||||
- “必须要瘦身上下文才能看出整体的效果”
|
||||
|
||||
这意味着明天接手时不要再把精力放在:
|
||||
|
||||
- 继续 patch 粗排小问题
|
||||
- 继续围绕 abort 收口补语义
|
||||
|
||||
下一步的主任务必须切换为:
|
||||
|
||||
- 第 3 阶段:上下文瘦身
|
||||
- 第 4 阶段:prompt 结构重构
|
||||
|
||||
---
|
||||
|
||||
## 6. 第 3 阶段:上下文瘦身,明天应该怎么做
|
||||
|
||||
### 6.1 目标
|
||||
|
||||
目标不是“再写一版更长的 prompt”,而是:
|
||||
|
||||
- 让 execute 每轮看到的输入,变成“足够决策、但不淹没”的信息量
|
||||
|
||||
换句话说,要把现在的:
|
||||
|
||||
- `system + tool summary + 全量 history + pinned + runtime prompt`
|
||||
|
||||
改造成更可控的:
|
||||
|
||||
- 少量稳定规则
|
||||
- 少量当前必要状态
|
||||
- 少量最近真实有效观察
|
||||
|
||||
### 6.2 第 3 阶段必须完成的事
|
||||
|
||||
#### A. 历史去流水账
|
||||
|
||||
重点文件:
|
||||
|
||||
- `backend/service/agentsvc/agent_newagent.go`
|
||||
- `backend/newAgent/prompt/base.go`
|
||||
- `backend/newAgent/node/execute.go`
|
||||
|
||||
要做:
|
||||
|
||||
- 同工具同参数的重复查询,不保留多份原文
|
||||
- 旧结果改成摘要
|
||||
- 只保留最近一条原始结果
|
||||
|
||||
典型对象:
|
||||
|
||||
- `get_overview`
|
||||
- `list_tasks`
|
||||
- `find_free`
|
||||
|
||||
#### B. assistant 过程废话不再进入后续模型历史
|
||||
|
||||
要处理的典型文本:
|
||||
|
||||
- “我先查一下”
|
||||
- “我接下来会……”
|
||||
- “我准备先获取……”
|
||||
|
||||
这些文本对下一轮决策价值极低,但会稳定吃 token。
|
||||
|
||||
#### C. 失败模式保留“摘要”,不要保留整段原始失败链路
|
||||
|
||||
例如:
|
||||
|
||||
- `place` 缺 `task_id`
|
||||
- `find_free` 缺 `duration`
|
||||
|
||||
正确保留方式应该更像:
|
||||
|
||||
- 最近失败模式:`place` 缺少 `task_id`
|
||||
|
||||
而不是整段原始 tool call / tool result 全保留。
|
||||
|
||||
#### D. 缩短 state summary / pinned / runtime prompt 的重叠信息
|
||||
|
||||
目前这三层有明显重复:
|
||||
|
||||
- `renderStateSummary`
|
||||
- pinned blocks
|
||||
- execute runtime user prompt
|
||||
|
||||
第 3 阶段要先做减法,减少重复指令。
|
||||
|
||||
#### E. 参考旧链路的 token budget
|
||||
|
||||
重点参考:
|
||||
|
||||
- `backend/service/agentsvc/agent.go`
|
||||
- `backend/pkg/token_budget.go`
|
||||
|
||||
要求:
|
||||
|
||||
- 不一定照搬
|
||||
- 但至少要借鉴旧链路“按预算裁历史”的思路
|
||||
|
||||
### 6.3 第 3 阶段推荐顺序
|
||||
|
||||
建议按这个顺序做:
|
||||
|
||||
1. 先打印/抓取 `BuildExecuteMessages()` 的真实输入样本
|
||||
2. 再压 `history`
|
||||
3. 再压 `pinned/state summary/runtime prompt` 的重叠
|
||||
4. 最后再接 token budget
|
||||
|
||||
原因:
|
||||
|
||||
- 先把“到底胖在哪”看清楚
|
||||
- 避免直接上 budget 把有用信息也一起砍掉
|
||||
|
||||
### 6.4 第 3 阶段完成标准
|
||||
|
||||
至少要满足:
|
||||
|
||||
1. execute 首轮 messages 显著变短
|
||||
2. 同类查询不会反复堆原始结果
|
||||
3. assistant 流水话大幅减少
|
||||
4. 最近失败模式还能被模型感知
|
||||
5. 不破坏第 1-2 阶段已经打通的粗排/abort 语义
|
||||
|
||||
---
|
||||
|
||||
## 7. 第 4 阶段:prompt 结构重构,明天应该怎么做
|
||||
|
||||
### 7.1 目标
|
||||
|
||||
把当前 execute prompt 从“堆规则 + 堆领域细节 + 堆运行时说明”的混合物,重构成:
|
||||
|
||||
1. 通用执行内核
|
||||
2. 领域模块
|
||||
3. 运行时任务简报
|
||||
|
||||
这是用户已经认可的方向。
|
||||
|
||||
### 7.2 建议的三层结构
|
||||
|
||||
#### 第一层:通用执行内核
|
||||
|
||||
负责:
|
||||
|
||||
- agent 身份
|
||||
- 通用动作协议
|
||||
- 通用输出字段
|
||||
- 最小 JSON 示例
|
||||
|
||||
这里不要写死排程语义。
|
||||
|
||||
#### 第二层:领域模块
|
||||
|
||||
对排程领域来说,建议抽成单独模块,至少包含:
|
||||
|
||||
- `domain_name`
|
||||
- `domain_primary_responsibility`
|
||||
- `domain_out_of_scope`
|
||||
- `domain_goals`
|
||||
- `domain_non_goals`
|
||||
- `tool_catalog_brief`
|
||||
- `hard_constraints`
|
||||
- `soft_objectives`
|
||||
- `abort_conditions`
|
||||
- `done_conditions`
|
||||
|
||||
对“粗排后排程优化”这个领域,必须明确写清:
|
||||
|
||||
- 这是优化器,不是补排器
|
||||
- `pending > 0` 是异常,不是待办
|
||||
|
||||
#### 第三层:运行时任务简报
|
||||
|
||||
负责:
|
||||
|
||||
- 用户原始目标
|
||||
- 最新补充指令
|
||||
- 当前阶段
|
||||
- 当前轮次
|
||||
- 当前实例级约束
|
||||
- 最近状态变化
|
||||
- 最近失败摘要
|
||||
- 上一次工具结果摘要
|
||||
- 本轮目标
|
||||
- 推荐下一步动作
|
||||
|
||||
### 7.3 第 4 阶段不要做成什么样
|
||||
|
||||
不要做成:
|
||||
|
||||
- 换一版更长的 execute prompt
|
||||
- 继续把排程规则硬编码进通用层
|
||||
- 继续把运行时状态散落在多个 message 里重复讲
|
||||
|
||||
### 7.4 第 4 阶段推荐落地文件
|
||||
|
||||
可以考虑在以下位置拆分:
|
||||
|
||||
- `backend/newAgent/prompt/base.go`
|
||||
- `backend/newAgent/prompt/execute.go`
|
||||
|
||||
如有必要,可以新增文件,例如:
|
||||
|
||||
- `backend/newAgent/prompt/execute_core.go`
|
||||
- `backend/newAgent/prompt/execute_domain_schedule.go`
|
||||
- `backend/newAgent/prompt/execute_runtime_brief.go`
|
||||
|
||||
### 7.5 第 4 阶段完成标准
|
||||
|
||||
至少要满足:
|
||||
|
||||
1. 通用执行协议不再写死排程业务
|
||||
2. 排程语义以领域模块方式注入
|
||||
3. 运行时信息有单独的结构化简报
|
||||
4. prompt 保留编号结构
|
||||
5. prompt 保留最小 JSON 示例
|
||||
|
||||
---
|
||||
|
||||
## 8. 明天接手时,最重要的判断标准
|
||||
|
||||
明天的助理接手后,不要先问:
|
||||
|
||||
- “为什么微调效果还是差?”
|
||||
|
||||
而要先问:
|
||||
|
||||
- “第 3 阶段有没有把上下文瘦下来?”
|
||||
|
||||
只有在第 3 阶段做完之后,才适合重新评估:
|
||||
|
||||
- execute 是否真正理解了粗排后的 suggested 语义
|
||||
- prompt 重构是否真的提升了整体表现
|
||||
- 端到端排程链路是否比之前更稳定
|
||||
|
||||
---
|
||||
|
||||
## 9. 关键文件清单
|
||||
|
||||
### 第 1-2 阶段已改文件
|
||||
|
||||
- `backend/conv/schedule_provider.go`
|
||||
- `backend/newAgent/model/state_store.go`
|
||||
- `backend/newAgent/model/graph_run_state.go`
|
||||
- `backend/newAgent/model/common_state.go`
|
||||
- `backend/newAgent/model/execute_contract.go`
|
||||
- `backend/newAgent/graph/common_graph.go`
|
||||
- `backend/newAgent/node/rough_build.go`
|
||||
- `backend/newAgent/node/execute.go`
|
||||
- `backend/newAgent/node/deliver.go`
|
||||
- `backend/newAgent/node/agent_nodes.go`
|
||||
- `backend/newAgent/prompt/base.go`
|
||||
- `backend/newAgent/prompt/execute.go`
|
||||
- `backend/newAgent/tools/read_helpers.go`
|
||||
- `backend/newAgent/tools/read_tools.go`
|
||||
- `backend/newAgent/tools/write_tools.go`
|
||||
- `backend/newAgent/tools/SCHEDULE_TOOLS.md`
|
||||
- `backend/service/agentsvc/agent_newagent.go`
|
||||
|
||||
### 第 3-4 阶段重点关注文件
|
||||
|
||||
- `backend/service/agentsvc/agent_newagent.go`
|
||||
- `backend/newAgent/prompt/base.go`
|
||||
- `backend/newAgent/prompt/execute.go`
|
||||
- `backend/newAgent/node/execute.go`
|
||||
- `backend/pkg/token_budget.go`
|
||||
- `backend/service/agentsvc/agent.go`
|
||||
|
||||
---
|
||||
|
||||
## 10. 测试与验证注意事项
|
||||
|
||||
1. 跑 `go test` 后必须清理项目根目录 `.gocache`
|
||||
|
||||
2. 如果为了验证临时补 `*_test.go`,跑完必须删除,不要长期保留
|
||||
|
||||
3. 当前用户明确不希望这轮把 agent 写库逻辑接回去,仍然以“内存态运行”为主
|
||||
|
||||
4. 所有说明、注释、文档都继续用中文
|
||||
|
||||
---
|
||||
|
||||
## 11. 一句话交给下一位助理
|
||||
|
||||
第 1-2 阶段已经把“粗排接入”和“正式 abort 收口”打通了,粗排真实链路也已经跑通;现在不要再围绕粗排打补丁,直接进入第 3 阶段做 execute 上下文瘦身,再做第 4 阶段 prompt 三层重构,完成后再评估整体链路效果。
|
||||
|
||||
---
|
||||
|
||||
## 12. 2026-04-08 最新增量交接(以本节为准)
|
||||
|
||||
> 本节优先级高于前文历史描述。接手时请先读本节,再看上文细节。
|
||||
|
||||
### 12.1 本轮已完成的落地项
|
||||
|
||||
1. execute 上下文结构已固定为 4 条消息:
|
||||
- `message[0]`:固定 prompt(规则 + JSON 约束 + 工具简表)
|
||||
- `message[1]`:历史上下文短摘要(聊天摘要 + 早期 ReAct 摘要)
|
||||
- `message[2]`:当轮 ReAct Loop 窗口(thought/reason + tool_call + observation 绑定)
|
||||
- `message[3]`:当前执行状态(初始目标、结束判断、非目标)
|
||||
|
||||
2. 当轮 ReAct 压缩已接入:
|
||||
- 窗口内同工具只保留最新 observation 原文;
|
||||
- 被压缩旧结果替换为“当前工具调用结果过于久远,已经被删除。”
|
||||
|
||||
3. execute 输出稳态增强:
|
||||
- `continue / ask_user / confirm` 缺 `speak` 时会兜底回退 `reason`;
|
||||
- 工具结果写入 history 前的截断已删除(不再自动裁到 3000 字符)。
|
||||
|
||||
4. 工具能力已升级:
|
||||
- `get_overview` 改为任务视角全量输出(课程仅占位统计,不展开课程明细);
|
||||
- 新增 `find_first_free`,`find_free` 保留兼容别名;
|
||||
- `move / batch_move` 限定仅允许 `suggested`;
|
||||
- `list_tasks` 增加输入约束(`status` 单值、`category` 不接受 task_class_ids 列表)。
|
||||
|
||||
5. prompt 与文档同步:
|
||||
- execute prompt 已切换到 `find_first_free` 表达;
|
||||
- `SCHEDULE_TOOLS.md` 已同步 `get_overview / find_first_free / move/batch_move` 新语义;
|
||||
- plan prompt 中读工具示例也已从 `find_free` 更新为 `find_first_free`。
|
||||
|
||||
### 12.2 最新日志结论(关键)
|
||||
|
||||
本轮问题已不是“上下文塞不下”,而是“工具不利于收敛”:
|
||||
|
||||
1. `find_first_free` 当前策略过于贪心
|
||||
只返回最早可用位,模型会持续把任务向前挪,容易出现“局部改善但全局不收口”的微调循环。
|
||||
|
||||
2. `query_range` 把“可嵌入共存”和“硬冲突”混合输出
|
||||
模型会把可嵌入并存也当成冲突,导致不必要移动。
|
||||
|
||||
3. 缺少“完成判据工具”
|
||||
当前只有读写事实工具,没有明确“是否可结束”的评估口径,模型自然倾向继续优化。
|
||||
|
||||
4. 写工具冲突口径存在潜在不一致
|
||||
`findConflict` 对 `CanEmbed` 的处理与 `findEmbedHost` 的可嵌入约束并非同一套判据,后续应统一。
|
||||
|
||||
### 12.3 下一棒建议优先级(按顺序做)
|
||||
|
||||
#### P0(必须先做)
|
||||
|
||||
1. 新增评估类只读工具(建议名:`evaluate_balance`)
|
||||
返回最少三项:
|
||||
- `hard_conflict_count`
|
||||
- `load_variance`(或等价离散指标)
|
||||
- `done_suggestion`(可结束/建议继续 + 原因)
|
||||
|
||||
2. 改 `find_first_free` 为“候选集”而非单点
|
||||
建议支持 `top_k`(默认 3)并返回每个候选的:
|
||||
- 位置
|
||||
- 目标日负载变化
|
||||
- 是否涉及可嵌入
|
||||
|
||||
3. 改 `query_range` 输出结构
|
||||
必须区分:
|
||||
- `hard_conflict`
|
||||
- `embeddable_overlap`
|
||||
避免模型把可嵌入并存误判为硬冲突。
|
||||
|
||||
#### P1(P0 后做)
|
||||
|
||||
4. prompt 增加收敛指引
|
||||
明确要求模型在每次写操作后优先调用 `evaluate_balance`,满足条件就 `done`,避免“无限微调”。
|
||||
|
||||
### 12.4 接手后的最小验证清单
|
||||
|
||||
1. 跑一轮真实 execute,确认不会长时间卡在 `list_tasks/find_first_free/move` 循环。
|
||||
2. 确认 `query_range` 可区分硬冲突与可嵌入并存。
|
||||
3. 确认 `evaluate_balance` 能触发 `done` 收口。
|
||||
4. 每次 `go test` 后清理项目根目录 `.gocache`。
|
||||
|
||||
### 12.5 关键文件(本轮增量相关)
|
||||
|
||||
- `backend/newAgent/prompt/execute_context.go`
|
||||
- `backend/newAgent/prompt/execute.go`
|
||||
- `backend/newAgent/prompt/plan.go`
|
||||
- `backend/newAgent/node/execute.go`
|
||||
- `backend/newAgent/tools/read_tools.go`
|
||||
- `backend/newAgent/tools/write_tools.go`
|
||||
- `backend/newAgent/tools/registry.go`
|
||||
- `backend/newAgent/tools/SCHEDULE_TOOLS.md`
|
||||
|
||||
---
|
||||
|
||||
## 13. 2026-04-08 下班前交接(本节优先级最高)
|
||||
|
||||
> 下一棒主线已经明确:先研究工具收敛能力,再修“新一轮执行前必要参数重置”。
|
||||
|
||||
### 13.1 本轮新增落地(已完成)
|
||||
|
||||
1. 顺序约束链路已落地:
|
||||
- 新增 `order_guard` 节点,并接入 graph 分支;
|
||||
- 默认 `AllowReorder=false` 时,`PhaseDone(completed)` 会先走 `order_guard` 再 `deliver`;
|
||||
- 用户明确允许打乱顺序时才放行。
|
||||
|
||||
2. `min_context_switch` 工具已接入:
|
||||
- 新增工具实现与注册;
|
||||
- execute 层已加护栏:未授权打乱顺序时拒绝执行并返回明确 observation;
|
||||
- prompt / 工具文档已同步“仅用户明确授权才可用”。
|
||||
|
||||
3. `execute.go` 乱码坏块已修复:
|
||||
- 清理了污染字符串、重复 if、结构异常;
|
||||
- 该段目前为单一、可读、可编译分支。
|
||||
|
||||
4. 当前分支编译验证通过:
|
||||
- `go test ./newAgent/... ./logic/...` 已通过;
|
||||
- 测试后已清理项目根目录 `.gocache`。
|
||||
|
||||
### 13.2 已确认的两个“未完成关键点”
|
||||
|
||||
#### A. msg2/msg3 语义尚未改到目标形态
|
||||
|
||||
现状:
|
||||
- execute 仍是固定 4 消息骨架(`msg2=当轮 ReAct 窗口`,`msg3=执行状态锚点`);
|
||||
- “当轮 ReAct 结束后降级为普通历史并走统一 token 裁剪”还没真正落地;
|
||||
- `ConversationContext.AppendHistory` 本身不做裁剪,统一裁剪链路也尚未接入。
|
||||
|
||||
相关文件:
|
||||
- `backend/newAgent/prompt/execute_context.go`
|
||||
- `backend/newAgent/prompt/base.go`
|
||||
- `backend/newAgent/model/conversation_context.go`
|
||||
|
||||
#### B. round 未在“新一轮开始”自动重置
|
||||
|
||||
现状:
|
||||
- `RoundUsed` 只在 `NextRound()` 累加;
|
||||
- `StartDirectExecute()` 不会重置 `RoundUsed`;
|
||||
- 快照恢复会带回旧 `RoundUsed`,所以“对话已结束但 round 没清零”可复现。
|
||||
|
||||
相关文件:
|
||||
- `backend/newAgent/model/common_state.go`
|
||||
- `backend/service/agentsvc/agent_newagent.go`
|
||||
|
||||
### 13.3 下一步实施建议(按此顺序)
|
||||
|
||||
#### P0:运行态重置(必须先做)
|
||||
|
||||
目标:不丢运行态,不破坏连续对话;只重置执行期临时字段。
|
||||
|
||||
1. 在 `CommonState` 新增 `ResetForNextRun()`(统一重置入口):
|
||||
- 需要重置:`RoundUsed`、`ConsecutiveCorrections`、`PlanSteps/CurrentStep`、`NeedsRoughBuild`、`NeedsRefineAfterRoughBuild`、`AllowReorder`、`SuggestedOrderBaseline`、`TerminalOutcome`。
|
||||
- 不重置:`ConversationID`、`UserID`、历史对话、ScheduleState。
|
||||
|
||||
2. 在 `Chat` 节点入口做主路径重置:
|
||||
- 条件:`!HasPendingInteraction()` 且上一轮 `PhaseDone`;
|
||||
- 目的:用户发起新轮请求时自动清执行期脏状态。
|
||||
|
||||
3. 在冷加载恢复处做同样重置兜底:
|
||||
- 位置:`loadOrCreateRuntimeState()`;
|
||||
- 条件同上;
|
||||
- 目的:覆盖断联恢复场景,避免旧 round 污染新轮。
|
||||
|
||||
#### P1:工具收敛能力研究与改造
|
||||
|
||||
延续 12.x 的结论,优先做:
|
||||
1. `evaluate_balance`(完成判据工具)
|
||||
2. `find_first_free` 从单点升级为候选集(`top_k`)
|
||||
3. `query_range` 明确区分 `hard_conflict` 与 `embeddable_overlap`
|
||||
|
||||
### 13.4 本节涉及的关键文件
|
||||
|
||||
- `backend/newAgent/model/common_state.go`
|
||||
- `backend/newAgent/node/chat.go`
|
||||
- `backend/service/agentsvc/agent_newagent.go`
|
||||
- `backend/newAgent/prompt/execute_context.go`
|
||||
- `backend/newAgent/tools/read_tools.go`
|
||||
- `backend/newAgent/tools/registry.go`
|
||||
- `backend/newAgent/tools/SCHEDULE_TOOLS.md`
|
||||
@@ -1,465 +0,0 @@
|
||||
# 阶段 3:上下文瘦身设计
|
||||
|
||||
本文档更新时间:2026-04-08
|
||||
|
||||
## 0. 文档目的
|
||||
|
||||
这份文档只服务第 3 阶段“上下文瘦身”。
|
||||
|
||||
职责边界:
|
||||
|
||||
1. 记录当前已经和用户对齐的“瘦身后 execute 上下文骨架”。
|
||||
2. 记录第 3 阶段的落地顺序、非目标和完成标准。
|
||||
3. 作为后续上下文被裁剪后的继续施工依据。
|
||||
|
||||
明确不负责:
|
||||
|
||||
1. 不展开第 4 阶段 prompt 三层拆分的最终结构。
|
||||
2. 不在这里继续讨论粗排和 abort 协议本身。
|
||||
|
||||
---
|
||||
|
||||
## 1. 当前已经确认的收敛结论
|
||||
|
||||
以下结论已经对齐,后续不要再回摆:
|
||||
|
||||
1. 第 3 阶段先解决“上下文过胖、重复、噪音多”,不是先做 prompt 三层重构。
|
||||
2. 工具参数定义和 JSON 调用示例,应该放在工具块里,不应该散落在别的 message。
|
||||
3. 上下文结构应尽量通用化,后端只填“已有事实”,不要引入大量需要主观概括的分类字段。
|
||||
4. `msg3` 和 `msg4` 必须是一一对应的一组:
|
||||
- `msg3` 是最近一次工具调用记录;
|
||||
- `msg4` 是与 `msg3` 对应的工具结果;
|
||||
- 如果当前没有最近工具调用,则 `msg3` / `msg4` 应一起缺省。
|
||||
5. `msg4` 已经承载“最近一次工具结果”,`msg5` 不应再重复这部分内容。
|
||||
6. `msg5` 只保留“有唯一来源的运行态事实”,不能放没有明确 owner 的解释性字段。
|
||||
7. `当前步骤` 可以保留,唯一来源应是 `CommonState.CurrentPlanStep()`。
|
||||
8. `当前目标` 当前不保留,因为没有稳定 owner,容易变成后端替模型总结下一步动作。
|
||||
9. `最近观察` 当前不保留,因为没有稳定结构化来源;如果需要相关信息,应直接通过 `msg4` 表达最近一次工具结果。
|
||||
10. `已确认语义` 这类过宽、难填、边界不清的字段不要进入第 3 阶段方案。
|
||||
|
||||
---
|
||||
|
||||
## 2. 瘦身后的目标上下文骨架
|
||||
|
||||
这里记录的是第 3 阶段完成后,`execute` 阶段理想的 messages 骨架。
|
||||
|
||||
注意:
|
||||
|
||||
1. 这是“上下文瘦身后的骨架”,不是第 4 阶段 prompt 三层重构的最终形态。
|
||||
2. 重点是减量、去重、压缩,而不是新增更多层次和字段。
|
||||
|
||||
### 2.1 目标 message 列表
|
||||
|
||||
```text
|
||||
message[0] role=system
|
||||
执行规则:
|
||||
- 只围绕当前步骤行动
|
||||
- 只输出严格 JSON
|
||||
- 不要伪造工具结果
|
||||
- 读操作使用 action=continue + tool_call
|
||||
- 写操作使用 action=confirm + tool_call
|
||||
- 缺少关键信息时用 action=ask_user
|
||||
- 当前流程应终止时用 action=abort
|
||||
- next_plan / done 时 goal_check 必填
|
||||
|
||||
message[1] role=system
|
||||
可用工具:
|
||||
- 工具名
|
||||
- 工具说明
|
||||
- 参数定义
|
||||
- 最小 JSON 调用示例
|
||||
|
||||
message[2] role=assistant
|
||||
历史摘要:
|
||||
- 用户目标
|
||||
- 更早但仍有效的事实
|
||||
- 最近失败摘要
|
||||
- 已折叠说明(重复查询、过程话术、旧修正链已省略)
|
||||
|
||||
message[3] role=assistant
|
||||
最近一次工具调用记录(与 message[4] 成对)
|
||||
|
||||
message[4] role=tool
|
||||
最近一次工具结果
|
||||
|
||||
message[5] role=system
|
||||
当前执行状态:
|
||||
- 当前轮次
|
||||
- 当前步骤
|
||||
- 当前步骤完成判定
|
||||
|
||||
message[6] role=user
|
||||
请继续当前任务的执行阶段,严格输出 JSON。
|
||||
```
|
||||
|
||||
### 2.2 各 message 的职责边界
|
||||
|
||||
#### message[0]:执行规则
|
||||
|
||||
只保留 execute 的稳定规则,不在这里重复工具参数,也不在这里放运行态数据。
|
||||
|
||||
#### message[1]:工具块
|
||||
|
||||
必须包含:
|
||||
|
||||
1. 工具名
|
||||
2. 工具说明
|
||||
3. 参数定义
|
||||
4. 最小 JSON 调用示例
|
||||
|
||||
原因:
|
||||
|
||||
1. 这是 LLM 真实调用工具时最直接依赖的材料。
|
||||
2. 如果只给工具名不给参数,模型很容易继续出现缺参调用。
|
||||
3. 第 3 阶段里,工具块比“更长的执行 prompt”更重要。
|
||||
|
||||
#### message[2]:历史摘要
|
||||
|
||||
只保留“更早但仍有效”的摘要,不保留全量流水账。
|
||||
|
||||
允许保留的内容:
|
||||
|
||||
1. 用户原始目标
|
||||
2. 当前会话中仍然有效的约束
|
||||
3. 最近失败摘要
|
||||
4. 历史折叠说明
|
||||
|
||||
不应保留的内容:
|
||||
|
||||
1. assistant 的过程话术,例如“我先看一下”“我接下来准备……”
|
||||
2. 同工具同参数的多份原始重复结果
|
||||
3. 整段 correction 往返原文
|
||||
|
||||
#### message[3] + message[4]:最近一组工具观察
|
||||
|
||||
这是 execute 在当前轮之前最关键、最新鲜的一组观察。
|
||||
|
||||
约束:
|
||||
|
||||
1. `message[3]` 和 `message[4]` 必须成对出现。
|
||||
2. `message[3]` 是调用记录,`message[4]` 是与之对应的工具结果。
|
||||
3. 若当前没有最近工具调用,则这两条一起省略。
|
||||
4. 不能凭空生成“最近结果摘要”。
|
||||
|
||||
#### message[5]:当前执行状态
|
||||
|
||||
这里只允许放“有唯一来源的运行态事实”。
|
||||
|
||||
当前允许的字段:
|
||||
|
||||
1. 当前轮次
|
||||
2. 当前步骤
|
||||
3. 当前步骤完成判定
|
||||
|
||||
当前不允许的字段:
|
||||
|
||||
1. 当前目标
|
||||
2. 最近观察
|
||||
3. 已确认语义
|
||||
4. 任何需要后端主观解释才能生成的字段
|
||||
|
||||
#### message[6]:本轮触发指令
|
||||
|
||||
作用很单一:
|
||||
|
||||
1. 明确“现在继续 execute”
|
||||
2. 强化“严格输出 JSON”
|
||||
|
||||
不要在这里重复整份计划、工具说明或历史摘要。
|
||||
|
||||
---
|
||||
|
||||
## 3. 一个更接近真实落地的示例
|
||||
|
||||
下面这个例子只用于校准方向,不要求文案逐字一致。
|
||||
|
||||
```text
|
||||
message[0] role=system
|
||||
你是 SmartFlow NewAgent 的执行器。
|
||||
|
||||
执行规则:
|
||||
1. 只围绕当前步骤行动,不要跳到别的步骤。
|
||||
2. 只输出严格 JSON,不要输出 markdown,不要输出 JSON 之外的解释。
|
||||
3. 不要伪造工具结果。
|
||||
4. 读操作用 action=continue + tool_call。
|
||||
5. 写操作用 action=confirm + tool_call。
|
||||
6. 缺少关键上下文且无法补齐时,输出 action=ask_user。
|
||||
7. 当前流程应正式终止时,输出 action=abort。
|
||||
8. 输出 action=next_plan 或 action=done 时,goal_check 必填。
|
||||
|
||||
message[1] role=system
|
||||
可用工具:
|
||||
|
||||
1. get_overview
|
||||
说明:查看当前窗口内整体分布。
|
||||
参数:
|
||||
{}
|
||||
调用示例:
|
||||
{
|
||||
"name": "get_overview",
|
||||
"arguments": {}
|
||||
}
|
||||
|
||||
2. find_free
|
||||
说明:查找满足指定连续时长的空位。
|
||||
参数:
|
||||
{
|
||||
"duration": "int, 必填",
|
||||
"day": "int, 可选"
|
||||
}
|
||||
调用示例:
|
||||
{
|
||||
"name": "find_free",
|
||||
"arguments": {
|
||||
"duration": 2,
|
||||
"day": 5
|
||||
}
|
||||
}
|
||||
|
||||
3. list_tasks
|
||||
说明:列出任务,可按类别和状态过滤。
|
||||
参数:
|
||||
{
|
||||
"category": "string, 可选",
|
||||
"status": "string, 可选, 可取 all/existing/suggested/pending"
|
||||
}
|
||||
调用示例:
|
||||
{
|
||||
"name": "list_tasks",
|
||||
"arguments": {
|
||||
"status": "suggested"
|
||||
}
|
||||
}
|
||||
|
||||
4. move
|
||||
说明:移动一个已预排任务(仅 suggested)。
|
||||
参数:
|
||||
{
|
||||
"task_id": "int, 必填",
|
||||
"new_day": "int, 必填",
|
||||
"new_slot_start": "int, 必填"
|
||||
}
|
||||
调用示例:
|
||||
{
|
||||
"name": "move",
|
||||
"arguments": {
|
||||
"task_id": 128,
|
||||
"new_day": 5,
|
||||
"new_slot_start": 1
|
||||
}
|
||||
}
|
||||
|
||||
5. swap
|
||||
说明:交换两个已落位任务。
|
||||
参数:
|
||||
{
|
||||
"task_a": "int, 必填",
|
||||
"task_b": "int, 必填"
|
||||
}
|
||||
调用示例:
|
||||
{
|
||||
"name": "swap",
|
||||
"arguments": {
|
||||
"task_a": 128,
|
||||
"task_b": 136
|
||||
}
|
||||
}
|
||||
|
||||
6. batch_move
|
||||
说明:批量原子移动多个任务。
|
||||
参数:
|
||||
{
|
||||
"moves": [
|
||||
{
|
||||
"task_id": "int, 必填",
|
||||
"new_day": "int, 必填",
|
||||
"new_slot_start": "int, 必填"
|
||||
}
|
||||
]
|
||||
}
|
||||
调用示例:
|
||||
{
|
||||
"name": "batch_move",
|
||||
"arguments": {
|
||||
"moves": [
|
||||
{
|
||||
"task_id": 128,
|
||||
"new_day": 5,
|
||||
"new_slot_start": 1
|
||||
},
|
||||
{
|
||||
"task_id": 129,
|
||||
"new_day": 5,
|
||||
"new_slot_start": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
7. unplace
|
||||
说明:取消一个已落位任务。
|
||||
参数:
|
||||
{
|
||||
"task_id": "int, 必填"
|
||||
}
|
||||
调用示例:
|
||||
{
|
||||
"name": "unplace",
|
||||
"arguments": {
|
||||
"task_id": 128
|
||||
}
|
||||
}
|
||||
|
||||
补充约束:
|
||||
- suggested 可以 move / swap / unplace
|
||||
- existing 不能 move / batch_move(仅作已安排事实层)
|
||||
- pending 不能 move / swap / unplace
|
||||
- 如果当前任务已经是 suggested,不要再把它当 pending 去 place
|
||||
|
||||
message[2] role=assistant
|
||||
历史摘要:
|
||||
- 用户目标:把任务类 [101,102] 调整到本周,尽量分布更均匀,周五不要太满。
|
||||
- 当前已知事实:
|
||||
1. 当前阶段是 execute
|
||||
2. task_class_ids=[101,102]
|
||||
3. 当前状态统计:existing=9, suggested=18, pending=0
|
||||
- 最近一次失败摘要:find_free 缺少 duration 参数
|
||||
- 更早的重复查询、过程话术、旧修正链已折叠
|
||||
|
||||
message[3] role=assistant
|
||||
tool_call:
|
||||
{
|
||||
"name": "get_overview",
|
||||
"arguments": {}
|
||||
}
|
||||
|
||||
message[4] role=tool
|
||||
规划窗口概览:
|
||||
- existing=9
|
||||
- suggested=18
|
||||
- pending=0
|
||||
- 周三第5-8节 suggested 偏密
|
||||
- 周五第1-2节有空位
|
||||
- 周五第3-4节有空位
|
||||
|
||||
message[5] role=system
|
||||
当前执行状态:
|
||||
- 当前轮次:2/8
|
||||
- 当前步骤:先识别最值得调整的 suggested 任务和候选空位
|
||||
- 当前步骤完成判定:能明确指出哪些任务值得调整,以及候选目标时段
|
||||
|
||||
message[6] role=user
|
||||
请继续当前任务的执行阶段,严格输出 JSON。
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 第 3 阶段的具体落地计划
|
||||
|
||||
### 4.1 第一件事:先抓真实输入样本
|
||||
|
||||
目标:
|
||||
|
||||
1. 先拿到 `BuildExecuteMessages()` 真正送给模型的样本。
|
||||
2. 不先拍脑袋改结构,先确认“胖点”究竟在 history、pinned,还是 runtime prompt。
|
||||
|
||||
当前可复用入口:
|
||||
|
||||
1. `backend/newAgent/prompt/execute.go`
|
||||
2. `backend/newAgent/prompt/base.go`
|
||||
3. `backend/newAgent/node/execute.go` 中已有 execute 上下文调试日志
|
||||
|
||||
产出:
|
||||
|
||||
1. 至少 2 到 3 份真实样本
|
||||
2. 标出每个 message 的长度、重复点和噪音来源
|
||||
|
||||
### 4.2 第二件事:补 execute 专用的历史压缩层
|
||||
|
||||
目标:
|
||||
|
||||
1. 不再把 `ConversationContext.History` 原样全量喂给 execute。
|
||||
2. 形成“更早历史摘要 + 最近一组工具观察”的结构。
|
||||
|
||||
必须做的事:
|
||||
|
||||
1. 同工具同参数的重复查询,不保留多份原始结果。
|
||||
2. 更早结果改成摘要,只保留最近一条原始结果。
|
||||
3. assistant 过程话术不再进入后续模型历史。
|
||||
4. correction / 工具失败链改成“最近失败摘要”,不要保留整段往返原文。
|
||||
5. 保留合法的 assistant tool_call + tool result 成对消息,不能破坏 OpenAI 兼容格式。
|
||||
|
||||
### 4.3 第三件事:压缩 pinned / runtime 的重复信息
|
||||
|
||||
目标:
|
||||
|
||||
1. 避免 `state summary + pinned + runtime user prompt` 三处重复抄同一份信息。
|
||||
2. 保留最新、必要、唯一来源的信息。
|
||||
|
||||
原则:
|
||||
|
||||
1. 当前计划/当前步骤只保留最新版本,不做历史累积。
|
||||
2. `msg5` 只保留“当前轮次 + 当前步骤 + 当前步骤完成判定”。
|
||||
3. 工具结果只出现在 `msg4`,不在 `msg5` 再复述。
|
||||
4. 粗排语义只保留一处,不要在多条 message 重复提醒。
|
||||
|
||||
### 4.4 第四件事:最后再接 token budget
|
||||
|
||||
目标:
|
||||
|
||||
1. 在完成摘要化和去重后,再做按预算裁剪。
|
||||
2. 避免一上来直接砍历史,把真正有价值的信息也一起砍掉。
|
||||
|
||||
可复用思路:
|
||||
|
||||
1. 参考旧链路 `agent.go` 的历史预算计算和裁剪流程。
|
||||
2. 参考 `backend/pkg/token_budget.go` 中的预算估算与窗口裁剪函数。
|
||||
|
||||
要求:
|
||||
|
||||
1. 不一定照搬旧链路。
|
||||
2. 但应复用“先估算、再裁剪、最后收敛会话窗口”的思路。
|
||||
|
||||
---
|
||||
|
||||
## 5. 第 3 阶段明确不做什么
|
||||
|
||||
为了避免和第 4 阶段混淆,这一轮明确不做:
|
||||
|
||||
1. 不把 execute prompt 直接拆成三层正式文件结构。
|
||||
2. 不在通用执行 prompt 里重写完整排程领域模块。
|
||||
3. 不额外新增没有稳定 owner 的字段,例如:
|
||||
- 当前目标
|
||||
- 最近观察
|
||||
- 已确认语义
|
||||
4. 不继续围绕粗排补边角语义。
|
||||
5. 不继续围绕 abort 协议扩展描述文案。
|
||||
|
||||
---
|
||||
|
||||
## 6. 第 3 阶段完成标准
|
||||
|
||||
至少要满足:
|
||||
|
||||
1. execute 首轮 messages 明显变短。
|
||||
2. 同工具同参数的重复查询不会继续堆多份原始结果。
|
||||
3. assistant 过程话术不再进入后续执行历史。
|
||||
4. 最近一次失败模式仍能被模型感知。
|
||||
5. 最近一次工具调用与结果仍以合法配对形式保留。
|
||||
6. `msg5` 不再重复 `msg4` 的内容。
|
||||
7. 不破坏第 1-2 阶段已经打通的粗排 / abort 语义。
|
||||
|
||||
---
|
||||
|
||||
## 7. 供下一轮继续时快速判断的检查清单
|
||||
|
||||
如果下一轮接手时要快速判断是否做对,可以先问这几个问题:
|
||||
|
||||
1. execute 现在是否还是“全量 history + 全量 pinned + 全量 runtime prompt”直接拼接?
|
||||
2. 工具参数和 JSON 示例是否已经进入单独工具块?
|
||||
3. `msg3` / `msg4` 是否仍保持一一对应?
|
||||
4. `msg5` 是否只保留运行态事实,而没有重复工具结果?
|
||||
5. assistant 的过程话术是否还在继续污染后续历史?
|
||||
6. correction 失败链是否还在整段保留?
|
||||
|
||||
如果以上问题仍然大多回答“是”,说明第 3 阶段还没有真正完成。
|
||||
Reference in New Issue
Block a user