mirror of
https://gitee.com/mateos/mateclaw.git
synced 2026-09-13 03:13:41 +08:00
feat(agent): require ledger discipline in system prompt for multi-step tasks
This commit is contained in:
parent
9f2fb3db23
commit
8798668524
@ -140,15 +140,26 @@ public class ReasoningNode implements NodeAction {
|
||||
+ " 请重新调用同一工具但**缩小内容**,或拆成多次顺序调用,**不要改成纯文字回答**。\n"
|
||||
+ "- 只在确实没有合适工具,或所有工具步骤都已完成、可以最终回答用户时,\n"
|
||||
+ " 才输出无 tool_call 的纯文字回答。\n\n"
|
||||
+ "## 进度跟踪(多步任务必读)\n\n"
|
||||
+ "- 对于包含 ≥3 个独立子步骤的任务(逐项调研、分节起草、批量生成等),\n"
|
||||
+ " 你**应当**使用 `progress_update` 工具维护进度账本:\n"
|
||||
+ " 1. 任务起手时为每个子步骤注册一条 `pending` 条目;\n"
|
||||
+ " 2. 开始执行某条前切到 `in_progress`;\n"
|
||||
+ " 3. 完成后立即切到 `done`;遇到阻塞切到 `blocked` 并写明原因。\n"
|
||||
+ "- 系统会在你的每一次推理前注入一份**当前进度快照**(标题 \"当前任务进度\"),\n"
|
||||
+ " 请把它视为权威的\"已完成清单\",**不要重复执行已经 done 的步骤**。\n"
|
||||
+ "- 单一问题(无须拆解的短任务)不需要使用本工具;用错不会报错,但会浪费一次调用。\n";
|
||||
+ "## 进度跟踪(多步任务强制规则,不可绕过)\n\n"
|
||||
+ "**触发条件**:用户的任务包含 ≥3 个可枚举子目标 — 比如\n"
|
||||
+ "\"调研 10 个模型\"、\"逐节起草报告\"、\"批量生成 N 份文档\"、\n"
|
||||
+ "\"依次调用 N 个 API\"、\"对每个文件执行同一操作\"等。\n\n"
|
||||
+ "**必须做的事**:\n"
|
||||
+ "1. **第一轮回复就用并行 tool_calls 批量注册全部子目标为 `pending`**\n"
|
||||
+ " 一条回复里 N 个 `progress_update` 同时发出(不要串行)。\n"
|
||||
+ " 例:要调研 10 个模型,第一轮就发 10 个 `progress_update(stepKey=\"model_xxx\", status=\"pending\")`。\n"
|
||||
+ "2. **每开始一个子目标**前发 `progress_update(同 stepKey, status=\"in_progress\")`。\n"
|
||||
+ "3. **每完成一个子目标**后立即发 `progress_update(同 stepKey, status=\"done\")`。\n"
|
||||
+ "4. **无法继续**时发 `progress_update(同 stepKey, status=\"blocked\", note=\"具体原因\")`。\n\n"
|
||||
+ "**为什么必须**:\n"
|
||||
+ "- 系统在你**每一次推理前**注入一份 \"## 当前任务进度\" 快照。\n"
|
||||
+ " 这是你**唯一可信**的\"已完成清单\"——比你记忆里的步骤更权威,因为上下文窗口\n"
|
||||
+ " 会被裁剪,老的工具调用记录会消失,但 ledger 不会。\n"
|
||||
+ "- 不维护 ledger 的后果(实测):\n"
|
||||
+ " · 上下文裁剪后忘记自己做过的步骤,重复执行已完成项 → 浪费迭代预算\n"
|
||||
+ " · 漏做项目 → 任务不完整 → 撞 max_iterations 还没干完\n"
|
||||
+ " · ledger snapshot 永远显示初始状态,对你毫无帮助\n\n"
|
||||
+ "**例外**:单一问题、简单问答、不可拆解的请求 — 不需要用。\n";
|
||||
|
||||
private final ChatModel chatModel;
|
||||
private final List<ToolCallback> toolCallbacks;
|
||||
@ -511,12 +522,28 @@ public class ReasoningNode implements NodeAction {
|
||||
// history that produced those done entries. Suppressed when the
|
||||
// ledger column is empty so short single-turn questions stay
|
||||
// prompt-cache-friendly.
|
||||
//
|
||||
// Past iteration ~10, also emit a stale-reminder SystemMessage when
|
||||
// the ledger looks abandoned (empty after many turns, or no
|
||||
// progress_update in >90s). This pushes the model back to the
|
||||
// ledger discipline before it drifts into the "I'm doing the work
|
||||
// but never marking it" failure mode observed in round-4 of the
|
||||
// LLM-review smoke test.
|
||||
if (progressLedgerService != null && conversationId != null && !conversationId.isBlank()) {
|
||||
try {
|
||||
String snapshot = progressLedgerService.load(conversationId).renderSnapshot();
|
||||
vip.mate.agent.progress.ProgressLedger ledger =
|
||||
progressLedgerService.load(conversationId);
|
||||
String snapshot = ledger.renderSnapshot();
|
||||
if (snapshot != null) {
|
||||
nonHistoryPrefix.add(new SystemMessage(snapshot));
|
||||
}
|
||||
String staleReminder = ledger.renderStaleReminder(
|
||||
accessor.iterationCount(), java.time.Instant.now());
|
||||
if (staleReminder != null) {
|
||||
nonHistoryPrefix.add(new SystemMessage(staleReminder));
|
||||
log.info("[ReasoningNode] Injected stale-ledger reminder at iter {} for conv {}",
|
||||
accessor.iterationCount(), conversationId);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Never let a ledger-side failure break the reasoning step.
|
||||
log.warn("[ReasoningNode] Failed to load progress ledger for {}: {}",
|
||||
|
||||
Loading…
Reference in New Issue
Block a user