第 03 章专题补课 · 可独立阅读

Embedding 模型选型
与 Milvus 从部署到检索

用同一套“退款政策知识库”完成:选 Embedding 模型 → 设计 Milvus Collection → Windows 部署 → 写入向量 → 带租户、权限和版本过滤检索。

Embedding ModelsMilvusSchemaDockerPyMilvus
第03章已经懂了
文字经 Embedding 模型变成向量,向量库负责寻找相近片段。
→
本专题解决
究竟有哪些模型、Milvus 内部装什么、怎样部署和真正调用。
→
接回第04章
把 PDF 解析、切块、版本发布形成完整 RAG 入库流水线。
学完后的结果:你能解释模型与数据库不是一回事,并能在 Windows 上启动 Milvus,建立适合企业知识库的字段,完成插入、过滤搜索、更新和排错。

本专题目录

阅读过程中可按 Ctrl + Z 快速返回当前页面的本章目录;也可以点击右下角按钮。

知识流思维导图

让退款政策可以被语义检索

顺序不能倒:先确定 Embedding 模型和输出维度,再创建 Milvus 向量字段。数据库字段是 1024 维,模型却返回 1536 维时,数据写不进去。

MODULE 01

Embedding 模型选型

按照思维导图从模型选择、数据存储到生产运行逐步完成。

M01Embedding 模型分类

Embedding 不是一个固定品牌,而是一类“把输入内容编码成向量”的模型。工程上最实用的分法是先看调用方式和擅长的数据。

类别常见代表(示例,不是完整名单)怎样调用优点边界
托管通用文本 APIOpenAI 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 的同义词
生活中的例子:模型像不同地图服务。通用地图覆盖面广,园区地图更懂楼层和门牌;云 API 是租地图服务,本地模型是把制图设备搬进公司。
生活中的例子:选择 Embedding 模型像为跨国客服选择翻译员:不仅要懂语言,还要看专业领域、速度和长期维护。

M02Embedding 模型选型与评测

明确默认方案:第一版先用成熟的托管多语言 Embedding API,减少模型运维,把精力放在切块、metadata 和召回评测;如果政策禁止文本出网,再选 BGE-M3 或 Qwen3-Embedding 等多语言开源模型在内网运行。最后让候选模型在同一份真实评测集上比赛。

优先云 API

团队小、要快速上线、不管理 GPU;代价是外部依赖、费用和合规审查。

优先本地模型

敏感文档不能出网、请求量稳定、团队能运维推理服务;工程成本更高。

不能只看排行榜

准备真实问法与正确 Chunk,比较 Recall@5、MRR、P95 延迟、费用和失败率。

选择时检查 8 件事

语言:中文、英文、混合语言和公司缩写是否稳定。
任务:检索、聚类、分类、代码搜索还是图文搜索。
Query/Document 用法:是否要求不同指令或 input_type=query/document。
维度:决定 Milvus Schema、内存和索引体积;更大不一定更准。
最大输入:超长 Chunk 会报错或截断。
距离函数:按模型说明选 COSINE、IP 或 L2。
吞吐与成本:分别测离线批量和在线单查询。
合规与版本:文本能否出网、日志策略、能否固定和回滚版本。
生活中的例子:选模型像招聘翻译。要让候选人翻译你的退款条款、缩写和真实客户口语,再看准确率、速度和费用。

M03模型版本、维度与迁移约束

原文 Chunk
→
模型 A v1
1024维
→
Milvus
dim=1024
→
问题也用 A v1

文档向量与查询向量必须位于兼容坐标系。换模型、重要版本、预处理方式或维度,通常要新建字段或 Collection,重新向量化全部文档,评测后再切流量。

不要原地混写:一半数据用模型 A、一半用模型 B,再用 B 搜整个 Collection,即使数据库成功返回,也没有可靠语义。

embedding_provider = "your-provider"
embedding_model = "exact-model-name"
embedding_version = "固定版本或内部发布号"
embedding_dim = 1024
preprocess_version = "chunk-clean-v3"
生活中的例子:经纬度、商场楼层坐标和游戏地图坐标都是数字,但不能混在一起算距离。换模型就是换坐标系。
MODULE 02

Milvus 数据存储

按照思维导图从模型选择、数据存储到生产运行逐步完成。

D01Milvus 数据层级与核心对象

向量数据库服务 Milvus 接收向量、普通字段和过滤条件,建立近邻搜索索引并返回相似记录。它不负责把文字变向量,也不生成最终答案。

Milvus 实例(运行中的数据库服务) └─ Database:业务空间 └─ Collection:类似一张表,例如 refund_policy_chunks ├─ Schema:字段、类型、主键和向量维度 ├─ Partition:可选的数据分区 │ └─ Segment:Milvus 内部管理的数据块 ├─ Entity:一行记录,也就是一个可检索 Chunk │ ├─ chunk_id:主键 │ ├─ text:片段正文 │ ├─ embedding:向量 │ └─ tenant_id/status/version:标量字段 └─ Index:向量或标量字段的加速结构

