构建自定义知识库
Alauda Hyperflux 插件自带一个内置的 系统知识库,涵盖 Alauda Container Platform (ACP)和 Alauda 产品文档。除此之外,Hyperflux 还维护着一个独立的 用户知识库, 你可以将自己的内容填充进去——内部 runbook、SRE playbook、设计文档、内置语料库中没有 提供的 Alauda 产品文档版本,或者任何其他私有 Git 仓库。Hyperflux 在每个问题上都会同时从 这两个知识库中检索并合并结果,因此添加自定义语料库会在增强内置产品知识的同时, 而不是替换它。
本指南介绍管理员驱动的路径:使用容器内的 builder,将一组 Git 仓库批量导入用户知识库。 (对于终端用户通过聊天 UI 上传文件,请使用 v1.3.1 中新增的 BYO Knowledge 工具——目标 位置相同,但入口不同。)
该工作流在部署后的 smart-doc pod 内部运行。该镜像已经包含 builder 源码、
embedding 模型以及正确的 Python 环境,并且 pod 已经具备到用户知识库 PostgreSQL 的连通性。
你只需要一个要导入的仓库清单,以及对 global 集群的 kubectl exec 访问权限。
目录
embedding 流水线的工作方式前提条件第 1 步 — 描述你的语料库第 2 步 — 将 manifest 复制到 smart-doc pod 中第 3 步 — 在 pod 内运行prepare第 4 步 — 在 pod 内运行 embed第 5 步 — 为用户知识库创建 BM25 索引(一次性)(可选)多集群:dump 和 restore替换内置系统知识库(高级)重新发布节奏注意事项embedding 流水线的工作方式
smart-doc builder 会分两个阶段将 Git 仓库列表转换为向量化知识库:
- Prepare — 克隆仓库,按标题和 chunk 大小拆分每个
.md/.mdx文档,然后调用 LLM (与运行中的 Hyperflux 插件已配置的那个相同)为每个文档生成一段摘要和若干代表性问题。 输出:documents.json。 - Embed — 加载
gte-multilingual-baseembedding 模型,对 chunks 和每篇文档的摘要进行 embedding,并将它们写入用户知识库 PostgreSQL(docvec_user_kb),存储到运行中的服务 读取的 collection 名称下(默认是user_defined_kb)。
完成 embedding 后,运行中的服务会在下一次查询时读取到新内容——无需修改 chart,也无需 重启 pod。系统知识库不会受到影响。
注意: 用于 hybrid retrieval 的 BM25 索引不是由 embed 步骤构建的。内置的系统 KB dump 包含预先构建好的 BM25 索引,但用户 KB 数据库在安装时是空创建的。如果你的部署启用了 hybrid retrieval(默认开启),你必须为用户 KB collection 额外创建一次 BM25 索引——见 第 5 步。
前提条件
- 具备对运行 Hyperflux 的集群(global 集群)的
kubectl访问权限,并拥有cpaas-system命名空间下smart-docpod 的exec权限。 - 对你想导入的每个 Git 仓库都有读取权限。如果是私有仓库,请准备好 HTTPS 用户名/令牌 对。
- 一个配额足够的 LLM endpoint。 prepare 阶段会对每个源文档调用一次 LLM(对于 ACP 规模的 知识库,大约需要 1,000–3,000 次调用)。默认情况下,容器内命令会复用已为 Hyperflux 配置 的 LLM endpoint(即安装时通过 LLM Base URL / LLM API Key / LLM Model Name 设置的那个)。如果你的账号受到速率限制,请准备一个配额更高的独立 endpoint,并在 exec 会 话中覆盖环境变量(第 3 步)。
你不需要单独的工作站 Python 环境、gte-multilingual-base 的下载副本、独立的 PostgreSQL
实例,也不需要克隆 smart-doc 仓库——smart-doc 容器已经内置了这些内容。
第 1 步 — 描述你的语料库
创建一个 JSON manifest,列出你想导入的每个 Git 仓库。将其保存在本地机器上,命名为
my-kb.json(任意名称均可——第 2 步会把它复制到 pod 中)。
如果要在一次运行中导入多个仓库,请添加更多 repos 条目。
字段说明:
第 2 步 — 将 manifest 复制到 smart-doc pod 中
第 3 步 — 在 pod 内运行 prepare
在 serve 容器中打开一个交互式 shell,并运行 prepare 阶段:
有用的参数:
--dryrun— 克隆仓库并打印文档列表,但不调用 LLM。建议先用它确认你的sub_dirs和doc_type过滤条件是否符合预期。
注意:
prepare不会在多次运行之间缓存 LLM 响应——每次执行都会针对每个源文档重新发起 一次 LLM 调用。请为每次重跑预留完整的单文档成本,只有在源语料库确实变化时才重新运行 prepare(否则只需基于现有documents.json重新运行embed)。
第 4 步 — 在 pod 内运行 embed
保持在同一个 shell 中(这样第 3 步中的环境变量仍然生效):
chart 已经导出 EMB_MODEL_NAME=/opt/gte-multilingual-base、DEVICE=cpu 和
PG_USER_KB_CONN_STR(指向用户 KB 数据库 docvec_user_kb),因此你不需要传递
--emb-model 或 --device。请显式传递 --pg-conn-str "${PG_USER_KB_CONN_STR}",因为脚本
的默认值是系统 KB 的连接字符串(PG_SYS_KB_CONN_STR)。
各参数的作用:
警告: 当
--vector-types包含doc_summary,但documents.json是由未设置ENABLE_GEN_QUESTIONS=true的 prepare 运行生成时,embed 会静默产出零个摘要向量, 只会在末尾记录no_summary=N。如果你看到no_summary数量很高,请先带上ENABLE_GEN_QUESTIONS=true重新运行 prepare,然后再重新运行 embed。
注意: serve 容器默认在 CPU 上运行(
DEVICE=cpu)。在 CPU 上嵌入 5,000 个 chunks 大约需要一小时;对于较小的内部语料库(几百篇文档),则只需几分钟。如果你需要 GPU 吞吐量, 请在 GPU 调度的 pod 上运行构建(本文不展开),并使用后文描述的多集群 dump-and-restore 路径。
embed 步骤不会调用 LLM;你可以基于同一个 documents.json 低成本重跑它,以尝试不同的 chunk
大小,或向现有 collection 追加新文档。
第 5 步 — 为用户知识库创建 BM25 索引(一次性)
用户 KB 数据库在安装时是空创建的——与内置的系统 KB dump 不同,它不包含预构建的 BM25 索引。如果启用了 hybrid retrieval(默认开启),请在首次 embed 运行后创建一次索引:
如果没有这个索引,hybrid-retrieval 路径会静默退回为仅 dense 的用户 KB 检索(仍然会返回结果, 只是不会有精确关键词召回)。
就这样——不需要修改 chart,也不需要重启 pod。运行中的服务已经会在每次查询时从
docvec_user_kb / user_defined_kb 读取,因此你的自定义语料库会立即开始影响回答。你可以在
聊天 UI 中提交一个代表性问题来确认。
(可选)多集群:dump 和 restore
如果你希望只构建一次语料库并将其推送到多个集群,可以在第 4 步之后对用户 KB 执行
pg_dump,然后在每个目标集群上恢复:
然后在每个目标集群上执行第 5 步(BM25 索引)——索引是按数据库生成的,单独恢复到空数据库时
不会自己保留下来(如果恢复到一个已有内容的数据库,且 dump 中包含 BM25,则会进行合并;对于
全新的用户 KB,请在 restore 之后运行 CREATE INDEX)。
注意: 如果将用户 KB dump
pg_restore到一个已经存在用户 KB 内容的目标集群(例如之前 的 BYO 上传),会在 langchain 表的 CREATE 上发生冲突。若要进行干净覆盖,请改用 chart 的 swap 机制,或者先在目标上删除并重新创建docvec_user_kb。只有在目标用户 KB 为空时, 直接pg_restore才是最安全的方式。
替换内置系统知识库(高级)
上述工作流会将内容添加到用户 KB,而不会影响内置的产品知识。如果你的需求不同——例如, 内置的 Alauda 产品文档与你的环境不符,而你希望用内部版本替换它们——则可以重复同样的 容器内工作流,但目标改为系统 KB:
--pg-conn-str "${PG_SYS_KB_CONN_STR}"--collection-name <your-system-kb-collection-name>- 在 chart 中更新
pgconnect.pgCollectionName以指向你的 collection 名称,然后重新发布。
此路径需要修改 chart,并会在未来的 Hyperflux 版本升级中禁用自动系统 KB 升级(自动交换规则 扫描不会匹配你的自定义 collection 名称)。仅在用户 KB 增强不足以满足需求时才使用它。
重新发布节奏
自定义知识库的变化速度通常比产品文档更快。请根据你的源仓库制定重新运行 prepare → embed 的计划:
- 每日变化的 runbook → 每晚 cron(一个 Kubernetes
CronJob,以一次性任务方式运行相同的 容器内命令)重新嵌入到同一个user_defined_kbcollection。 - 每季度更新的架构文档 → 在每个发布边界手动重新发布。
针对同一个 collection 名称重新运行 embed 时,会使用确定性的 row ID(smart_doc_builder.py:38-48
中的 make_row_id),因此未变更的 chunks 会幂等地 upsert,而变更的 chunks 会覆盖——但
从 manifest 中移除的文档对应的行会变成孤儿。若要进行干净替换,请在重新嵌入前删除并重建
collection:
然后重新运行第 4 步以重新填充数据。langchain_pg_embedding 上的 BM25 索引会自动继续作用于新
行,因此你不需要重新运行第 5 步——除非你也删除了数据库本身(例如为了实现上文多集群
pg_restore 覆盖)。
注意事项
- 自定义语料库与 BYO Knowledge 工具上传共享同一个用户 KB。 终端用户通过聊天 UI 上传的
文件(v1.3.1 中引入)会落到与你的管理员精选语料库相同的
user_defined_kbcollection 中。 只要 URL 不冲突,它们就可以共存;实际上这通常没有问题,因为 BYO 上传使用的是不同的 URL 方案。如果你确实删除并重建了 collection(见“重新发布节奏”一节),该 collection 中的 BYO 上传也会与语料库一起被清除——如果你在意这些文件,请先备份。 - 系统 KB 的版本过滤不适用于用户 KB。 当用户提出一个与版本相关的问题(例如关于 ACP 4.3), 系统 KB 会按该版本进行过滤,但用户 KB 会返回跨所有版本的匹配项。如果你的自定义语料库是 多版本的,预计会有跨版本的 chunks 出现在回答中。
- embedding-model 不匹配 是最常见的静默失败:使用除容器内
/opt/gte-multilingual-base之外的模型构建的向量虽然可以被检索到,但得分始终接近 0,最终回答会退化为“我没有足够 信息”,且不会出现明显错误。本文描述的容器内工作流默认使用内置模型——只有在你明确知道 自己在做什么时,才覆盖EMB_MODEL_NAME。