Skip to content

知识库

知识库让 Agent 的答案有根据 —— LLM 不用凭训练数据猜,因为它每一轮都 可以搜你的 runbook、过去的 postmortem、团队文档。

存储结构

一个向量库,三种来源类型。

来源类型来自哪里只读?
vault内置 ongridio/vault playbook 合集(截至 2026-05-29 有 96 份 markdown 文档)
repo你注册的 git URL —— public HTTPS 或按仓库身份的 SSH否(编辑设置 + 重新同步)
upload通过 SPA 的 /knowledge 页直接上传(md / txt / pdf / docx)否(按行编辑 / 删除)
manual通过内联编辑器粘贴 markdown

四种类型共享一个 Qdrant collection(ongrid_knowledge)和一个 embedding 模型。搜索命中会返回 source_type payload 字段,UI 据此渲染对应 的 "from vault" / "from your repos" 徽章。

ADR-028 —— 知识来源分层

为什么一个 collection:另一种方案(每个来源类型一个 collection)逼着 LLM 每个问题调 N 次搜索才能覆盖全面,把 tool-call 预算炸掉。一个 collection + source_type 过滤一次查询就拿到同等隔离。

Qdrant 客户端

窄接口,在 internal/manager/biz/knowledge/usecase.go:62

go
type QdrantClient interface {
    EnsureCollection(ctx context.Context, name string, dim int) error
    EnsurePayloadIndex(ctx context.Context, collection, field, schema string) error
    Upsert(ctx context.Context, collection string, points []qdrantx.Point) error
    DeleteByFilter(ctx context.Context, collection string, mustMatch map[string]any) error
    DeleteByID(ctx context.Context, collection string, id uint64) error
    GetPoints(ctx context.Context, collection string, ids []uint64) ([]qdrantx.SearchHit, error)
    Search(ctx context.Context, collection string, vector []float32, opts qdrantx.SearchOpts) ([]qdrantx.SearchHit, error)
    Scroll(ctx context.Context, collection string, opts qdrantx.ScrollOpts) (*qdrantx.ScrollResult, error)
}

生产用 internal/pkg/qdrantx 实现,测试里可以 fake。Qdrant 跟 docker-compose 一起发;通过 ONGRID_QDRANT_URL 也支持外接 Qdrant。

vault

vault 是公开的 git 仓库(不要认证),装预先整理好的诊断 playbook。 覆盖话题(截至 2026-05-29):

  • 网络:DNS / TCP / TLS / HTTP 排查手册。
  • Kubernetes:pod / node / kubelet 症状-原因映射。
  • Linux:进程 / 内存 / 磁盘 / journald 调查路径。
  • 数据库:MySQL slow-log 分诊、PostgreSQL 复制延迟。
  • 诊断:70+ 按症状索引的 playbook。

ADR-029 加了云端同步:manager 按计划拉最新 vault(默认 24h,通过 SPA 设置 配置),有变化就重 embed。本地 checkout 在 /var/lib/ongrid/repos/<vault_id>/ 下;qdrant 上的点带 source=vault 标签, 所以 Sync 只删 vault 的点,从不删你自己的。

别把 vault 当成你的 repo

vault 是内置来源 —— 它从不出现在 /knowledge/repos 的 CRUD 页面里。代码用 isBuiltinVault() / is_builtin 卡这个;别再 substring-match ongridio/vault (见 recurring-pitfalls 反馈)。

你自己的 repo

POST /v1/knowledge/repos,body 带 { url, name } 注册一个 git 仓库。下次 同步 tick 里 manager 会:

  1. git clone --depth=1(或者目录已存在就 git pull)到 /var/lib/ongrid/repos/<id>/
  2. 走树找 .md / .txt / .rst / .yaml / .yml / .toml / .json 文件。
  3. 用配置的 embedding 模型对每个文件 embed。
  4. 原子替换这个 repo 的点集(source=reporepo_id=<id>)。

SSH 认证

按仓库身份,通过 ssh_identities 表和 SPA 的 /knowledge/identities 页 管理。Repository带 provider 字段 —— 身份表是 git 凭证的唯一来源 (ADR-023)。

每次同步把 GIT_SSH_COMMAND 指向身份的 key 文件,这样每个 repo 的克隆都用 自己的 key,不会污染 $HOME/.ssh/

HTTPS 认证

Public HTTPS repo 免认证克隆。Private HTTPS 认证暂缓:SSH 已经覆盖了实际 用例之后,原来的 GitHub-PAT 路径被移走了。在 ADR-018 的 RepoFetcher 落 地前,private 用 SSH。

上传

/knowledge/upload 页接受:

格式提取器
.md.txt直接读 + 切块
.pdfdocextract(internal/pkg/docextract
.docxdocextract

每次上传变成 knowledge_docs 表一行 + qdrant 一个点,带 source=upload。 "组织知识" 树里支持按行内联编辑和删除。

搜索

LLM 拿到一个 query_knowledge BaseTool —— schema 在 query_knowledge_basetool.go。 入参:query,可选的 source_type 过滤,可选的 top_k。返回: {score, source, title, snippet, url?} 命中列表。

coordinator persona 被告知:碰到 "怎么做" / "为什么会出现 X" / "Y 的 runbook 是什么" 这类问题先调它 —— 一次知识搜索的代价远低于一次 5 工具的调查, 而调查最后落到的还是 playbook 已经写好的答案。

chat UI 也提供一个 Quick Action 按钮 "搜索知识",让操作员不进 chat 也能查同 一索引。

另见

  • 技能 —— query_knowledge 是技能 registry 里桥接出来的 18 个 BaseTool 之一。
  • RCA —— investigator persona 把知识搜索当第一手工具调用。
  • 架构 —— Qdrant 在 L1 栈里的位置。