Collection 不是整份 PDF

一条 Entity 通常对应一个 Chunk。一份 PDF 切成 50 段,就产生约 50 行,用同一个 document_id 关联。

Partition 不是必选

小白项目先用默认 Partition 和 metadata 过滤。只有规模与性能评测证明需要时,再设计 Partition Key。

生活中的例子:Milvus 像档案馆:Database 是园区,Collection 是档案库,Schema 是收件规范,Entity 是档案卡,Index 是快速目录,Partition 是分馆。

D02向量写入与搜索链路

Python 后端
→
Milvus 19530
→
过滤+索引搜索
→
Top-k Entity

访问与协调

Proxy 接收请求,Coordinator 维护拓扑、调度任务;Standalone 把这些职责打包运行。

计算

写入相关组件处理数据,Query Node 执行搜索;Distributed 模式可独立扩容。

持久化

Meta Store 存元数据,Object Storage 存大文件和索引,WAL 记录可靠写入;默认实现会随版本变化。

应用不用直接调用内部节点:后端只连统一 URI。理解内部结构是为了排查写入、对象存储、索引和查询内存问题。

生活中的例子:寄快递只面对营业员,但系统负责人要知道包裹可能堵在受理、分拣、运输还是仓库。
生活中的例子:写入像商品入库并贴标签,搜索像拿着需求单先筛权限,再找位置最接近的货物。

D03退款知识库的字段设计

默认设计:一个 Entity 存一个 Chunk;正文放 Milvus 方便取回,原始 PDF 放对象存储。权限、租户、状态、版本和有效期使用独立标量字段,便于搜索前过滤。

字段类型来源用途例子
chunk_idVARCHAR 主键入库程序去重、更新、追踪refund-v4-p2-c1
document_idVARCHAR文档系统关联原文与父块refund-policy
textVARCHAR解析/切块返回 Reranker/LLM退款审核通过后...
embeddingFLOAT_VECTOR(1024)Embedding 模型向量搜索[0.018,-0.227,...]
tenant_idVARCHAR业务系统租户隔离company-a
access_levelINT16权限系统可见范围1
version/statusINT32/VARCHAR发布系统只查有效版本4 / active
effective_at/expires_atINT64 时间戳发布系统按当前时间过滤1788192000
source_uriVARCHAR文件系统引用和审计s3://policies/refund-v4.pdf

高频过滤字段不要全塞进一个大 JSON:tenant、status、时间等建议独立建字段和索引,类型、权限逻辑和性能更清楚。

生活中的例子:档案卡的部门、密级、有效期应是独立栏目,不能全写在“备注”里,否则每次都要读完整备注。

P01Milvus 部署模式选型

模式是什么适合不足
Milvus Lite嵌入 Python 的本地文件数据库Notebook、演示、小规模实验;先核对系统支持不是高可用服务器;Windows 不作为本教程默认路线
Standalone单机服务器版学习、开发、测试和中等规模生产单机容量与故障域,需要自管备份监控
DistributedKubernetes 多节点集群大规模、高并发、高可用生产运维最复杂
托管服务云厂商代管 Milvus需要生产能力但不想自运维持续费用、云依赖和合规评估

你的默认选择:Windows + Docker Desktop + Milvus Standalone。真正需要多节点、高可用和更大规模时,再评估 Distributed 或托管服务。

生活中的例子:Lite 像桌面文件柜,Standalone 像独立档案室,Distributed 像全国仓储网络。几箱资料不必先建全国网络。
生活中的例子:Lite、Standalone、Distributed 像手推车、小型仓库和多仓物流网络,要按数据量与并发选择,不是越大越好。
MODULE 03

部署与生产运行

按照思维导图从模型选择、数据存储到生产运行逐步完成。

P02Windows 用 Docker 部署 Standalone

Docker 容器部署 Docker 把 Milvus 及依赖装进隔离容器。Python 后端可在容器外通过 localhost:19530 连接。

安装并启动 Docker Desktop,启用 WSL 2 后端并分配足够内存。
建立专用目录,例如 D:\milvus-local,保存 Compose 与持久化卷。
从官方页面下载当前稳定版 Compose。下面版本只代表本教程核对时的官方示例。
运行 docker compose up -d,用 docker compose ps 检查容器健康。
19530 是客户端入口,9091 是管理/观测入口;生产环境不要直接暴露公网。
# 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 卷可能造成不可恢复的数据丢失。删除前先备份并确认路径。

生活中的例子:容器像店铺,Volume 像店外仓库。店铺关门不代表仓库清空;把仓库拆掉才可能真的丢数据。

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 按环境选择实现,适合第一版。生产优化仍要用真实数据评测。

