跳转至

Milvus:向量检索与运维

Milvus 是向量数据库的一个具体实现。它负责从大量向量中找出与问题最相近的候选片段,并按元数据条件缩小范围;它不负责切分文档、生成 Embedding、重排结果,也不负责让大模型组织最终答案。

原始文档 → 清洗与切片 → Embedding 模型 → 向量 + 元数据写入 Milvus
用户问题 → 同一 Embedding 模型 → Milvus 过滤检索 → 候选片段 → Reranker → LLM 回答

它在知识系统中解决什么问题

当文档被切成几十万甚至更多片段后,系统需要在可接受的时间内找出语义相近、权限允许、且属于当前场景的内容。Milvus 的职责就是这一段“候选召回”。

例如用户问“某站点链路中断后如何排查”:查询向量表达问题语义;site_id、设备厂商、文档类型和权限范围作为过滤条件;Milvus 返回最可能有关的 20~50 个片段。之后再由重排模型挑出最可靠的 3~8 段,交给 LLM 基于证据作答。

因此,Milvus 检索结果不好时,问题不一定出在数据库:也可能是切片切坏了、Embedding 模型不适合、元数据缺失、过滤条件错误,或没有重排。

核心对象:一张可检索的知识片段表

Milvus 中最重要的对象是 Collection,可以理解为一张面向向量检索的数据表。它需要先定义 Schema;每条记录至少包含一个主键、一个向量字段,以及支撑过滤与回溯的标量字段。

对象 作用 知识库中的建议
Collection 一类可共同检索的数据集合 按业务域或数据生命周期拆分,例如 ops_knowledge_chunks
Primary Key 唯一标识一条记录 使用稳定的 chunk_id,不要用会随重新切片变化的序号
Vector Field 保存 Embedding,用于近邻搜索 embedding;维度必须与所用模型完全一致
Scalar Fields 字符串、数字、布尔等元数据 文档、章节、站点、设备、权限、更新时间、模型版本
Index 加速近似最近邻检索 依据规模、内存和召回目标选择 HNSW、IVF 等
Partition 物理或逻辑分组手段 只在有明确隔离或生命周期需求时使用,不能替代通用元数据过滤

一个实用的知识片段 Schema 可以从下面这些字段开始:

字段 示例 为什么需要
chunk_id linux-ssh-001-03 回写、删除和去重的稳定主键
embedding [0.012, -0.083, ...] 片段的语义表示
document_id linux-ssh-guide-v2 将多个片段归回同一份文档
title / section_path SSH 加固 / 权限 > SSH 结果展示、引用与上下文拼接
source_url 文档来源地址 让答案可以追溯到原文
site_id / device_vendor sh-a01 / huawei 让检索贴合现场对象
permission_scope ops-team-a 防止跨团队或跨客户召回
updated_at 时间戳 支持优先使用较新的内容
embedding_model_version bge-m3-2026-01 模型升级时区分旧、新向量

text 正文可以一并保存,方便直接取回;也可以只保存内容定位信息,把全文放在对象存储或原始文档库中。无论采用哪种方式,检索结果都必须能稳定取得原文与来源。

写入链路:先把数据准备对

  1. 确定边界与权限:明确哪些文档能进入知识库,给每份文档补齐来源、业务域、站点和权限等元数据。
  2. 清洗、切片、保留上下文:按语义段落切片,并保留标题路径、章节、前后片段关联。只把孤立的一小段文字塞进向量库,往往会造成“召回到了但看不懂”。
  3. 统一生成向量:同一 Collection 内的向量必须使用兼容的模型、维度和相似度度量。切换模型时应做版本隔离或全量重建,不能新旧向量混写。
  4. 写入向量和标量字段:写入时同时保存文本定位与过滤字段,不能只存 id + embedding
  5. 建索引并加载服务:数据写入后建立索引,再将可检索数据加载到查询服务;用一组真实问题验证结果后才接入应用。

查询链路:Milvus 只负责候选召回

问题
  → 查询改写(可选)
  → Query Embedding
  → Milvus:权限 / 站点 / 文档状态等元数据过滤 + Top K 近邻搜索
  → Reranker:从候选中重新排序
  → LLM:带引用生成答案,无法支持时明确说明

先做标量过滤,再在符合条件的数据中进行近邻搜索,能减少无关候选,也避免把本不应出现的数据送给后续模型。过滤条件必须来自可信的登录身份或业务上下文,不能只相信用户在问题中写的“我是某某团队”。

