边界与数据模型
本节目标
你将明确向量数据库与 Embedding/搜索/RAG 的责任边界,设计一个包含空间契约、稳定 point ID、向量、来源、权限、状态和 hash 的记录,并判断何时拆 collection、何时用 payload/partition。
先画清系统边界
一个常见数据流:
canonical document
-> parse/chunk
-> embedding adapter
-> versioned point records
-> vector database (filter + exact/ANN)
-> search fusion/rerank
-> RAG context + citations每层负责:
| 层 | 负责 | 不应假装负责 |
|---|---|---|
| 文档/Chunking | 来源、结构、span、ACL、content hash | 向量相似度 |
| Embedding | 角色、模型/revision、维度、向量 | 数据库存储与授权 |
| 向量数据库 | schema、持久化、过滤、近邻、CRUD、运维 | 判断回答事实正确 |
| 搜索/Rerank | query、融合、候选排序、相关性评测 | 内容生成 |
| RAG | 上下文、引用、回答与拒答 | 修复上游丢失的数据 |
把原文复制进 payload 可能方便展示,但也扩大泄露、备份和更新面。常见安全基线是向量库保存最小可检索 metadata 与受控文本指针,最终引用回 canonical source;若确需存正文,应明确加密、ACL、保留和删除范围。
Collection 先定义空间契约
一个逻辑容器无论叫 collection、index、table 还是 namespace,都应绑定:
{
"space_id": "ops-rag-v3",
"model": "provider/model-id",
"embedding_revision": "immutable-revision",
"dimension": 1024,
"metric": "cosine",
"normalized": true,
"dtype": "float32"
}JSON 不能加合法行尾注释:space_id 隔离索引空间,model/embedding_revision 固定生成来源,dimension/metric/normalized/dtype 定义可比较的数学与存储契约。请把尖括号或数字替换成已核对的实际值,而不要从本示例推断模型规格。
上述数字只是 schema 示例,不是模型建议。实际值来自 [[Knowledge/AI Agent Engineer/docs-CN/Embedding/00-目录|Embedding]]候选卡。
不同模型或 revision 即使维度相同,也不自动兼容。Dimension、metric、normalization、dtype 或角色策略改变时,创建新 space_id 并走迁移,不在旧索引中混写。
Contract signature 可由规范化字段哈希得到,用于:
- 应用启动时校验 collection;
- 防止 query vector 查错空间;
- 缓存和批任务隔离;
- 快照/恢复后核对;
- 发布 alias 指向正确版本。
一个可审计 point
{
"id": "tenant-a:doc-17:chunk-03",
"vector": [0.12, -0.08, 0.44],
"payload": {
"tenant_id": "tenant-a",
"document_id": "doc-17",
"chunk_id": "chunk-03",
"source_revision": "rev-7",
"content_sha256": "64-char-lowercase-hex",
"embedding_revision": "immutable-revision",
"acl": ["employees", "sre"],
"status": "published",
"section_path": ["运行手册", "回滚"],
"language": "zh"
}
}这段也保持为可解析 JSON:顶层 id 支持幂等写入、删除与引用;vector 必须符合上一个 contract 的维度;payload 中 tenant_id、来源/版本/哈希、ACL 与 status 是查询前安全过滤和生命周期追踪的最小字段。展示性 section_path/language 不能替代授权字段。
示例向量只有 3 维,仅为可读性;真实 dimension 必须等于 collection contract。
字段职责:
| 字段 | 用途 | 常见错误 |
|---|---|---|
| point ID | 幂等 upsert、删除和引用 | 用数组序号导致前插后全漂移 |
| tenant ID | 强隔离/filter/shard 路由 | 直接信任客户端任意 tenant 参数 |
| document/chunk ID | 追溯 canonical source | 只保存向量,无法删除整篇文档 |
| source revision | 阻止新旧正文混合 | 更新向量但 payload 仍旧 |
| content hash | 对账向量是否对应当前输入 | 哈希展示文本而非实际 embedding input |
| embedding revision | 检查空间版本 | 只有 dimension,没有 model/revision |
| ACL | 检索前授权 | 只在最终 UI 删除越权结果 |
| status | draft/published/archived 生命周期 | 草稿和 tombstone 仍可搜索 |
| section/language | 过滤、解释、子组评测 | 类型漂移导致索引/过滤异常 |
Metadata 类型必须稳定。acl有时字符串、有时数组,会让 filter 语义不可预测。时间字段要统一时区与格式;高基数字段是否建标量索引要由查询分布决定。
ID 设计
稳定 ID 应:
- 在重试和重放中相同;
- 在租户之间不冲突;
- 能映射到 source/chunk;
- 不泄露不必要敏感信息;
- 支持 source 删除时枚举全部 points;
- 不只依赖 ordinal。
可以用可读复合 ID,也可以用内容派生/随机 ID 加显式 mapping。若 content hash 进入 ID,正文变化会产生新 ID,删除旧 ID 的流程必须可靠;若稳定 chunk ID 不随正文变,则 upsert 需用 source revision 防止乱序覆盖。
不要让客户端自行声明有权覆盖某个 point ID。服务端应从可信 tenant/source mapping 构造 ID 与授权。
Payload 是查询 schema,不是杂物袋
加入字段前回答:
- 会用于 filter、排序、展示、审计还是删除?
- 类型与允许值是什么?
- 谁产生、何时更新?
- 是否包含敏感信息?
- 是否需要标量索引?
- 旧记录缺字段时 fail-open 还是 fail-closed?
- 迁移/备份是否包含它?
高频过滤字段可建 payload/scalar index;低频、高基数、只展示字段不一定需要。每个索引都会增加写入、磁盘和维护成本。
如何划分 collection/partition
通常应分开的情况
- 不同 dimension/metric/embedding space;
- 法规要求的硬租户/区域隔离;
- 完全不同备份、保留、加密或访问控制;
- 独立扩缩容、SLO 或生命周期;
- 高风险实验与生产发布。
通常不必每项拆开的情况
- 语言、文档类型、小部门标签;
- 数量很多的微型租户;
- 只为一个可过滤字段;
- 希望用多个 collection 掩盖 schema 混乱。
Collection-per-tenant 隔离直观,但大量小 collection 会增加控制面、备份和运维成本;共享 collection + tenant payload 易于集中运维,却要求 filter 与分片设计严格。专用库还可能支持 partition/custom sharding。选择依目标产品版本和租户分布,不存在通用数量阈值。
多向量与稀疏向量
部分产品支持一个 point 的 named dense vectors、sparse vectors 或多向量。可用于:
- 同一对象的文本与图片表示;
- dense + sparse 混合检索;
- 标题和正文分开编码;
- 多粒度表示。
但“存在同一 point”不等于不同空间可以互相点积。每个向量字段仍需独立 contract、dimension/metric 和查询路径。删除、ACL 与 source revision 应保持一致,避免只更新其中一个表示。
Source of truth 与派生索引
工程建议把 canonical source/chunk registry 作为可重建事实,把向量索引视为版本化派生数据:
- source 更新产生 outbox/event;
- embedding job 从固定 revision 编码;
- vector write 带 source/input hash;
- 索引完成后对账;
- published alias 切换;
- 删除事件传播到所有活动空间。
如果向量库是唯一保存 payload/ACL/删除映射的地方,灾难恢复和迁移会更难。[[Knowledge/AI Agent Engineer/docs-CN/知识库构建/00-目录|知识库构建]]中的 revision/outbox 模式可提供上游事实链。
Schema 门禁
写入前检查:
- Contract signature 完全匹配;
- point ID 合法且 tenant 不可跨转移;
- vector dimension、finite、nonzero/normalized 合规;
- required payload 字段齐全、类型稳定;
- source/embedding revision 与 job 一致;
- ACL 非空且 status 允许;
- content hash 是实际 embedding input;
- point 与 tombstone 不同时存在。
查询前再次检查 query vector 属于同一空间。
常见错误与排查
- 一个 collection 塞所有模型:按 contract 清点并新建隔离空间。
- 只存 vector 和 text:无法做 tenant/filter/version/delete。
- payload 任意 JSON:字段类型漂移,过滤和索引不稳定。
- ID 用 chunk 序号:源文前插导致大量无意义重写。
- 正文复制到日志/快照:敏感面扩大,回到最小 metadata + source pointer。
- 草稿可被搜索:status filter 缺失或 fail-open。
- named vectors 更新不同步:增加 source revision 与表示完整性对账。
练习
- 为“多租户内部 FAQ”设计 contract 与 point schema,列出 required/optional 字段。
- 比较复合 ID 与随机 ID + mapping 的删除、迁移、隐私权衡。
- 判断哪些字段需要标量索引:tenant、ACL、language、content hash、标题、创建时间。
- 为 text/image 两个 named vectors 写各自空间契约,并说明哪些 payload 必须共享。
- 设计一个坏记录:vector 属于新模型、payload embedding revision 仍旧;写出拒绝门禁。
- 为缺失 ACL 的历史记录选择 fail-closed 迁移策略。
掌握检查
- 我能说明向量库与 Embedding、搜索、RAG 的边界。
- Collection 有完整且可哈希的 space contract。
- Point 能回溯 source/chunk/revision/hash,并携带 tenant/ACL/status。
- Metadata 字段有稳定类型、来源、更新和索引规则。
- 不同 space 或 hard isolation domain 不混在同一查询路径。
- Named/multivector 仍分别版本化,不因共存就互相兼容。
- Canonical source 可重建索引,向量库不是唯一事实孤岛。
小结与下一步
数据模型先保证“比较的是正确空间、记录可授权可追溯”。下一步再决定如何更快找邻居:[[Knowledge/AI Agent Engineer/docs-CN/向量数据库/02-距离精确检索与ANN索引|距离、精确检索与 ANN 索引]]。
参考资料
- Qdrant: Overview
- Qdrant: Points
- pgvector official repository
[[Knowledge/AI Agent Engineer/docs-CN/Embedding/00-目录|Embedding]]
来源获取日期:2026-07-22。返回 [[Knowledge/AI Agent Engineer/docs-CN/向量数据库/00-目录|向量数据库目录]]。