title: “使用 Milvus 的 RAG” weight: 400
在本模块中,我们将使用检索增强生成(Retrieval-Augmented Generation,RAG)将 agent 连接到产品目录。Milvus 已经部署在我们的环境中。连接完成后,agent 会用有依据的结果来回答产品问题(例如"我们们有 100 美元以下的无线耳机吗?"),而不是靠猜测。
Milvus 是一个开源向量数据库,专为大规模相似性搜索而构建。我们将数据存储为高维向量(embeddings),然后通过"找出离这个向量最近的向量"来进行查询。它支持多种索引类型(IVF、HNSW、DiskANN)、混合搜索(向量 + 标量过滤器),并且可以从单 pod 独立模式扩展到分布式集群。
milvus 命名空间中。无需外部向量数据库服务。all-MiniLM-L6-v2 的 fastembed
(ONNX runtime,约 20 MB),而不是完整的 PyTorch。相同的向量,镜像却小了约 80%。
search_productsall-MiniLM-L6-v2 权重)将查询嵌入化,并在 Milvus 中搜索相似的条目kubectl get pods -n milvus
我们应该看到 milvus-standalone、etcd 和 minio pod 正在运行。
cd ~/environment/modules/20-self-managed/400-rag-milvus/customer-agent
与 使用 Langfuse 的可观测性实验
相比,本模块引入了两个新文件:rag_tools.py,它定义了产品搜索工具;以及 seed_products.py,它作为一次性设置步骤将目录加载到 Milvus 中。除了这些新增内容外,改动很小。agent.py 添加了一个 import,而 Dockerfile 切换到了多阶段构建,以便将嵌入模型权重打包到最终镜像中。
_embedder = TextEmbedding(
model_name="sentence-transformers/all-MiniLM-L6-v2",
cache_dir="/app/.fastembed_cache",
)
_client = MilvusClient(uri=MILVUS_URI)
@tool
def search_products(query: str, limit: int = 5) -> list:
"""Search the AnyCompany Shop product catalog and FAQs.
Use this when a customer asks about products, pricing, shipping, returns, or warranties.
"""
embeddings = [v.tolist() for v in _embedder.embed([query])]
results = _client.search(COLLECTION, data=embeddings, ...)
all-MiniLM-L6-v2 模型。镜像中没有 Python ML 框架。
FROM public.ecr.aws/docker/library/python:3.12-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
RUN python -c "from fastembed import TextEmbedding; TextEmbedding(model_name='sentence-transformers/all-MiniLM-L6-v2', cache_dir='/app/.fastembed_cache')"
FROM public.ecr.aws/docker/library/python:3.12-slim
WORKDIR /app
COPY --from=builder /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
COPY --from=builder /usr/local/bin /usr/local/bin
COPY --from=builder /app/.fastembed_cache /app/.fastembed_cache
Builder 预先将 ONNX 模型下载到 /app/.fastembed_cache 中,运行时阶段只复制这些内容。pod 启动时无需访问 HuggingFace Hub。
seed_products.py 定义了约 13 个产品和 FAQs,将它们嵌入化,并插入到 product_catalog 集合中。与其为了一次性填充而在我们的 IDE 上安装 fastembed + pymilvus,我们将该脚本打包在 customer-agent 镜像中,并从集群中的一个 pod 运行它。
customer-agent:milvus 镜像在配置期间已经预先构建并推送到 ECR,因此直接运行 seeder:
IMG=$ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/customer-agent:milvus
kubectl run milvus-seed --rm -i --restart=Never \
--image=$IMG \
--image-pull-policy=Always \
--env="MILVUS_URI=http://milvus.milvus.svc.cluster.local:19530" \
--command -- python seed_products.py
我们应该看到 “Inserted 13 items” 以及针对 “wireless headphones” 的测试搜索返回了匹配项。脚本退出时该 pod 会消失。
envsubst < k8s.yaml | kubectl apply -f -
kubectl rollout status deployment/customer-agent --timeout=180s
打开聊天 UI,选择 Customer Agent (Self-managed GenAI),并尝试产品问题:
What's your return policy?
Do you have any noise cancelling headphones?
Is the Laptop Pro under warranty?
在 Langfuse 中,注意新的 search_products span,嵌入 + 搜索通常需要 50-200ms。

agent 现在有两个工具:lookup_order 用于特定订单,search_products 用于目录/FAQ 问题。产品知识由真实的 embeddings 支持,而不是硬编码的 switch 语句。
订单仍然在 agent 进程内部被模拟。接下来我们将把工具迁移到运行在 EKS 上的真实 MCP server 上。