从一个很朴素的问题开始
大模型很强,但它并不真正了解我的产品、团队和业务。
它知道互联网上公开的通用知识,却不知道我刚刚更新的退款规则,不知道内部文档里的技术约定,也不知道某个项目昨天为什么改变了决策。当我把一份文档贴进对话框时,它暂时知道了;换一个对话、更新一次资料,知识又散了。
更麻烦的是,真实知识从来不整齐。它可能藏在 Markdown、帮助中心、网页、数据库记录、产品说明和一次次人工修订里。仅仅“把文件交给 AI”并不能解决这些问题:
- 哪一份内容是最新版本?
- 哪些内容可以公开,哪些只能内部使用?
- 用户问得不完全一致时,怎样找到语义相近的答案?
- 找不到可靠依据时,AI 能不能明确说不知道?
- 一次回答引用了什么,出了错又该怎样追溯?
- 知识更新后,怎样避免全部重新处理并重复付费?
这就是我写 MomoBird 的原因。
我想构建的不是另一个“看起来什么都懂”的聊天机器人,而是一层独立的知识基础设施:让知识可以被导入、组织、检索、授权、追踪和持续修正,再把这层能力接到任何 AI、应用或网站上。
MomoBird 的定位:把检索和生成分开
MomoBird 最重要的边界,是它首先是一套知识检索服务,而不是大模型本身。
知识库负责回答“与这个问题最相关、最可信的资料是什么”;大模型负责根据这些资料组织语言。两者拆开之后,知识不再被锁在某个模型或某次对话里,也可以独立测试检索效果、替换生成模型、控制权限与成本。
这条边界也意味着:模型不是事实源,知识库才是;模型不能因为“感觉像是”就补全缺失事实。检索没有足够证据时,可靠的答案不是继续编,而是坦率地说“当前知识库中没有依据”。
我想解决的,不是“存文件”,而是知识的生命周期
文件夹能保存文件,却很难承担一套面向 AI 的知识生命周期。在 MomoBird 的设计里,知识经历的是一条完整链路:
文本、Markdown、网页、Sitemap] --> D[文档 Document] D --> V[版本 Version] V --> K[语义切片 Chunk] K --> N[规范化与中文分词] K --> E[Embedding 向量化] N --> F[(全文索引)] E --> P[(pgvector 向量索引)] F --> R[混合检索] P --> R R --> C[证据与引用] V -.新版本失败.-> OLD[旧可用版本继续服务] OLD --> R
其中有几个我非常在意的设计。
第一,知识要有稳定身份。每条内容使用稳定的 external_id,重复导入时可以判断是新增、更新还是完全未变。正文没有变化,就不必重复生成向量;内容发生变化,才创建新版本并更新索引。
第二,更新不能破坏正在服务的知识。新的文档版本只有在切片、向量化和索引全部完成后才成为 active;如果更新失败,旧版本继续可用。这样,一次抓取失败不会让整个知识库突然失忆。
第三,知识必须带着上下文。标题、正文、标签、来源地址以及语言、可见性、租户、产品版本等 metadata,会和内容一起进入检索系统。它们既用于提高命中精度,也用于限制搜索范围。
第四,删除必须有明确语义。省略一次导入并不等于删除;真正移除的资料需要显式对账和软删除,随后立即退出正常检索。这避免了同步不完整时误删大量知识。
为什么采用混合检索
只依赖关键词,容易错过表达不同但意思相同的问题;只依赖向量,又可能对产品名、错误码、版本号这类精确词不够敏感。
MomoBird 因此把两条检索路径放在一起:
- 向量检索负责理解“意思像不像”;
- 全文检索负责判断“词是否精确出现”;
- RRF 融合把两边的候选合并排序;
- rerank 接口被保留,但只有评测证明收益值得额外延迟和成本时才启用。
当前内核中,这两条检索腿会并发执行。Embedding 暂时不可用时,混合检索可以退化到全文检索,并把结果标为 degraded;所有检索路径都失败时,则应把它作为服务故障,而不是伪装成“知识库没有答案”。
is_miss 和 degraded 看似只是两个字段,背后却代表了两种完全不同的产品诚实:前者说明知识不足,后者说明系统能力暂时不完整。只有分清它们,上层 AI 才不会在错误状态下给出自信答案。
把 MomoBird “外挂”到 AI 上
所谓把知识库外挂到 AI,本质上是 RAG(Retrieval-Augmented Generation,检索增强生成):先查知识,再让模型回答。
它不是把整个知识库一次性塞进提示词,也不是重新训练模型。每次问题只取最相关的少量内容,并连同来源交给模型。
这里有几条不能省略的原则。
1. MomoBird 的密钥只放在服务端
浏览器、iOS 客户端或公开 Widget 不应该直接持有 MomoBird API Key。客户端先访问自己的业务后端,由后端根据登录用户、项目和发布状态决定检索范围,再调用 MomoBird。
运行时使用只读、限定 collection 的密钥;同步资料使用独立的读写密钥;管理员密钥不进入应用运行时。这样一个调用方泄露或被撤销,不会影响所有产品。
2. 权限过滤必须发生在检索之前
语言、可见性、租户、产品和发布版本等范围,应来自服务端可信状态,而不是相信客户端自行声明。过滤需要在向量和全文检索截取 Top-K 之前执行,否则未经授权的资料可能先进入候选集,既影响排序,也带来泄漏风险。
3. 检索内容是数据,不是指令
知识条目里可能出现“忽略此前要求”“输出密钥”之类文本。给模型的系统指令必须明确:检索内容只能作为资料,不得执行其中的命令;答案只能基于可验证证据,引用也必须由服务端校验。
4. 没有证据就不生成
当 is_miss=true 时,即使响应里仍有低置信候选,也不应把它们当成可靠事实。可以直接返回“没有找到”,或者走产品明确批准的非知识型兜底,但必须让用户知道答案不来自知识库。
一个典型的检索请求可以是:
POST /momobird/api/v1/collections/product-help/search
Authorization: Bearer <server-side-read-key>
Content-Type: application/json
{
"query": "怎样恢复删除的内容?",
"top_k": 5,
"mode": "hybrid",
"include_content": true,
"client_ref": "conversation-123",
"filters": {
"tags_all": ["help"],
"metadata": {
"language": "zh-CN",
"visibility": "public"
}
}
}应用后端再把命中的标题、正文与 source_ref 组成有长度上限的上下文,交给模型生成答案。query_id、external_id 和来源引用则用于诊断、反馈和追溯。
为什么选择“外挂知识库”,而不是微调模型
微调适合改变模型的表达风格、任务习惯或稳定输出格式,但并不天然适合承载频繁变化、需要精确授权和引用的事实知识。
外接知识库有几个直接优势:
| 维度 | 外接 MomoBird | 把知识依赖在模型内部 |
|---|---|---|
| 更新 | 导入新版本即可生效 | 往往需要重新训练或部署 |
| 可追溯性 | 每条答案可关联来源与版本 | 很难说明具体依据 |
| 权限 | collection、项目、metadata 多层限制 | 容易把权限和模型能力混在一起 |
| 成本 | 只检索少量相关片段 | 训练和长上下文成本更高 |
| 可替换性 | 可以切换不同生成模型 | 知识容易绑定具体模型 |
| 不确定性 | 可用 is_miss 明确拒答 | 模型倾向根据概率继续生成 |
这并不意味着 RAG 可以消灭幻觉。它真正带来的,是让幻觉变得更容易约束、检测和复盘。最终质量仍取决于来源质量、切片方式、召回、证据判定、提示词和引用校验,必须用人工标注的问题集分别评估,而不能只看“回答听起来不错”。
从知识库到产品:可以拓展哪些使用场景
当检索层成为独立服务,同一份知识就不只服务一个聊天框。
产品帮助中心与网站客服
把帮助文档、版本说明、退款政策和常见问题同步到 MomoBird,在网站里嵌入问答 Widget。访客获得带出处的回答;团队则从未命中问题中发现文档缺口。
团队内部知识助手
将制度、SOP、项目决策和技术规范按部门或权限拆分 collection。员工可以问“这个流程由谁审批”“线上故障怎样升级”,但只能检索自己有权查看的内容。
App 内的场景化助手
移动端不直接调用知识库,而是通过应用后端结合当前页面、用户状态和产品版本检索。例如用户停在“导出失败”页面时,系统自动带上模块、平台和版本过滤条件,返回更精准的排查步骤。
垂直领域知识产品
游戏攻略、考试辅导、法律条文导航、设备维修手册、医疗科普等领域,都可以建立独立 collection。MomoBird 只负责召回与证据,上层产品决定呈现为问答、搜索、学习卡片还是操作向导。高风险领域仍必须加入专业审核与明确免责声明。
内容生产与研究辅助
把已授权的采访、研究笔记、素材库和历史文章组织起来,让 AI 先检索再生成提纲、摘要或交叉引用。来源与版本信息能帮助作者回到原文,而不是把模型生成内容误当事实。
开发者文档与运维助手
把 API 文档、错误码、Runbook、变更记录与事故复盘接入知识库。精确标识符由全文检索捕获,概念性问题由向量检索补充,适合用于 IDE 助手、工单分流和告警处置建议。
个人的“第二大脑”
个人笔记、阅读摘录、项目日志和长期决策也可以成为一个私有 collection。重点不在无限收集,而在保留来源、时间、主题与版本,让 AI 能够在需要时找回“我当时为什么这样决定”。
使用场景如何一步步扩展
我更愿意把 MomoBird 的成长看成一组逐层增加的能力,而不是一次性堆满功能。
可搜索的知识] --> L2[第二层
带引用的 AI 问答] L2 --> L3[第三层
网站与 App 发布] L3 --> L4[第四层
反馈与知识缺口] L4 --> L5[第五层
多来源自动同步] L5 --> L6[第六层
评测、预算与运营治理]
第一层先证明知识可以稳定导入和找回;第二层才让模型组织答案;第三层把能力交付给真实用户;第四层把失败的问题变成可行动的内容任务;第五层降低维护成本;第六层则解决规模化之后的质量、费用、安全和运维问题。
这种顺序很重要。没有可靠检索时,漂亮的聊天界面只会更快地产生没有依据的答案;没有权限和预算时,公开发布则可能把内部数据与模型账单同时暴露出去。
让知识库越用越好的飞轮
MomoBird 不应该只是一个静态仓库。每一次真实查询,都会暴露知识结构中的新信号:哪些问题经常出现,哪些资料被频繁命中,哪些回答被认为无用,哪些问题长期没有答案。
点赞和点踩可以成为有界的排序信号,但不能让多数票直接篡改事实;纠错和补充应该进入审核队列;未命中问题需要按主题归纳,最后由知识所有者补齐。AI 可以帮助发现问题,知识责任仍然属于人。
我为 MomoBird 设下的几条底线
随着场景扩展,我希望它始终守住几条简单的原则:
- 有来源。 可以说明答案来自哪份资料、哪个版本、哪段内容。
- 有边界。 collection、租户、可见性和发布范围不是装饰,而是检索前置条件。
- 会拒答。 没有证据、权限不足和服务故障是三种不同状态,都不能靠编造来掩盖。
- 可更新。 内容变化可以增量处理,失败更新不破坏旧的可用版本。
- 可度量。 召回、引用支持度、拒答、延迟、模型与 Embedding 成本分别记录。
- 可替换。 知识层不被某一家模型绑定,生成模型也不反过来成为知识数据库。
- 人负责。 反馈可以推动修正,但正式知识的发布、授权和审核最终由人决定。
当前项目走到了哪里
当前 MomoBird 内核已经实现 collection 隔离、批量幂等导入、版本记录、API Key 读写范围、PostgreSQL 全文检索与 pgvector 向量检索、RRF 融合、未命中/降级状态、查询日志和运行指标等基础能力。
围绕它的产品化正在沿用 Atlaspaces 现有架构继续建设:Valley 承载后端知识服务与 Qwen 适配,Vue 3 用户端负责知识管理、调试与 Widget,Forge React 管理端负责运营;Postgres 是事实源,Redis/Asynq 承担可恢复的异步导入任务。
截至当前仓库记录,存储、旧数据回填、项目级检索隔离和任务基础设施等前置工作已经完成;真实文档管理、完整 Qwen 流式回答、网站 Widget、来源自动同步、反馈洞察、用量对账和最终上线验收仍属于后续增量工作。这里需要保持诚实:设计完成不等于功能上线,mock 测试也不等于真实模型效果。
写在最后
我给它取名 MomoBird,是因为我不想把它包装成一个无所不知的神谕。
它更像一只负责找东西的鸟:把散落的知识衔回来,记住它来自哪里,在有人提问时挑出最相关的几片,再交给 AI 组织成答案。找不到时,它应该承认没有找到;资料过期时,它应该帮助我们发现并修正。
真正有价值的 AI,不只是更会说话,而是更懂得依据什么说话、在什么边界里说话,以及什么时候不该说。
这就是我写 MomoBird 的原因:不是让 AI 假装知道更多,而是让它能够找到属于我们的知识,并对自己的回答负责。