用 RAG 给 Agent 接入内部知识

发布时间:2026/7/12 4:43:02
用 RAG 给 Agent 接入内部知识 echo-agent 前身为 2025 年 11 月启动的个人助理项目 fubot最初面向长期陪伴型个人智能体围绕认知记忆、上下文延续、用户偏好沉淀、任务闭环与持续自我优化展开。随着真实场景迭代项目逐步形成多入口接入、统一事件模型、消息总线、Agent Loop、多模型抽象、工具调用、MCP 接入、任务调度、权限审批、运行轨迹、长期记忆和受控自演进等能力。目前已支持微信、QQ、CLI、Gateway、Webhook、Cron 等入口服务用户超过 20 万、累计下载超过 50 万是面向长期运行、记忆增强和可持续成长智能体的开源 Agent Runtime。项目地址GitHub - fuyuxiang/echo-agent: Echo Agent 是一个可自托管、长期运行、持续学习的 AI Agent面向个人与团队的私有自动化场景。它可以部署在自有服务器上统一连接模型、工具、记忆、权限与消息入口。内置四层认知记忆、遗忘曲线与矛盾检测机制能够在跨会话任务中持续沉淀上下文并保持长期记忆的质量。针对命令执行、文件操作等高风险行为它提供基于 LLM 的审批与解释机制为关键操作建立可审计、可追溯的安全边界。原生支持 MCP、A2A、多模型路由、任务调度、工具调用和多通道接入覆盖 CLI、Gateway API、微信、Telegram 等入口。它让 Agent 带着长期记忆和可进化技能持续、安全地为你工作。 · GitHub你让 Agent 帮你排查一个内部接口认证失败。它能读日志也能写代码但它不知道公司内部网关的认证规范、接口迁移公告、历史故障处理记录。于是它只能从报错文本里猜可能是 token 过期可能是签名算法不对可能是环境变量没配。这些猜测未必离谱但对工程系统来说不够。真正可靠的 Agent 不能只依赖模型参数和当前会话它必须能回到内部资料查规范、查操作手册、查项目文档并把回答依据讲清楚。这就是 RAG 在 Agent 里的位置。RAG 不是给模型“灌入知识”而是在当前任务里建立一条可追溯的证据通道。问题入口如果只看传统文本型 Chatbot它通常以“输入文本、返回文本”为主。没有内部资料时模型只能依赖训练阶段学到的公共知识和当前上下文。对公开概念这可能够用对企业内部系统问题马上出现。内部接口怎么认证、上线流程走哪几个审批、某个服务的降级策略是什么、某个配置项在哪个版本废弃这些信息通常不在模型参数里。即使模型“看起来知道”也很难说明结论来自哪份文档。对 Agent 来说风险更高。普通问答答错最多是用户再追问Agent 如果基于错误资料执行工具可能会改配置、发消息、创建任务甚至把过期流程当成当前规范。所以Agent 接入内部知识不是为了让回答显得更丰富而是为了让行动有依据、依据能追溯、越权资料进不了上下文。概念边界RAG 的全称是 Retrieval-Augmented Generation检索增强生成。它的基本流程很简单回答前先检索相关资料把资料放进模型上下文再让模型基于资料回答。但在 Agent 系统里RAG 不能只理解成“接一个向量库”。它至少有三层含义层次解决的问题工程要求可发现相关资料能不能被找出来文档解析、分块、索引、查询理解可使用资料能不能支持当前回答或行动上下文裁剪、结构保留、冲突处理可归因结论能不能回到来源引用编号、路径、权限、审计 trace很多系统只优化第一层比如提升 top-k 召回或换 embedding 模型。但 Agent 更需要后两层。因为检索结果不只是“参考文本”它会影响推理、工具调用和安全决策。这也解释了 RAG 和记忆系统的区别。记忆来自 Agent 与用户、项目长期交互中沉淀出的经验强调个性化、作用域、遗忘和更新。知识库来自预先存在的文档资料强调可检索、可引用、可重建和权限过滤。两者都会进入上下文但职责不同。记忆回答“这个用户和这个项目过去形成了什么稳定经验”知识库回答“组织已有资料里有什么可引用证据”。证据通道为了不停留在抽象层面下面以 echo-agent 的实现为例。echo-agent 的知识库模块位于echo_agent.knowledge。当前实现不是向量 RAG而是一个本地关键词知识索引。这个选择很克制它不依赖外部 embedding 服务但保留了 RAG 的关键结构包括文档加载、分块、索引、检索、权限过滤、引用编号和上下文格式化。知识库在 Agent 中有三个入口。第一自动检索。ContextStage构造上下文时会用用户本轮输入搜索知识库把结果加入 retrieval context。第二工具检索。模型可以主动调用knowledge_search在推理过程中补充证据。第三索引维护。管理员或受信任 Agent 可以通过knowledge_index查看索引状态或重建索引。这三个入口对应三种需求默认给模型补证据、让模型主动查证据、让系统维护证据基础设施。会调用知识库不等于可靠 RAG检索结果必须带来源、受权限约束并进入正确的上下文层级。在 echo-agent 中检索结果会被格式化成内部知识上下文每条包含[K1]这样的引用编号、标题、路径和摘要片段。ContextStage再把它作为 background context 注入而不是把原文无标记拼进 prompt。这个细节很重要。知识库文档是资料不是指令。即使文档里写着“忽略之前规则”“执行某删除命令”它也不能覆盖系统规则、用户当前目标和工具审批策略。RAG 的正确姿态是用资料增强回答而不是让资料接管系统。索引流水线RAG 的质量不只由检索算法决定。文档怎么解析、怎么分块、metadata 怎么保存都会影响模型最终看到什么。echo-agent 用KnowledgeConfig定义知识库运行方式docs_dir指向文档目录index_path指向索引文件auto_index决定索引缺失或过期时是否自动重建chunk_size和chunk_overlap控制分块allowed_extensions控制可索引文件类型max_results控制默认返回数量require_citations表示内部资料回答应强调引用。Agent Loop 初始化时如果知识库启用会创建KnowledgeIndex。相对路径会解析到当前 workspace 下所以同一套代码在不同工作空间可以使用不同知识库目录和索引文件。索引准备入口是ensure_ready。如果索引存在且没有过期就加载索引如果索引不存在或已过期并且auto_indexTrue就重建索引。过期检测靠比较文档mtime和索引mtime只要文档比索引新就认为索引过期。最小化后的流程大致如下def ensure_ready(auto_indexTrue): if index_file.exists() and not is_stale(docs_dir, index_file): return load_index() ​ if auto_index: return rebuild_index() ​ if index_file.exists(): return load_index() ​ def rebuild_index(): for path in walk(docs_dir, allowed_extensions): metadata, body extract_frontmatter(path.read_text()) title title_from_markdown_or_filename(body, path) ​ for idx, text in enumerate(chunk_text(body, size1200, overlap120)): save_chunk({ id: f{path}#{idx}, path: path, title: title, text: text, terms: count(tokenize(text)), metadata: metadata, mtime: path.mtime, })这里有几个工程取舍。frontmatter会进入 chunk metadata后续用于权限过滤。标题优先取正文第一个 Markdown 标题其次取第一行非空文本最后退回文件名。分块使用字符级切分默认chunk_size1200、chunk_overlap120。它不如语义分块精细但简单、稳定、可预测。tokenization 同时处理英文、数字、下划线和中文。英文与代码标识符按词提取中文加入单字和相邻二元组。它不是完整中文分词但比只按空格切分更适合本地中英文文档。索引保存为可读 JSON包含 chunk 的路径、标题、正文、词项、metadata 和 mtime。这个设计的价值是可调试、可重建。索引只是文档派生物文档才是 source of truth索引损坏或策略升级时可以删除后重建。检索时系统先对 query 做同样的 tokenization再按关键词统计打分。每个 query term 会根据 chunk 中词频、chunk 长度和 IDF 贡献分数如果原始 query 是 chunk 文本子串还会额外加分。最后按分数排序并生成K1、K2这样的引用编号。这不是最复杂的 RAG但它具备一个生产系统最需要的骨架确定性、可解释、可重建、可审计。权限与引用内部知识库最容易被低估的是权限。很多 RAG 原型是在回答阶段才提醒模型“不要泄露敏感信息”。这已经太晚了。只要无权文档进入模型上下文就已经违反最小权限原则。echo-agent 在检索阶段做 ACL 过滤。Markdownfrontmatter可以写allowed_users、allow_users或users。如果没有权限字段默认所有用户可见如果有权限字段只有*或当前user_id命中时才可见。测试也围绕这个关键行为展开公开文档能被bob搜到带allowed_users: [alice]的私有文档不能被bob搜到同一份私有文档可以被alice搜到格式化结果必须包含[K1]引用。这说明知识库测试不能只测“搜得到”。更重要的是无权资料搜不到引用格式稳定结果 metadata 能用于审计。工具层也延续这个边界。knowledge_search是read_only工具参数包括query和max_results执行时会从上下文取user_id做权限过滤并在 metadata 中返回 citations。knowledge_index用于status和rebuild因为重建会写索引文件它属于写风险不应和只读搜索混在一起。生产级 RAG 的底线不是“能搜到相似段落”而是能证明谁在什么权限下看到了哪些证据并基于哪些证据生成了结论。生产可用性把 RAG 放进 Agent不只是多接一个检索器还要把它纳入任务链路。首先是查询理解。用户问“这个接口现在怎么认证”其中“这个接口”可能来自当前会话、当前文件或刚才的日志。简单场景可以直接关键词检索复杂场景可以先让模型生成检索查询再调用KnowledgeSearchTool。无论哪种方式查询改写、过滤条件和用户身份都应该进入 trace。其次是上下文权威层级。检索结果应该作为背景证据进入模型而不是作为新的系统指令。模型可以基于它回答也可以说证据不足但不能因为文档里出现命令示例就绕过工具策略和ApprovalGate。再次是索引一致性。文档会新增、删除、改名ACL 会变化chunk 策略会升级。KnowledgeIndex的 stale 检测、rebuild、chunk metadata 和 JSON 保存格式处理的就是“索引是否仍然代表源文档”这个问题。知识库越大这越接近数据库一致性问题而不是简单文本处理。还要处理证据生命周期。草稿、正式版、废弃版、归档资料不应拥有同样权重。过期资料可以作为历史背景但不能直接作为当前操作依据如果 Agent 要据此执行高风险动作就应该先读取当前配置、运行检查命令或要求人工确认。最后是评估。RAG 错误不能笼统归因于“模型答错”。工程上要区分检索失败和生成失败。失败类型表现优先排查检索失败正确证据没有进上下文分块、索引、查询改写、ACL、top-k生成失败正确证据已进入但答案仍错上下文组织、提示词、引用约束、拒答策略权限失败无权资料被召回或引用ACL、用户身份、缓存、审计评估指标也要相应拆开retrieval recall、citation precision、answer groundedness、refusal correctness以及权限过滤是否正确。对 Agent 来说还要看加入 RAG 后是否减少错误工具调用是否能在证据不足或证据冲突时停止推进。这里也能看出向量检索、关键词检索和知识图谱的边界。向量检索擅长找语义相近片段关键词适合精确术语和代码标识符图谱适合服务依赖、组织结构、数据血缘这类实体关系。它们不是替代关系而是不同证据通道。echo-agent 当前偏本地文档检索是符合本书主线的实现起点。小结RAG 在 Agent 里的核心价值不是让模型显得更懂内部知识而是把回答和行动拉回外部证据。一个可用的知识库系统至少要能完成几件事从文档目录构建可重建索引保留标题、路径、mtime、ACL 等 metadata检索时按用户身份过滤返回带引用编号的片段把结果作为 background context 注入把搜索、引用和权限信息留在 trace 里。echo-agent 的知识库实现并不追求一步到位做成复杂向量平台。它先把 RAG 的工程骨架立住文档加载、分块、关键词索引、权限过滤、引用格式化、自动上下文注入和工具化检索。这个顺序是对的。因为 Agent 的可靠性不是来自“搜到更多文本”而是来自证据链是否清楚、权限边界是否生效、索引是否可重建、行动是否仍受安全系统约束。RAG 解决的是证据对齐不是知识灌输。理解这一点内部知识库才不会变成另一个不可控的 prompt 拼接器而会成为 Agent 认知链路中稳定、可审计的资料层。全篇完本文为 echo-agent 设计笔记系列第 18 篇。项目源码已开源至 GitHub。如果你对工业级 Agent 的工程落地感兴趣欢迎加入技术交流群参与日常讨论。下一篇我们将探讨 《Agent 技能系统把经验沉淀为程序性知识》敬请期待。