Milvus 向量库实践
Milvus 是面向 大规模向量相似检索 的开源向量数据库,RAG 里负责存 embedding、做 top-k 搜索。本篇讲核心概念与最小 ingest / search;与 LangChain 拼装见下文「LangChain + Milvus」。流水线概念见 RAG 与检索增强;Chroma 本地 PoC 见 [LangChain RAG 实践](/docs/ai/RAG/LangChain RAG 实践)。
在 RAG 里的位置
切分(chunk) → embedding → 【Milvus 入库】→ 问句 embedding → 【Milvus search】→ 拼 Prompt → 生成
| RAG 阶段 | Milvus 对应 |
|---|---|
| 写入索引 | insert / LangChain add_documents |
| 检索 top-k | search / as_retriever |
| 元数据过滤 | collection 里 VARCHAR 字段 + filter 表达式 |
| 持久化 | Milvus Lite 文件 / Docker 服务 / Zilliz Cloud |
何时从 Chroma 换 Milvus:数据量上来、要多副本与高可用、要混合检索(dense + sparse)、要上生产集群——PoC 继续用 Chroma 即可。
部署形态(选型)
| 形态 | URI 示例 | 适合 |
|---|---|---|
| Milvus Lite | ./milvus.db | 本地开发、小库、零 Docker |
| Standalone(Docker) | http://localhost:19530 | 本机/团队联调、中等规模 |
| Zilliz Cloud | 云端 endpoint + token | 托管、免运维 |
Milvus Lite 把库写在本地文件,API 与服务器版一致,最适合「先跑通再迁 Docker」。
本地 Standalone(示意):
# 见 https://milvus.io/docs/install_standalone-docker.md
curl -sfL https://raw.githubusercontent.com/milvus-io/milvus/master/scripts/standalone_embed.sh | bash -s -- start
核心概念
| 概念 | 直觉 |
|---|---|
| Collection | 类似表;一个 RAG 知识库常对应一个 collection |
| Schema | 字段定义:主键、FLOAT_VECTOR、文本/metadata(VARCHAR) |
| Index | 向量索引(如 AUTOINDEX、HNSW);必须先建 index 再 load/search |
| metric_type | 距离度量:COSINE(文本常用)、L2、IP;与 embedding 训练方式一致 |
PyMilvus 最小流程
依赖:pip install pymilvus(版本以 Milvus 文档 为准)。
# milvus_rag/ingest_search.py
from pymilvus import MilvusClient, DataType
URI = "./milvus.db" # Milvus Lite;Docker 用 http://localhost:19530
COLLECTION = "rag_docs"
DIM = 128 # 与 embedding 模型维度一致
client = MilvusClient(uri=URI)
if client.has_collection(COLLECTION):
client.drop_collection(COLLECTION)
schema = client.create_schema(auto_id=True)
schema.add_field("id", DataType.INT64, is_primary=True)
schema.add_field("vector", DataType.FLOAT_VECTOR, dim=DIM)
schema.add_field("text", DataType.VARCHAR, max_length=2048)
schema.add_field("source", DataType.VARCHAR, max_length=256)
index_params = client.prepare_index_params()
index_params.add_index(
field_name="vector",
index_type="AUTOINDEX",
metric_type="COSINE",
)
client.create_collection(
collection_name=COLLECTION,
schema=schema,
index_params=index_params,
)
# 示例:实际应换真实 embedding
rows = [
{"vector": [0.1] * DIM, "text": "退货 7 天内可退", "source": "policy.txt"},
{"vector": [0.2] * DIM, "text": "包邮门槛 99 元", "source": "policy.txt"},
]
client.insert(collection_name=COLLECTION, data=rows)
query_vec = [[0.15] * DIM]
hits = client.search(
collection_name=COLLECTION,
data=query_vec,
limit=3,
output_fields=["text", "source"],
)
print(hits)
顺序要点:create_collection → insert →(若未随 collection 自动建索引则 create_index)→ load(Lite 常自动)→ search。无 index 就 search 会报错。
与 LangChain 拼装
PoC 用 Chroma;换 Milvus 通常只改 VectorStore,Loader / Splitter / Retriever 不变。包:langchain-milvus(以官方集成文档为准)。
from langchain_community.document_loaders import TextLoader
from langchain_community.embeddings import FakeEmbeddings
from langchain_milvus import Milvus
from langchain_text_splitters import RecursiveCharacterTextSplitter
from pathlib import Path
embeddings = FakeEmbeddings(size=128) # 上线换真实 Embeddings
docs = []
for path in Path("data").glob("*.txt"):
docs.extend(TextLoader(str(path), encoding="utf-8").load())
splits = RecursiveCharacterTextSplitter(
chunk_size=200, chunk_overlap=40
).split_documents(docs)
vector_store = Milvus.from_documents(
documents=splits,
embedding=embeddings,
connection_args={"uri": "./milvus.db"},
collection_name="langchain_rag",
drop_old=True,
)
retriever = vector_store.as_retriever(search_kwargs={"k": 3})
docs = retriever.invoke("退货几天内可以?")
| [LangChain RAG 实践](/docs/ai/RAG/LangChain RAG 实践) | LangChain + Milvus |
|---|---|
Chroma(persist_directory=...) | Milvus(connection_args={"uri": ...}) |
| 本地目录持久化 | Lite 文件或 19530 服务 |
| 小 PoC | 更接近生产的向量库 |
生成与拒答逻辑直接复用 LangChain 篇的 answer 模板即可。
混合检索(点到为止)
Milvus 2.x 支持 dense + sparse(如 BM25 内置函数)做混合检索,适合专有名词、编号类 query。配置比单向量复杂,建议 Naive 向量基线评测后再加。详见 Milvus 全文检索文档。
常见坑
- 维度不一致:schema 的
dim必须与 embedding 输出长度相同。 - metric 选错:文本 embedding 多用
COSINE;换模型时确认训练时用的相似度。 - 未建 index / 未 load:insert 后 search 失败,先查 index 与 load 状态。
- insert 与 query 不是同一 URI:Lite 文件路径或 Docker 地址 ingest / query 必须一致。
- 把 Milvus 当 GraphRAG:Milvus 是向量库;全局主题归纳仍见 [GraphRAG 概览与查询](/docs/ai/RAG/GraphRAG 概览与查询)。
与 Chroma / FAISS 对比
| Chroma / 本地 FAISS | Milvus | |
|---|---|---|
| 定位 | 轻量 PoC、嵌入式 | 生产级向量库、可扩展 |
| 部署 | 进程内 / 本地目录 | Lite 文件 / Docker / 云 |
| 混合检索、分区 | 有限 | 原生支持更强 |
| RAG 教程默认 | 常见默认 | 数据量大时更常见 |
实践要点
- 先 RAG 落地实践 → [LangChain RAG 实践](/docs/ai/RAG/LangChain RAG 实践),再把 VectorStore 换成 Milvus,改动最小。
- 本地用 Milvus Lite(
./milvus.db)即可对照学习,不必先搭 K8s。 - collection 设计时预留
source、租户 id 等 VARCHAR,便于 RAG 权限过滤(见概念篇失效模式)。 - 用同一套
eval_set.jsonl对比 Chroma vs Milvus 召回,验证迁移未退化。 - 面试挂钩:说清 Collection / Index / metric / top-k search,以及 Milvus 在 RAG 流水线中的位置即可。