Harness Engineering 的关键不是继续等待更强模型而是把模型外部的工具、上下文、记忆、检索、状态和反馈循环工程化。过去两年Al 应用讨论很容易落在模型能力上哪个模型更会推理哪个模型更会写代码哪个模型幻觉更少。这个讨论当然重要但当我们真正把 Agent 放进工作环境中时很快会发现模型只是系统的一部分。OReilly 的一篇文章 Agent Harness Engineering 给了一个很直接的框架Agent Model Harness。这里的 Harness 指的是模型外部的整套支架。也就是说一个 raw model 并不会自动成为可工作的 Agent。只有当它被放进一套能给它状态、工具、反馈和约束的系统里才开始具备长期执行任务的能力。传统 RAG 的隐藏问题记忆在第一步就坏掉了然而当我们审视目前的知识型 Agent 实践时会发现这套支架经常在文档进入系统时就已经失效。这类问题在 RAG 系统里非常常见答案不理想时问题到底出在模型、向量数据库还是出在文档进入系统的方式面对这种问题很多团队的第一反应是换更贵的模型、改 prompt、调 temperature。但真正的问题可能发生在更早的地方正确证据根本没有被召回或者文档在进入系统时已经被切碎、丢失结构、断开来源。更准确地说RAG 出错至少要拆成三层来看如果检索层没有找到正确证据这是Recall 问题如果找到了证据但模型编造了文档里不存在的细节这是Faithfulness 问题如果答案有依据但没有完整回应用户意图这是Relevance 问题。在这个系统中文档解析层扮演着至关重要的角色。传统观念里像 Unstructured 或 LangChain Text Splitters 这类工具不应该只被简单解释成 parser 或者 RAG chunking 工具。如果只从 parser 或 chunking 的角度看它很容易被放进一个很窄的类别里把 PDF、Office、Markdown、图片变成文本块。一旦沿用这种平铺碎片的思路Recall 低就成了一个难以解决的系统性顽疾。Recall 低通常是系统性结构丢失不是单点问题在今天的 RAG 工程实践里一个越来越清楚的事实是效果不好时不能把问题粗暴归因于模型或向量数据库。Recall 低通常不是某一个模块单独失效更多的是文档如何被处理查询如何被表达检索如何被执行结果如何被评估这几件事叠加后的结果。其中最先影响召回上限的往往是文档进入系统时的处理方式。很多 RAG 管线仍然依赖固定长度 chunking把文档按 512 或 1024 tokens 切开。这种方式实现简单但很容易把完整答案拆到两个 chunk 里滑动窗口能缓解边界问题却会制造重复内容让相似 chunk 占据 top-k 结果按标题、段落、章节切分更符合人的阅读习惯但前提是文档结构可靠。现实中的 PDF、PPT、表格、扫描件、内部 Wiki 和工单记录往往并不规整所以 chunking 的问题本质上不是切多长的参数问题而是系统有没有理解文档结构的问题。真实文档并不是平铺文本。它有标题、章节、段落、表格、图片、脚注、引用、上下文关系也有从总览到细节的阅读路径。一旦把这些结构拍平成一堆 flat chunksAgent 拿到的就不再是一份文档而是一堆失去层级和来源的碎片。它可能知道某段文字和问题语义相似却不知道这段文字属于哪一章、上下文在讲什么、下文是否有限制条件、旁边的表格是否才是关键证据。很多 RAG 的问题正是从这一步开始埋下的。这就导致了检索不能只依赖单一信号。例如用户问 XR-2048 产品的功耗参数系统却召回 XR-1024 的说明。从通用语义上看两者都和“功耗参数”接近但从业务角度看型号错了答案就是错的。通用 embedding 擅长处理语义相似比如把“退款流程”和“退货申请”拉近。但面对产品型号、API 名称、错误码、合同编号、内部缩写这类精确词时它并不稳定。BM25 能补上词面匹配Reranker 可以在候选结果里重新判断相关性Query Rewriting 则可以把用户的口语表达改写成文档中的专业术语。它们各自解决的是检索链路中的不同盲区。但从 Harness Engineering 的角度看更关键的不是列举这些优化方法而是看到背后的共同事实一个可靠的 agent 系统需要的不只是一段相似文本更多的是一组可以组合使用的检索信号。语义、关键词、章节路径、文档层级、metadata、表格位置、图文关系、引用来源都会影响 agent 最终能不能找到正确证据。所以说 RAG 的 Recall 优化不是一个单点调参问题而是一套工程系统问题。它需要文档解析、结构化 chunking、多路检索、重排、查询改写、评估集、监控和反馈闭环一起工作。换句话说RAG 评估优化本身就是 Harness Engineering 的一部分模型之外的这些管道、工具、状态和反馈机制决定了 Agent 最终能不能拿到正确、完整、可引用的上下文。Knowhere: Agent 的结构化、可导航记忆层要解决上述所有结构丢失和单一信号的问题Harness 就需要一层新的基础设施。这正是我们最近在 GitHub 上开源的仓库 Knowhereontos-ai/knowhere应该被放进 Harness Engineering 里讨论的原因。如果说Agent Model Harness那么 Knowhere 对应的就是 Harness 里的document memory / search / context layer。它要解决的问题是大量企业内部非结构化和半结构化数据比如那些肮脏的被随意涂抹的 Excel 表格、排版混乱的 Word 文档如何顺畅地进入 agent 的长期记忆并在需要时被可靠地检索、导航和引用Knowhere 的价值入口不在大家经常聊的生成阶段、planner 阶段、review 阶段等等而是在更上游。一个好的复杂文档解析层在这个体系里的角色是成为其中的 document memory and retrieval substrate把复杂文档转成 agent 可导航、可引用、可检索、可持续使用的结构化记忆。这和模型怎么推理、agent 怎么规划任务、怎么通过 hook 来实现任务 review 同等关键。放到金融、法律场景的知识型 agent 里memory、search 和 context engineering 是 Harness 中非常关键的一层。模型本身不会天然知道新上传的文档也不会自动理解一份 PDF 的章节结构、表格关系、图片含义和引用来源。所有这些信息都必须通过外部记忆系统进入 agent 的工作流。但这里的关键不是“把文档全部塞给模型”。上下文窗口是有限的而且上下文越长模型越容易出现注意力稀释和推理质量下降。真正有效的 Harness不是把所有内容都塞进上下文而是决定哪些内容直接注入哪些内容留在外部记忆里按需检索哪些结果只需要摘要哪些回答必须带上原文证据和来源路径。因此RAG 的问题不能只看成“检索器有没有召回文本片段”。更准确地说它是在考验 Harness 有没有能力把外部知识组织成 agent 可用的形式。Knowhere 解决的就是这一层的问题为 Agent Harness 提供一层可持续使用的文档记忆和检索基础设施。它不是在做一次性的文档转文本也不是简单切除一批 chunks然后交给 vector db 检索它更重要的工作是在文档进入系统时尽可能保留结构和上下文把原始文档转成后续检索可以利用的多维信号。技术内核从 Flat Chunks 到 Tree-like Chunking但这还只是定位。真正关键的问题是Knowhere 如何把复杂文档从一堆 flat chunks变成 agent 可以导航、比较和引用的 memory substrate记忆基底既然平铺的碎片行不通文档进入 Agent 记忆的形态就应该回归它本身的立体样貌。Knowhere 通过它背后的 tree-like chunking 算法来做到这点。一篇复杂的文档进来Knowhere 的输出的 chunks 里不只是调整 chunk size也不只是给 chunk 多加几个 metadata 字段而是如上图所示把文档理解成一棵有层级、有路径、有关系的结构。第一层是文档内部的树。也就是说chunk 不再是一个被切下来的文本片段它变成了一个有位置、有父节点、有路径、有相邻关系、有来源信息的记忆节点。它知道自己属于哪个 sectionsection 属于哪个 chapter相关表格和图片在哪里上下文要不要一起读最终证据能不能回到原始文档。这样Agent 在 Harness 里调用检索工具时面对的就不是一堆孤立的 top-k 相似片段而是可以沿着章节、路径、关系和证据来源继续定位的文档记忆。最终我们会发现Agentic RAG 的核心不是 retrieval before generation而是retrieval as agent action它是 Harness 不可或缺的一部分。Knowhere 就是作为这一部分的关键服务出现的。
[特殊字符] Harness 工程中怎么做 RAG
发布时间:2026/5/28 6:25:52
Harness Engineering 的关键不是继续等待更强模型而是把模型外部的工具、上下文、记忆、检索、状态和反馈循环工程化。过去两年Al 应用讨论很容易落在模型能力上哪个模型更会推理哪个模型更会写代码哪个模型幻觉更少。这个讨论当然重要但当我们真正把 Agent 放进工作环境中时很快会发现模型只是系统的一部分。OReilly 的一篇文章 Agent Harness Engineering 给了一个很直接的框架Agent Model Harness。这里的 Harness 指的是模型外部的整套支架。也就是说一个 raw model 并不会自动成为可工作的 Agent。只有当它被放进一套能给它状态、工具、反馈和约束的系统里才开始具备长期执行任务的能力。传统 RAG 的隐藏问题记忆在第一步就坏掉了然而当我们审视目前的知识型 Agent 实践时会发现这套支架经常在文档进入系统时就已经失效。这类问题在 RAG 系统里非常常见答案不理想时问题到底出在模型、向量数据库还是出在文档进入系统的方式面对这种问题很多团队的第一反应是换更贵的模型、改 prompt、调 temperature。但真正的问题可能发生在更早的地方正确证据根本没有被召回或者文档在进入系统时已经被切碎、丢失结构、断开来源。更准确地说RAG 出错至少要拆成三层来看如果检索层没有找到正确证据这是Recall 问题如果找到了证据但模型编造了文档里不存在的细节这是Faithfulness 问题如果答案有依据但没有完整回应用户意图这是Relevance 问题。在这个系统中文档解析层扮演着至关重要的角色。传统观念里像 Unstructured 或 LangChain Text Splitters 这类工具不应该只被简单解释成 parser 或者 RAG chunking 工具。如果只从 parser 或 chunking 的角度看它很容易被放进一个很窄的类别里把 PDF、Office、Markdown、图片变成文本块。一旦沿用这种平铺碎片的思路Recall 低就成了一个难以解决的系统性顽疾。Recall 低通常是系统性结构丢失不是单点问题在今天的 RAG 工程实践里一个越来越清楚的事实是效果不好时不能把问题粗暴归因于模型或向量数据库。Recall 低通常不是某一个模块单独失效更多的是文档如何被处理查询如何被表达检索如何被执行结果如何被评估这几件事叠加后的结果。其中最先影响召回上限的往往是文档进入系统时的处理方式。很多 RAG 管线仍然依赖固定长度 chunking把文档按 512 或 1024 tokens 切开。这种方式实现简单但很容易把完整答案拆到两个 chunk 里滑动窗口能缓解边界问题却会制造重复内容让相似 chunk 占据 top-k 结果按标题、段落、章节切分更符合人的阅读习惯但前提是文档结构可靠。现实中的 PDF、PPT、表格、扫描件、内部 Wiki 和工单记录往往并不规整所以 chunking 的问题本质上不是切多长的参数问题而是系统有没有理解文档结构的问题。真实文档并不是平铺文本。它有标题、章节、段落、表格、图片、脚注、引用、上下文关系也有从总览到细节的阅读路径。一旦把这些结构拍平成一堆 flat chunksAgent 拿到的就不再是一份文档而是一堆失去层级和来源的碎片。它可能知道某段文字和问题语义相似却不知道这段文字属于哪一章、上下文在讲什么、下文是否有限制条件、旁边的表格是否才是关键证据。很多 RAG 的问题正是从这一步开始埋下的。这就导致了检索不能只依赖单一信号。例如用户问 XR-2048 产品的功耗参数系统却召回 XR-1024 的说明。从通用语义上看两者都和“功耗参数”接近但从业务角度看型号错了答案就是错的。通用 embedding 擅长处理语义相似比如把“退款流程”和“退货申请”拉近。但面对产品型号、API 名称、错误码、合同编号、内部缩写这类精确词时它并不稳定。BM25 能补上词面匹配Reranker 可以在候选结果里重新判断相关性Query Rewriting 则可以把用户的口语表达改写成文档中的专业术语。它们各自解决的是检索链路中的不同盲区。但从 Harness Engineering 的角度看更关键的不是列举这些优化方法而是看到背后的共同事实一个可靠的 agent 系统需要的不只是一段相似文本更多的是一组可以组合使用的检索信号。语义、关键词、章节路径、文档层级、metadata、表格位置、图文关系、引用来源都会影响 agent 最终能不能找到正确证据。所以说 RAG 的 Recall 优化不是一个单点调参问题而是一套工程系统问题。它需要文档解析、结构化 chunking、多路检索、重排、查询改写、评估集、监控和反馈闭环一起工作。换句话说RAG 评估优化本身就是 Harness Engineering 的一部分模型之外的这些管道、工具、状态和反馈机制决定了 Agent 最终能不能拿到正确、完整、可引用的上下文。Knowhere: Agent 的结构化、可导航记忆层要解决上述所有结构丢失和单一信号的问题Harness 就需要一层新的基础设施。这正是我们最近在 GitHub 上开源的仓库 Knowhereontos-ai/knowhere应该被放进 Harness Engineering 里讨论的原因。如果说Agent Model Harness那么 Knowhere 对应的就是 Harness 里的document memory / search / context layer。它要解决的问题是大量企业内部非结构化和半结构化数据比如那些肮脏的被随意涂抹的 Excel 表格、排版混乱的 Word 文档如何顺畅地进入 agent 的长期记忆并在需要时被可靠地检索、导航和引用Knowhere 的价值入口不在大家经常聊的生成阶段、planner 阶段、review 阶段等等而是在更上游。一个好的复杂文档解析层在这个体系里的角色是成为其中的 document memory and retrieval substrate把复杂文档转成 agent 可导航、可引用、可检索、可持续使用的结构化记忆。这和模型怎么推理、agent 怎么规划任务、怎么通过 hook 来实现任务 review 同等关键。放到金融、法律场景的知识型 agent 里memory、search 和 context engineering 是 Harness 中非常关键的一层。模型本身不会天然知道新上传的文档也不会自动理解一份 PDF 的章节结构、表格关系、图片含义和引用来源。所有这些信息都必须通过外部记忆系统进入 agent 的工作流。但这里的关键不是“把文档全部塞给模型”。上下文窗口是有限的而且上下文越长模型越容易出现注意力稀释和推理质量下降。真正有效的 Harness不是把所有内容都塞进上下文而是决定哪些内容直接注入哪些内容留在外部记忆里按需检索哪些结果只需要摘要哪些回答必须带上原文证据和来源路径。因此RAG 的问题不能只看成“检索器有没有召回文本片段”。更准确地说它是在考验 Harness 有没有能力把外部知识组织成 agent 可用的形式。Knowhere 解决的就是这一层的问题为 Agent Harness 提供一层可持续使用的文档记忆和检索基础设施。它不是在做一次性的文档转文本也不是简单切除一批 chunks然后交给 vector db 检索它更重要的工作是在文档进入系统时尽可能保留结构和上下文把原始文档转成后续检索可以利用的多维信号。技术内核从 Flat Chunks 到 Tree-like Chunking但这还只是定位。真正关键的问题是Knowhere 如何把复杂文档从一堆 flat chunks变成 agent 可以导航、比较和引用的 memory substrate记忆基底既然平铺的碎片行不通文档进入 Agent 记忆的形态就应该回归它本身的立体样貌。Knowhere 通过它背后的 tree-like chunking 算法来做到这点。一篇复杂的文档进来Knowhere 的输出的 chunks 里不只是调整 chunk size也不只是给 chunk 多加几个 metadata 字段而是如上图所示把文档理解成一棵有层级、有路径、有关系的结构。第一层是文档内部的树。也就是说chunk 不再是一个被切下来的文本片段它变成了一个有位置、有父节点、有路径、有相邻关系、有来源信息的记忆节点。它知道自己属于哪个 sectionsection 属于哪个 chapter相关表格和图片在哪里上下文要不要一起读最终证据能不能回到原始文档。这样Agent 在 Harness 里调用检索工具时面对的就不是一堆孤立的 top-k 相似片段而是可以沿着章节、路径、关系和证据来源继续定位的文档记忆。最终我们会发现Agentic RAG 的核心不是 retrieval before generation而是retrieval as agent action它是 Harness 不可或缺的一部分。Knowhere 就是作为这一部分的关键服务出现的。