生活中的例子:Schema 是入库单模板,Index 是货架目录。模板规定箱子信息,目录帮助管理员快速找到货物。

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)

在线与离线:文档在发布知识库时批量向量化;用户每次提问只向量化问题,不会重新处理全库。

生活中的例子:提前给所有商品贴好货架坐标;顾客来时只把需求换成要去的区域,不会重贴全仓库标签。

C04向量索引选型

数据库加速结构 索引不是数据本身,而是帮助 Milvus 少比较一些向量。速度、内存、构建时间和召回率需要权衡。

选择直观做法优点不足建议
AUTOINDEX让系统选实现简单底层可控细节少第一版默认
FLAT逐个精确比较精确,可作基准大数据慢小评测集/召回上限
HNSW在多层近邻图上走近目标常见的高召回低延迟方案内存较多,要调参有真实性能数据后选择
IVF_FLAT先分桶,只搜相近桶比全量快搜索范围太小会漏理解 nlist/nprobe 后使用
量化/磁盘类压缩向量或更多使用磁盘省内存、规模更大精度和调参更复杂内存成为瓶颈后评估

不要照抄参数:用固定真实查询集比较 Recall@k、P95、QPS、建索引时间、内存和磁盘。

生活中的例子:FLAT 是挨家挨户问;HNSW 是沿熟人网络找更近的人;IVF 是先判断城区,再只查几个城区。
生活中的例子:向量索引像图书馆目录,用额外整理工作换取更快查找;不同索引是不同的目录组织方式。

C05更新政策如何避免新旧混淆

新文档进入 staging,解析、切块、向量化并写入新版本。
检查数量、字段、维度,运行检索评测和抽样。
发布时把新版本设为 active,同时停用旧版本或结束有效期。
在线查询始终带 status 和生效时间过滤。
保留模型版本、document_id、chunk_id 和发布批次,支持回滚。

小规模可用 upsert 更新同一主键;需要审计的政策更适合保留版本记录,通过状态切换控制可见性。大量数据重建应研究批量导入。

生活中的例子:换菜单要先在后台印好并核价,再统一换上桌,不能一边印一边随机让客人看到新旧价格。
生活中的例子:政策更新像更换机场时刻表:新表未验收前不能替换旧表,切换后还要能快速退回上一版。

P03生产环境保障

安全

修改默认凭据、认证、网络隔离、TLS、最小权限;19530/9091 不直接暴露公网。

可靠性

备份数据和配置并演练恢复;监控磁盘、内存、查询延迟、错误率、积压和索引状态。

容量

向量原始大小约为“记录数 × 维度 × 每个数的字节数”,另加索引、标量、日志和副本。

治理

记录模型、切块版本、发布时间、租户和来源,设计删除、过期、重建与审计。

评测

成功返回 5 条不等于正确,必须用 Recall@k、MRR 和坏案例分类验证。

降级

Milvus 超时或证据不足时应拒答、安全说明或转人工,不能让 LLM 脱离证据猜。

生活中的例子:装好档案柜不等于建成档案系统,还要有门禁、备份、盘点、借阅记录和应急流程。

P04常见故障从哪里查

现象先查常见原因
连不上 19530容器状态、端口、日志容器未启动、端口冲突、Docker/WSL 资源问题
插入维度错误len(vector) 与 dim换模型后没重建 Collection
有数据却搜不到写入结果和 filter条件排除数据、时间戳单位错
召回旧政策status 与有效期旧版仍 active 或查询漏过滤
相似度异常模型版本与 metric坐标系混用、归一化/指令不一致
搜索变慢记录量、过滤、索引、内存、并发索引缺失、候选过多、资源不足

排错顺序:先服务健康,再确认数据存在,再检查过滤,最后才调相似度和索引。不要一错就换模型。

生活中的例子:排查检索故障像查快递:按模型、写入、索引、过滤和返回结果逐站定位,不能只看最后一句报错。

本专题全链路总结

Embedding 模型负责文字变向量。选型看自家评测、语言、隐私、延迟、成本、维度和输入规则。
Milvus存 Entity、标量和向量,通过过滤与索引返回候选;它不生成向量,也不回答用户。
上线顺序定模型 → 定维度和 Schema → 部署 → 写入 → 权限/版本过滤 → Rerank/引用/拒答 → 持续评测。

接回主线:第04章继续解决 PDF 如何解析、切块并安全发布;第05章解决怎样证明检索真的有效。

官方资料与版本提醒

型号、版本和组件会更新。教程解释稳定工程原则,真正安装时以官方页面为准。

← 返回第03章
Embedding 与语义检索基础
继续第04章 →
RAG 数据工程
↑ 返回本章目录Ctrl+Z