Top K 不是越大越好。过小会漏召回;过大则会增加重排成本并给 LLM 带入噪声。可以先以 20~50 作为候选数、以 3~8 作为最终上下文的起点,再通过题库评测调整。

最小可用的召回代码

下面的代码刻意把 Embedding 生成留在 Milvus 外部:embed_query() 应调用你统一选定的 Embedding 模型,且返回维度必须等于 Collection 的维度。site_idpermission_scope 应由后端根据登录身份写入,不能让前端任意传入。

from pymilvus import MilvusClient

client = MilvusClient(
    uri="http://milvus.internal:19530",
    token="${MILVUS_TOKEN}",
)

question = "华为交换机配置 OSPF 后邻居没有建立,如何排查?"
query_vector = embed_query(question)  # 例如返回 1024 个 float

results = client.search(
    collection_name="ops_knowledge_chunks",
    data=[query_vector],
    filter="site_id == 'sh-a01' and permission_scope in ['netops']",
    limit=30,  # Milvus 的候选召回数,不是最终喂给 LLM 的段数
    output_fields=["chunk_id", "text", "title", "section_path", "source_url"],
)

candidates = results[0]
top_context = rerank(question, candidates)[:5]
answer = llm_answer(question, top_context)

search() 返回的是距离/相似度和指定的 output_fields。应用服务应记录问题、过滤条件、候选 ID、分数、重排后结果与最终引用;这样出现错误答案时,才能判定是“没召回”还是“召回后没用好”。

召回效果应该怎样验收

准备 30~100 个真实问题,每题标记至少一段正确证据。对每次模型、切片或索引变更,比较下面三层,而不是只看一个相似度分数:

层次 要问的问题 例子
Milvus 候选层 正确片段是否进入 Top 30? Top-30 中有正确 OSPF 故障处理步骤
重排层 正确片段是否进入 Top 5? 设备厂商、场景最贴近的步骤排到前面
回答层 LLM 是否依据证据回答并给出引用? 不把其他厂商命令混入答案;无证据时拒答

候选层漏了正确内容,优先查切片、Embedding、过滤和 Top K;候选层命中了但答案错,才重点查 Reranker、Prompt 和 LLM。

索引与调优:先看质量,再看参数

HNSW 常用于低延迟、高召回的在线检索,但会占用更多内存。三个容易遇到的参数是:

参数 主要影响 调整方向
M 图连接数、召回与内存 提高通常有利于召回,但会增加内存与构建成本
efConstruction 建索引时的搜索深度 提高通常改善索引质量,但建索引更慢
ef 查询时的候选探索量 提高通常改善召回,但延迟会上升

调优顺序建议如下:先固定切片规则、Embedding 模型、度量方式和评测集;再确认是否需要元数据过滤;最后才用同一批问题对比 Top K、索引与查询参数。直接调 ef,无法修复“切片没有保留故障现象”或“文档版本已经过期”这类数据问题。

部署:开发能跑与生产可用不是一回事

1. 单机验证:Docker Compose

适合个人学习、开发联调和小规模 PoC。先创建专用目录,再下载与当前 Milvus 版本匹配的官方 Compose 文件:

mkdir -p /opt/milvus-standalone
cd /opt/milvus-standalone
wget https://github.com/milvus-io/milvus/releases/download/v3.0.0/milvus-standalone-docker-compose.yml -O docker-compose.yml
docker compose up -d
docker compose ps

官方 Standalone Compose 会启动 milvus-standalonemilvus-etcdmilvus-minio:Milvus 对外提供 gRPC/API 端口 19530etcd 保存元数据,MinIO 保存对象数据。确认容器健康后,可在服务器本机打开 http://127.0.0.1:9091/webui/ 查看状态。

docker compose logs --tail=100 standalone
curl -I http://127.0.0.1:9091/webui/

不要为了方便把 19530、MinIO 管理端口或 WebUI 直接暴露到公网;应用与 Milvus 应处于同一内网或容器网络,通过安全组、防火墙和认证限制访问。Compose 文件里的 volumes/ 保存持久化数据,升级、迁移或清理前必须先备份;docker compose down 只停服务,删除 volumes/ 才会删除数据。

安装 Python 客户端并做连接验证:

python3 -m pip install -U pymilvus
python3 - <<'PY'
from pymilvus import MilvusClient
client = MilvusClient(uri="http://127.0.0.1:19530", token="root:Milvus")
print(client.list_collections())
PY

root:Milvus 是官方示例的初始凭据,只能用于本地验证;接入任何共享环境前应建立专用应用账户或令牌、改掉默认凭据,并将密钥放入 Secret/环境变量,而不是 Markdown、代码仓库或镜像中。

2. Kubernetes:生产集群的起点

适合需要高可用、容量扩展或多个应用共享检索服务的场景。前置条件是 Kubernetes、Helm 和可用的 StorageClass;生产环境还应先确定持久卷类别、对象存储、备份位置、网络策略和资源配额。

helm repo add zilliztech https://zilliztech.github.io/milvus-helm/
helm repo update
helm install knowledge-milvus zilliztech/milvus \
  --namespace milvus --create-namespace \
  --set image.all.tag=v3.0.0 \
  --set woodpecker.enabled=true \
  --set woodpecker.image.tag=v0.1.37 \
  --set streaming.enabled=true \
  --set streaming.woodpecker.embedded=false \
  --set indexNode.enabled=false
kubectl get pods -n milvus

上面的命令用于建立当前官方推荐架构的基线,不是生产最终配置。正式上线应把所有覆盖项写入受版本控制的 values.yaml,至少明确 PVC 的 StorageClass/容量、对象存储、资源 requests/limits、认证与 TLS、网络策略、监控、备份和版本固定。不要用 latest 标签,也不要在没有快照和回滚方案时直接升级 Chart。

3. 部署后的验收顺序

  1. 容器或 Pod 全部就绪,日志没有反复重启、磁盘或对象存储报错。
  2. 应用网络能连通 19530,但未授权网络不能连通。
  3. 用一个已知维度的 Embedding 创建 Collection,写入 3~10 条测试片段。
  4. 用同一模型生成查询向量,验证 Top K 能返回预期片段和所需 output_fields
  5. 再测试权限过滤、文档更新删除、备份恢复与节点重启,而不是只测试“服务端口已监听”。
场景 建议 关注点
本地学习、功能验证 使用单机或 Standalone 方便验证 Schema、写入和检索闭环,数据可随时重建
小规模内部知识库 独立服务部署,做好持久化与备份 容量、内存、索引构建时间、权限字段
生产级检索服务 按当前发行版的集群架构部署 元数据存储、对象存储、查询与数据组件、监控、扩缩容与故障恢复

Milvus 的组件会随发行版与部署方式变化。生产部署应以当前官方 Helm Chart 或运维文档为准,不要直接照搬旧版本教程中的组件名和端口。无论哪种方式,都要把数据目录、对象存储、元数据和访问凭据纳入备份与恢复演练。

日常运维与验收

上线前,不要只测“接口返回 200”。至少准备一组覆盖同义问法、缩写、站点限定、权限边界和无答案问题的评测集,并持续观察:

  • 召回质量:Recall@K、重排后命中率、无依据回答比例。
  • 性能:查询 P50/P95、过滤后的延迟、索引构建耗时、写入积压。
  • 资源:查询节点内存、索引与原始向量占用、对象存储容量、加载状态。
  • 数据健康度:向量维度、模型版本、重复片段、失效文档、缺失元数据。
  • 安全性:过滤条件是否由服务端强制注入,日志中是否泄露正文或敏感检索词。

常见问题定位

现象 优先检查
写入失败或查询报维度错误 Embedding 模型、向量维度、Collection Schema 是否一致
能搜到相似话题,却不是正确步骤 切片是否包含完整上下文;是否需要 Reranker;Top K 是否过小
跨站点、跨客户返回了内容 site_idpermission_scope 等服务端过滤是否遗漏
更新文档后仍回答旧内容 旧 chunk 是否删除或标记失效;索引与缓存是否刷新;版本是否可追溯
延迟突然升高 过滤条件命中范围、ef、Top K、索引加载状态、并发与内存是否变化
召回越来越差 是否混入不同 Embedding 模型的向量;评测集是否已经失去代表性

何时选择 Milvus

如果向量检索会成为独立的长期服务,数据量、并发、过滤条件或运维要求逐渐增长,Milvus 是合适的候选。若只是少量文档和已有 PostgreSQL 系统,可先评估 pgvector;本地原型也可以用 Chroma 一类更轻的方案。关键不是产品名,而是能否把“数据质量、权限过滤、召回评测、可恢复运维”这条链路做好。

官方资料