摘要:本文是 VeapAI 实战系列第二篇,聚焦企业 AI 知识库中元数据标准与 Collection 的声明式管理。文章先点出知识库建设的两大痛点——字段口径混乱与向量集合手工创建易出错,随后介绍标准、字段、模板三层模型,说明如何通过元数据标准定义字段、由标准声明式创建 Milvus Collection,并借助 sync_state 状态字段与 schema_json 快照解决标准与集合的"两本账"一致性问题。文中还走读了源码入口与 Milvus 操作封装,总结了标准层的层级、版本、链路三个扩展点,并给出可复现步骤。
# 从零打通企业 AI 知识库全链路:VeapAI 实战(二)元数据标准与 Collection 声明式管理
> 关键词:Milvus 集合创建教程、元数据标准、动态表单 | 首发:CSDN | 同步:知乎 / 掘金
![本系列 8 步流程总览(当前:② 元数据标准与 Collection)]
## 问题先摆出来
做知识库最怕两件事:字段口径乱,和向量集合手工建。
前者好理解:政策库要"发文机关 + 文号 + 生效日期",工程库要"项目名称 + 预算金额 + 类别",每个主题一套字段,靠开发硬编码,加一个字段改一次代码。后者更隐蔽:手动在 Milvus 里建集合,维度写错、度量写错,向量一进去,检索结果全歪,还查不出哪一步错了。
VeapAI 的解法是把这两件事绑在一起:元数据标准定义字段,Collection 由标准声明式创建,数据库里还留了同步状态。
## 三层模型:标准、字段、模板
先看 `ai_metadata_standard` 和 `ai_metadata_field` 两张表。
`ai_metadata_standard` 关键字段:`code`(标准编码)、`title`、`parent_id`(支持子标准)、`version`、`llm_id`。注意最后这个字段,标准上直接挂 embedding 模型,后面向量作业的模型一致性约束靠它。
`ai_metadata_field` 关键字段:`standard_id`(归属标准)、`field_name`、`field_type`、`is_required`、`schema_json`。`schema_json` 是这张表的灵魂:存 JSON Schema 片段,支持类型、枚举、正则、范围、嵌套对象。前端动态表单按它渲染,加字段不改代码。
第三张是 `ai_metadata_standard_template`:模板表,`field_schema` 存一组字段定义(JSON 数组,含字段名、类型、必填、描述),建标准时从模板导入,省得反复配。
这三张表放在一起看,是一个"字段定义可复用"的设计:模板是库,标准是实例,字段是明细。同类的标准(比如各类政策文件都有一套发文机关/文号/生效日期)从模板起手,改几个字段就行,不用每次从头配。
## Collection 是怎么由标准"长"出来的
`ai_milvus_collection` 是声明式管理的主体,关键字段:
| 字段 | 说明 |
| ---- | ---- |
| `metadata_standard_id` | 声明结构来源。一个标准可对应多个集合,单集合只对应一个标准 |
| `vector_field` / `vector_dim` | 向量字段名和维度,维度必须与 embedding 模型一致 |
| `metric_type` | L2 / IP / COSINE |
| `schema_json` | Schema 快照,用于 diff 展示 |
| `sync_state` | unknown / in_sync / out_of_sync / pending / error,配 `last_sync_time` / `last_sync_msg` |
字段层面两张表:
- `ai_milvus_collection_field`:集合的字段定义,注释直说这是 **Schema 权威**。`uk_collection_metadata_field(tenant_id, collection_id, metadata_field_id)` 保证一个集合里一个元数据字段只出现一次;`dim` 对向量字段必填,`max_length` 对 VarChar 必填。
- `ai_milvus_index`:索引定义,`index_type`(HNSW / IVF_FLAT / IVF_PQ / AUTOINDEX)、`build_state`(unknown / building / ready / error)记录构建进度。
![核心表关系:标准 → 集合]
## 页面操作
![元数据标准编辑页]
1. 在「AI 知识库 → 元数据标准」建标准,挂 embedding 模型;
2. 标准下维护字段,每个字段配 `schema_json`,前端表单自动长出来;
3. 在「Milvus 管理 → 集合管理」新建 Collection:选实例、选标准、定主键字段 / 向量字段 / 维度 / 度量,字段列表从标准字段里勾选;
4. 保存后系统调 Milvus 建集合、建索引,`sync_state` 走到 `in_sync`。
更新标准字段后集合状态会变成 `out_of_sync`,页面提示需要同步——这就是"声明式管理"的意思:数据库是期望态,Milvus 是实际态,两边差了,状态字段说话。
## 源码走读
业务侧入口是 `com.veap.ai.controller.AiMetadataStandardController`(basePath `/metadataStandard`)和 `com.veap.ai.controller.AiMetadataFieldController`。
真正操作 Milvus 的代码在 `veap-milvus` 的 `milvusops` 包:
- `milvusops.facade.MilvusOpsFacade`(实现 `IMilvusOpsFacade`):统一入口,`hasCollection`、`createCollection` 等方法;
- `milvusops.service.MilvusCollectionOpsService`:拼 `HasCollectionParam` / `CreateCollectionParam` 调 SDK;
- 每次调用前后走审计,写入 `ai_milvus_op_log`。
```java
Boolean exists = MilvusRUtil.requireData(resp, "hasCollection");
```
`MilvusRUtil.requireData` 这类工具方法把 SDK 返回的 RPC 状态做了统一断言,失败直接抛——和第 1 篇的"禁止吞错"是同一条规矩。
## 一处值得抄的设计
`sync_state` 五态 + `schema_json` 快照这个组合,解决的是分布式系统里最烦的"两本账"问题。集合到底和标准一不一致,不靠人肉比对,靠状态字段和快照 diff。运维界面把 `out_of_sync` 标红,剩下就是点一下同步。
我自己早期版本没有这个状态,标准改了字段,Milvus 里还是旧的,检索时按新字段过滤,Milvus 直接报字段不存在,排了半天。
## 标准这层的三个扩展点
别把标准看成一张静态字典,它自带三层可扩展结构:
1. **层级扩展**:`parent_id` 支持子标准。上级标准管公共字段(发文机关、文号),子标准加专属字段。字段定义随层级分化,不互相污染。
2. **版本扩展**:`version` 字段在,标准演进就有账可查。主题绑定的是 `standard_code` 不是标准主键(第 3 篇会讲到),版本变化不影响引用侧。
3. **链路扩展**:字段定义不只给 Collection 用。`ai_semantic_template` 语义模板表的表注释写了一条取值链路——`topic_code → 知识主题 → 元数据标准 → 元数据字段`,意思是后面 AI 生成知识内容时,取哪些字段、拼什么格式,也是从这套标准里长的。标准定义一次,Collection 建表、动态表单、语义生成三处共用,这是整条链路"配置化"的地基。
## 复现
环境同第 1 篇。建一个标准、挂三个字段、创建一个维度 1024 的集合,看 `ai_milvus_collection.sync_state` 变化,再去 Milvus 侧 `describe collection` 验证字段一致。
下一篇讲知识主题:多级主题怎么绑标准,以及应用主题知识配置里召回条数、匹配度阈值这些参数为什么值得单独一张表。
仓库:https://gitee.com/mindock/veap(表结构 `veap-cloud/DB/veap.sql`,设计文档 `docs/AiMilvus/`)