From 2b6a4c64c99139b307ec1aeac2d4649565dd8756 Mon Sep 17 00:00:00 2001 From: matevip Date: Thu, 21 May 2026 15:13:15 +0800 Subject: [PATCH] fix(agent): add data-fidelity rules to summarizer prompts + fix fallback cut (#187) --- .../java/vip/mate/agent/graph/node/SummarizingNode.java | 4 +++- .../prompts/context/structured-summary-system.txt | 5 +++++ .../main/resources/prompts/graph/limit-exceeded-system.txt | 1 + .../src/main/resources/prompts/graph/summarize-system.txt | 7 +++++++ 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/mateclaw-server/src/main/java/vip/mate/agent/graph/node/SummarizingNode.java b/mateclaw-server/src/main/java/vip/mate/agent/graph/node/SummarizingNode.java index 53b751ef..83e8b022 100644 --- a/mateclaw-server/src/main/java/vip/mate/agent/graph/node/SummarizingNode.java +++ b/mateclaw-server/src/main/java/vip/mate/agent/graph/node/SummarizingNode.java @@ -14,6 +14,7 @@ import org.springframework.ai.chat.prompt.ChatOptions; import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.openai.OpenAiChatOptions; import vip.mate.agent.GraphEventPublisher; +import vip.mate.agent.context.StructuredTruncator; import vip.mate.agent.graph.NodeStreamingChatHelper; import vip.mate.agent.graph.state.MateClawStateAccessor; import vip.mate.agent.prompt.PromptLoader; @@ -120,7 +121,8 @@ public class SummarizingNode implements NodeAction { log.warn("[SummarizingNode] Summarization LLM call failed: {}, using raw observations as fallback", result.errorMessage()); String fallback = observationText.length() > 500 - ? observationText.substring(0, 500) + "...[摘要生成失败,已截断]" + ? StructuredTruncator.headSlice(observationText.toString(), 500) + + "\n...[摘要生成失败,仅保留原始观察的前部片段;数据不完整,请勿编造、补全或重新编号缺失内容]" : observationText.toString(); AssistantMessage fallbackMsg = new AssistantMessage("[工具观察摘要(降级)]\n" + fallback); return MateClawStateAccessor.output() diff --git a/mateclaw-server/src/main/resources/prompts/context/structured-summary-system.txt b/mateclaw-server/src/main/resources/prompts/context/structured-summary-system.txt index da30a817..b83e9c3f 100644 --- a/mateclaw-server/src/main/resources/prompts/context/structured-summary-system.txt +++ b/mateclaw-server/src/main/resources/prompts/context/structured-summary-system.txt @@ -30,5 +30,10 @@ ## 关键上下文 [不显式保留就会丢失的具体值、错误消息、配置详情] +## 数据保真(最高优先级) +- 涉及具体数据集(列表、表格、记录集合)时,**绝不编造、重新编号,或把明细缩减为范围表述/总数**。只复述上下文中真实可见的内容。 +- 明细已被清理或不在上下文中(如出现"旧工具输出已清理""已截断""TRUNCATED"等标记)时,只声明该部分数据不完整且不可见,**不要猜测其数量、内容或来源路径**;仅当上下文里有真实可见的落盘路径(read_file)时才可引用它。 +- 不要为了塞进篇幅上限而虚构、合并或范围化明细——诚实省略(如标注"该数据集未完整保留")始终优于编造。 + 目标约 {summary_budget} 字。要具体——包含文件路径、命令输出、错误消息和实际值。 只输出摘要正文,不要前缀或额外说明。 \ No newline at end of file diff --git a/mateclaw-server/src/main/resources/prompts/graph/limit-exceeded-system.txt b/mateclaw-server/src/main/resources/prompts/graph/limit-exceeded-system.txt index 1c774282..fd8f7d26 100644 --- a/mateclaw-server/src/main/resources/prompts/graph/limit-exceeded-system.txt +++ b/mateclaw-server/src/main/resources/prompts/graph/limit-exceeded-system.txt @@ -4,6 +4,7 @@ 回答要求: 1. 给出简洁、诚实、可执行的回答 2. 若信息不足以完全回答,明确说明哪些部分还不确定 +2.1. 若所依据的数据被截断或不完整(含"已截断/TRUNCATED/preview/INCOMPLETE"等标记),明确告知用户数据不完整并指出缺口,**绝不编造、补全或重新编号缺失的数据条目**,也不要把明细列表缩减为范围表述 3. 如果还有未完成的方向,简要列出建议的下一步 4. **不要为「未完成」道歉,不要提及「推理步数」「迭代次数」「工具调用上限」这类技术细节** —— 直接给结论 5. 保持输出简洁,避免重复已知内容 diff --git a/mateclaw-server/src/main/resources/prompts/graph/summarize-system.txt b/mateclaw-server/src/main/resources/prompts/graph/summarize-system.txt index 187ac46f..dff3c028 100644 --- a/mateclaw-server/src/main/resources/prompts/graph/summarize-system.txt +++ b/mateclaw-server/src/main/resources/prompts/graph/summarize-system.txt @@ -1,5 +1,12 @@ 你是一个信息整理助手。请基于用户的原始问题和多轮工具调用的观察结果,生成一份结构化的上下文摘要。 +## 数据保真(最高优先级,先于一切篇幅要求) + +- **绝不编造、推测或重新编号任何数据**。只能复述观察结果中真实出现的内容。 +- **绝不把明细列表/表格/记录集合缩减为范围表述或总数**(例如把 60 条记录写成"第 1-60 行"或"共 60 项"而丢弃具体内容)。条目过多无法全部保留时,明确写"已保留 N 条具体记录,省略 M 条;完整数据见原始工具输出或落盘文件(read_file)",绝不用概括掩盖省略。 +- 若某条观察本身带有截断标记(如 `TRUNCATED`、`已截断`、`INCOMPLETE`、`preview`、`compacted`、`trimmed`),在摘要中**显式标注该数据不完整**,并指明完整数据的来源,绝不补全缺失部分。 +- 当篇幅上限与数据保真冲突时,**优先保真**:宁可如实标注"还有 M 条未列出",也不要为压缩篇幅而虚构或合并明细。 + ## 任务结构判断(先做这一步) 判断用户的原始问题包含的是单一任务还是多个独立子任务: