文字经 Embedding 模型变成向量,向量库负责寻找相近片段。
究竟有哪些模型、Milvus 内部装什么、怎样部署和真正调用。
把 PDF 解析、切块、版本发布形成完整 RAG 入库流水线。
本专题目录
阅读过程中可按 Ctrl + Z 快速返回当前页面的本章目录;也可以点击右下角按钮。
知识流思维导图
顺序不能倒:先确定 Embedding 模型和输出维度,再创建 Milvus 向量字段。数据库字段是 1024 维,模型却返回 1536 维时,数据写不进去。
Embedding 模型选型
按照思维导图从模型选择、数据存储到生产运行逐步完成。
M01Embedding 模型分类
Embedding 不是一个固定品牌,而是一类“把输入内容编码成向量”的模型。工程上最实用的分法是先看调用方式和擅长的数据。
| 类别 | 常见代表(示例,不是完整名单) | 怎样调用 | 优点 | 边界 |
|---|---|---|---|---|
| 托管通用文本 API | OpenAI text-embedding-3 系列、Voyage 4 系列、Cohere Embed、Google Gemini Embedding | 后端经 HTTPS/SDK 发送文本 | 接入快,不管理显卡和推理服务 | 数据出网、按量费用、限流、网络和厂商变更 |
| 开源多语言模型 | BGE-M3、Qwen3-Embedding、multilingual-E5、Jina Embeddings、Nomic Embed | 下载到自己的 CPU/GPU 或推理服务 | 数据留在内网,可固定版本 | 自己负责硬件、并发、监控和升级 |
| 领域模型 | 代码、法律、金融、生物医学专用模型 | 可能是 API 或本地部署 | 可能更懂行业术语 | “专用”不保证适合你,仍要实测 |
| 多模态模型 | 文本、图片、文档页面统一编码 | 输入可含文字或图片 | 能搜图表、商品图、扫描页 | 成本、存储和评测更复杂 |
| 稀疏向量模型 | SPLADE 类 sparse embedding | 输出大部分维度为 0 的向量 | 保留词项匹配能力,可做混合检索 | 不是普通 dense embedding 的同义词 |
M02Embedding 模型选型与评测
明确默认方案:第一版先用成熟的托管多语言 Embedding API,减少模型运维,把精力放在切块、metadata 和召回评测;如果政策禁止文本出网,再选 BGE-M3 或 Qwen3-Embedding 等多语言开源模型在内网运行。最后让候选模型在同一份真实评测集上比赛。
优先云 API
团队小、要快速上线、不管理 GPU;代价是外部依赖、费用和合规审查。
优先本地模型
敏感文档不能出网、请求量稳定、团队能运维推理服务;工程成本更高。
选择时检查 8 件事
input_type=query/document。M03模型版本、维度与迁移约束
1024维
dim=1024
文档向量与查询向量必须位于兼容坐标系。换模型、重要版本、预处理方式或维度,通常要新建字段或 Collection,重新向量化全部文档,评测后再切流量。
不要原地混写:一半数据用模型 A、一半用模型 B,再用 B 搜整个 Collection,即使数据库成功返回,也没有可靠语义。
embedding_provider = "your-provider" embedding_model = "exact-model-name" embedding_version = "固定版本或内部发布号" embedding_dim = 1024 preprocess_version = "chunk-clean-v3"
Milvus 数据存储
按照思维导图从模型选择、数据存储到生产运行逐步完成。
D01Milvus 数据层级与核心对象
向量数据库服务 Milvus 接收向量、普通字段和过滤条件,建立近邻搜索索引并返回相似记录。它不负责把文字变向量,也不生成最终答案。
Collection 不是整份 PDF
一条 Entity 通常对应一个 Chunk。一份 PDF 切成 50 段,就产生约 50 行,用同一个 document_id 关联。
Partition 不是必选
小白项目先用默认 Partition 和 metadata 过滤。只有规模与性能评测证明需要时,再设计 Partition Key。
D02向量写入与搜索链路
访问与协调
Proxy 接收请求,Coordinator 维护拓扑、调度任务;Standalone 把这些职责打包运行。
计算
写入相关组件处理数据,Query Node 执行搜索;Distributed 模式可独立扩容。
持久化
Meta Store 存元数据,Object Storage 存大文件和索引,WAL 记录可靠写入;默认实现会随版本变化。
应用不用直接调用内部节点:后端只连统一 URI。理解内部结构是为了排查写入、对象存储、索引和查询内存问题。
D03退款知识库的字段设计
默认设计:一个 Entity 存一个 Chunk;正文放 Milvus 方便取回,原始 PDF 放对象存储。权限、租户、状态、版本和有效期使用独立标量字段,便于搜索前过滤。
| 字段 | 类型 | 来源 | 用途 | 例子 |
|---|---|---|---|---|
| chunk_id | VARCHAR 主键 | 入库程序 | 去重、更新、追踪 | refund-v4-p2-c1 |
| document_id | VARCHAR | 文档系统 | 关联原文与父块 | refund-policy |
| text | VARCHAR | 解析/切块 | 返回 Reranker/LLM | 退款审核通过后... |
| embedding | FLOAT_VECTOR(1024) | Embedding 模型 | 向量搜索 | [0.018,-0.227,...] |
| tenant_id | VARCHAR | 业务系统 | 租户隔离 | company-a |
| access_level | INT16 | 权限系统 | 可见范围 | 1 |
| version/status | INT32/VARCHAR | 发布系统 | 只查有效版本 | 4 / active |
| effective_at/expires_at | INT64 时间戳 | 发布系统 | 按当前时间过滤 | 1788192000 |
| source_uri | VARCHAR | 文件系统 | 引用和审计 | s3://policies/refund-v4.pdf |
高频过滤字段不要全塞进一个大 JSON:tenant、status、时间等建议独立建字段和索引,类型、权限逻辑和性能更清楚。
P01Milvus 部署模式选型
| 模式 | 是什么 | 适合 | 不足 |
|---|---|---|---|
| Milvus Lite | 嵌入 Python 的本地文件数据库 | Notebook、演示、小规模实验;先核对系统支持 | 不是高可用服务器;Windows 不作为本教程默认路线 |
| Standalone | 单机服务器版 | 学习、开发、测试和中等规模生产 | 单机容量与故障域,需要自管备份监控 |
| Distributed | Kubernetes 多节点集群 | 大规模、高并发、高可用生产 | 运维最复杂 |
| 托管服务 | 云厂商代管 Milvus | 需要生产能力但不想自运维 | 持续费用、云依赖和合规评估 |
你的默认选择:Windows + Docker Desktop + Milvus Standalone。真正需要多节点、高可用和更大规模时,再评估 Distributed 或托管服务。
部署与生产运行
按照思维导图从模型选择、数据存储到生产运行逐步完成。
P02Windows 用 Docker 部署 Standalone
Docker 容器部署 Docker 把 Milvus 及依赖装进隔离容器。Python 后端可在容器外通过 localhost:19530 连接。
D:\milvus-local,保存 Compose 与持久化卷。docker compose up -d,用 docker compose ps 检查容器健康。# PowerShell New-Item -ItemType Directory -Path D:\milvus-local Set-Location D:\milvus-local # 2026-09 官方安装页示例为 3.0.1;未来安装前先核对官方页面 Invoke-WebRequest https://github.com/milvus-io/milvus/releases/download/v3.0.1/milvus-standalone-docker-compose.yml -OutFile docker-compose.yml docker compose up -d docker compose ps
当前官方 Compose 会启动 Milvus、MinIO 和 etcd 等容器。客户端地址通常为 http://localhost:19530,数据映射到当前目录的 volumes/。
# 停服务,保留数据 docker compose down # 再启动 docker compose up -d # 查看日志 docker compose logs milvus-standalone
停容器不等于删数据:删除 volumes 或删除 Docker 卷可能造成不可恢复的数据丢失。删除前先备份并确认路径。
C01连接、建 Collection 和索引
pip install -U pymilvus sentence-transformers
from pymilvus import MilvusClient, DataType
URI = "http://localhost:19530"
TOKEN = "root:Milvus" # 仅本地演示;生产必须改默认凭据
COLLECTION = "refund_policy_chunks_v1"
DIM = 1024 # 必须与真实模型输出长度一致
client = MilvusClient(uri=URI, token=TOKEN)
schema = MilvusClient.create_schema(
auto_id=False,
enable_dynamic_field=False,
)
schema.add_field("chunk_id", DataType.VARCHAR,
is_primary=True, max_length=128)
schema.add_field("document_id", DataType.VARCHAR, max_length=128)
schema.add_field("text", DataType.VARCHAR, max_length=8192)
schema.add_field("embedding", DataType.FLOAT_VECTOR, dim=DIM)
schema.add_field("tenant_id", DataType.VARCHAR, max_length=64)
schema.add_field("access_level", DataType.INT16)
schema.add_field("version", DataType.INT32)
schema.add_field("status", DataType.VARCHAR, max_length=16)
schema.add_field("effective_at", DataType.INT64)
schema.add_field("expires_at", DataType.INT64)
schema.add_field("source_uri", DataType.VARCHAR, max_length=512)
index_params = client.prepare_index_params()
index_params.add_index(
field_name="embedding",
index_type="AUTOINDEX",
metric_type="COSINE",
)
for field in ["tenant_id", "status", "effective_at", "expires_at"]:
index_params.add_index(field_name=field, index_type="AUTOINDEX")
client.create_collection(
collection_name=COLLECTION,
schema=schema,
index_params=index_params,
)Schema
创建 Collection 时由开发者提交。以后插入必须符合字段和类型;向量不是 1024 维会报错。
AUTOINDEX
让 Milvus 按环境选择实现,适合第一版。生产优化仍要用真实数据评测。
C02文本变向量并写入 Milvus
下面用开源 BAAI/bge-m3 演示。第一次会下载模型,CPU 能运行但可能较慢。生产可以替换为托管 API,Milvus 写入逻辑不变。
from sentence_transformers import SentenceTransformer
embedder = SentenceTransformer("BAAI/bge-m3")
chunks = [
{
"chunk_id": "refund-v4-p2-c1",
"document_id": "refund-policy",
"text": "退款审核通过后,款项通常在三个工作日内原路退回。",
"tenant_id": "company-a",
"access_level": 1,
"version": 4,
"status": "active",
"effective_at": 1788192000,
"expires_at": 4102444800,
"source_uri": "s3://policies/refund-v4.pdf",
},
{
"chunk_id": "refund-v4-p3-c1",
"document_id": "refund-policy",
"text": "生鲜商品拆封后不支持无理由退款。",
"tenant_id": "company-a",
"access_level": 1,
"version": 4,
"status": "active",
"effective_at": 1788192000,
"expires_at": 4102444800,
"source_uri": "s3://policies/refund-v4.pdf",
},
]
vectors = embedder.encode(
[item["text"] for item in chunks],
normalize_embeddings=True,
).tolist()
assert len(vectors[0]) == DIM, "模型输出维度与 Schema 不一致"
for item, vector in zip(chunks, vectors):
item["embedding"] = vector
result = client.insert(collection_name=COLLECTION, data=chunks)
print(result)在线与离线:文档在发布知识库时批量向量化;用户每次提问只向量化问题,不会重新处理全库。
C03带租户、权限和版本过滤搜索
import time
question = "退款审核通过了,钱什么时候回来?"
query_vector = embedder.encode(
[question],
normalize_embeddings=True,
)[0].tolist()
now_ts = int(time.time())
filter_expr = (
'tenant_id == "company-a" '
'and access_level <= 1 '
'and status == "active" '
f'and effective_at <= {now_ts} '
f'and expires_at > {now_ts}'
)
hits = client.search(
collection_name=COLLECTION,
data=[query_vector],
anns_field="embedding",
filter=filter_expr,
limit=5,
output_fields=[
"chunk_id", "document_id", "text",
"version", "source_uri"
],
)
for hit in hits[0]:
print(hit["distance"], hit["entity"]["text"])hits[0] 是第一个查询的结果列表。每个结果含主键、距离/相似度和指定字段。这只是候选证据,后面还要去重、Rerank、冲突检查、引用和必要时拒答。
权限过滤由登录系统产生:不能让 LLM 猜 tenant_id,也不能信任浏览器随便提交的 tenant_id。
C04向量索引选型
数据库加速结构 索引不是数据本身,而是帮助 Milvus 少比较一些向量。速度、内存、构建时间和召回率需要权衡。
| 选择 | 直观做法 | 优点 | 不足 | 建议 |
|---|---|---|---|---|
| AUTOINDEX | 让系统选实现 | 简单 | 底层可控细节少 | 第一版默认 |
| FLAT | 逐个精确比较 | 精确,可作基准 | 大数据慢 | 小评测集/召回上限 |
| HNSW | 在多层近邻图上走近目标 | 常见的高召回低延迟方案 | 内存较多,要调参 | 有真实性能数据后选择 |
| IVF_FLAT | 先分桶,只搜相近桶 | 比全量快 | 搜索范围太小会漏 | 理解 nlist/nprobe 后使用 |
| 量化/磁盘类 | 压缩向量或更多使用磁盘 | 省内存、规模更大 | 精度和调参更复杂 | 内存成为瓶颈后评估 |
不要照抄参数:用固定真实查询集比较 Recall@k、P95、QPS、建索引时间、内存和磁盘。
C05更新政策如何避免新旧混淆
小规模可用 upsert 更新同一主键;需要审计的政策更适合保留版本记录,通过状态切换控制可见性。大量数据重建应研究批量导入。
P03生产环境保障
安全
修改默认凭据、认证、网络隔离、TLS、最小权限;19530/9091 不直接暴露公网。
可靠性
备份数据和配置并演练恢复;监控磁盘、内存、查询延迟、错误率、积压和索引状态。
容量
向量原始大小约为“记录数 × 维度 × 每个数的字节数”,另加索引、标量、日志和副本。
治理
记录模型、切块版本、发布时间、租户和来源,设计删除、过期、重建与审计。
评测
成功返回 5 条不等于正确,必须用 Recall@k、MRR 和坏案例分类验证。
降级
Milvus 超时或证据不足时应拒答、安全说明或转人工,不能让 LLM 脱离证据猜。
P04常见故障从哪里查
| 现象 | 先查 | 常见原因 |
|---|---|---|
| 连不上 19530 | 容器状态、端口、日志 | 容器未启动、端口冲突、Docker/WSL 资源问题 |
| 插入维度错误 | len(vector) 与 dim | 换模型后没重建 Collection |
| 有数据却搜不到 | 写入结果和 filter | 条件排除数据、时间戳单位错 |
| 召回旧政策 | status 与有效期 | 旧版仍 active 或查询漏过滤 |
| 相似度异常 | 模型版本与 metric | 坐标系混用、归一化/指令不一致 |
| 搜索变慢 | 记录量、过滤、索引、内存、并发 | 索引缺失、候选过多、资源不足 |
排错顺序:先服务健康,再确认数据存在,再检查过滤,最后才调相似度和索引。不要一错就换模型。
本专题全链路总结
接回主线:第04章继续解决 PDF 如何解析、切块并安全发布;第05章解决怎样证明检索真的有效。
官方资料与版本提醒
型号、版本和组件会更新。教程解释稳定工程原则,真正安装时以官方页面为准。