当你一个人扛起了一个还算硬核的 RAG 系统底座(涵盖了 VFS 2.0、实时 ACL 和 Git 同步)后,最容易犯的工程错误是什么?
是无节制的数据贪婪。
系统一上线,周围就涌来了大量的声音:“既然 Git 能接,能不能顺便把钉钉的聊天记录也接进来?”、“能不能把公司的 Jira Issue 全导进来做向量化?”、“要不把运维系统的实时告警日志也接了吧,这样排查问题快!”
如果我只是一个为了 KPI 冲刺的执行者,我可能会兴奋地接下所有需求,用各种 Python 脚本和 Webhook 写一堆脏代码把数据全怼进向量库里。
但作为这套系统唯一的架构师兼运维人员,我对这种缺乏边界的“大杂烩”接入充满了天然的恐惧。数据新鲜度的过期、无休止的同步状态断层、混乱且无法映射的权限隔离,会像多米诺骨牌一样,在几个月内把高昂的维护成本转移到我个人头上,最终把系统彻底压垮。
因此,在思考“接下来想接住什么样的知识源”这个问题时,我给自己定了一个不讲情面的原则:宁可拒绝接入,也绝不破坏系统的架构纯粹性。
一、拒绝“野蛮生长”:确立知识源的“三大契约”
在 KH 的架构蓝图里,任何一种外部数据想要进入我们的检索宇宙,不能靠硬编码的“旁路脚本”。在 Spec-Driven Development (SDD) 的指导下,我们首先在文档里立下规矩:新知识源必须先签署我们定下的“三大契约”。
这 30% 的人类智慧:对架构熵增的硬核防御。
我宁愿牺牲前期的数据广度,也要用严格的契约把劣质数据挡在门外。
- SHA 溯源契约:你必须能提供唯一的标识符(如版本号、Hash 值或精确时间戳)。KH 内部有极其严格的
BaseSha防并发覆盖机制,如果你的数据不支持版本追踪,说明你不具备一致性基础,连进入暂存区(Staging)的资格都没有。- 权限对齐契约:如果源系统的数据是分密级的(比如部门可见),你必须能将这些密级完美映射为 KH 底层
document.access_policy支持的 GORM 权限格式。安全降级是绝对的红线,如果做不到,别来沾边。- 原子性同步契约:接入过程必须适配我们
internal/gitsync/service.go中基于状态流转的异步任务引擎。支持失败重试、支持断点恢复、支持事务回滚。
二、架构的柔性与硬度:由 SyncHook 驱动的插件式生态
那怎么在不弄脏核心代码的前提下,优雅地接住那些通过了契约的外部系统呢?
我不想在核心的 service.go 里写满了一坨坨 if sourceType == "juzi" {} else if sourceType == "jira" {} 这种极其丑陋的业务判断。我选择了一种极具后端设计审美的方案:引入 SyncHook 注册表机制。
实战:句子文档 (JuZiDocs) 的解耦接入
以我们实际接入的第三方库 JuZiDocs 为例。在 internal/synchook/juzidocs.go 中,我通过 HookRegistry 暴露出了同步生命周期的几个关键拦截点:PreSync、PostSync、OnError。
我们把那些针对 JuZiDocs 奇葩 API 的清洗逻辑、特殊格式转换逻辑全部隔离在这个独立的 Hook 插件里。当核心的同步任务引擎流转时,它只负责机械地触发 Hook 接口,根本不在乎背后是哪家厂商的数据。
这种“主干硬核、枝叶柔性”的插件化架构,确保了 KH 在横向扩张时,核心的索引和权限引擎能够保持极致的“圈地自萌”。
三、从“被动检索”到“主动调用”:MCP 的破局
还有一类数据,比如实时的物流订单状态,或是按秒刷新的 Kubernetes Pod 负载。这类数据我们是绝对不想“同步”进来的。
让 RAG 去做这种高频时效数据的向量化,不仅是对 GPU 算力的犯罪,更是架构上的灾难。对于这类场景,我们拥抱了目前业内极具破坏力的概念:MCP (Model Context Protocol) 协议。
在 pkg/mcp 模块的指导下,我转变了思路:我们不搬运数据,我们只分发工具。
我们将不再试图把这些高频动态源同步成 Markdown 存起来。相反,我们将针对它们封装出符合 MCP 标准的 Tool(比如 query_order_status_tool 或 get_pod_logs),并直接挂载到 Agent 的能力清单里。
在这个视角下,知识源不再是“死的数据切片”,而是“活的函数调用”。在 Agent-first 的架构下,大模型可以根据上下文,自主决定是去 search_knowledge_base 查历史规范,还是去调用 MCP Tool 查此时此刻的最新状态。这种基于协议的解耦,才是 KH 从“文件柜”走向“泛知识中枢”的终极钥匙。
四、Hermes 闭环:基于反馈的稳健演进
在规划未来的接入版图时,我引入了 Hermes 闭环 的思想:不追求大跃进,而是基于系统自身的运行反馈稳步扩张。
- 第一阶段:存量夯实(现在的死磕)
利用异步任务引擎(AsyncRunner),死磕 Git 同步和文件上传的边界场景。解决极高并发下SyncStatus的最终一致性问题。在日志里沉淀所有的异常 Case。 - 第二阶段:受控 WebHook(基于契约的扩展)
当系统在第一阶段证明了自己的健壮性后,基于完善的SyncHook,开放标准化的 WebHook 接收端。允许那些相对静态的外部系统(如 Confluence)主动推送变更。KH 只做守门人:执行增量 Hash 校验和严格的权限对齐。 - 第三阶段:MCP 泛化接入(未来的利刃)
针对高频、动态的业务库,全面拥抱 MCP 工具化。保持 KH 系统内核的绝对干净,将处理复杂实时逻辑的职责“外包”给大模型自身的 Tool Use 调度能力。
结语:架构师的“克制”美学
在一个什么都想用 AI 强行重做一遍的狂热时代里,敢于承认“有些数据不适合被 RAG”是需要技术勇气的。
Knowledge Hub 之所以能保持逻辑上的清晰与轻盈,正是因为我在扩张的岔路口上,用一堆冰冷的“契约”、“Hook”和“MCP 协议”挡住了那些不合理的数据诉求。
架构的优雅不仅在于你写出了什么牛逼的代码,更在于你顶住压力拒绝了什么。
作为这个系统的唯一负责人,守住这条边界,坚决不让系统滑向数据堆填区的深渊,才是我对这个工业级项目生命力最负责的承诺。