Milvus + LangChain + Ollama 搭建生产级 RAG(含 Tag / Metadata 解析)

本文记录一次从 Milvus 容器反复重启、端口拒绝,到最终稳定运行并实现 LangChain RAG 成功检索的完整实战过程。适用于本地 RAG、私有大模型、知识库系统等场景。

一、背景与问题

在本地构建 RAG(Retrieval-Augmented Generation)时,开发者常遇到以下典型问题:

  • telnet 19530 连接被拒绝
  • Milvus 容器反复 Restarting (1)
  • pymilvus 能连上,但 LangChain 查不到数据
  • 不清楚 Milvus 中的「tag / metadata」到底存在哪里

本文基于 Milvus 2.4 + LangChain + Ollama(Qwen + bge-m3),逐步解决上述问题。

二、整体架构

复制代码
LangChain
   │
   ├─ Ollama Embedding (bge-m3)
   │
   ├─ Milvus Vector Store
   │     ├─ etcd
   │     ├─ minio
   │     └─ standalone
   │
   └─ Ollama LLM (qwen2.5)

Python 3.9 / 3.10 / 3.11 均可支持。

bash 复制代码
pip install -U \
  langchain \
  langchain-core \
  langchain-community \
  langchain-text-splitters \
  langchain-ollama \
  pymilvus \
  faiss-cpu

三、Milvus Docker Compose(稳定版)

注意:Milvus standalone 必须依赖 etcd + minio,不能直接使用 docker run milvusdb/milvus,否则 19530 端口不会监听。

docker-compose.yml

yaml 复制代码
version: '3.5'

services:
  rag-etcd:
    container_name: rag-milvus-etcd
    image: quay.io/coreos/etcd:v3.5.5
    volumes:
      - ./rag-volumes/etcd:/etcd
    command: >
      etcd
      -advertise-client-urls=http://127.0.0.1:2379
      -listen-client-urls http://0.0.0.0:2379
      --data-dir /etcd

  rag-minio:
    container_name: rag-milvus-minio
    image: minio/minio:RELEASE.2023-03-20T20-16-18Z
    environment:
      MINIO_ACCESS_KEY: minioadmin
      MINIO_SECRET_KEY: minioadmin
    ports:
      - "19000:9000"
      - "19001:9001"
    volumes:
      - ./rag-volumes/minio:/minio_data
    command: minio server /minio_data --console-address ":9001"

  rag-milvus:
    container_name: rag-milvus-standalone
    image: milvusdb/milvus:v2.4.0
    command: ["milvus", "run", "standalone"]
    environment:
      ETCD_ENDPOINTS: rag-etcd:2379
      MINIO_ADDRESS: rag-minio:9000
    volumes:
      - ./rag-volumes/milvus:/var/lib/milvus
    ports:
      - "19530:19530"
      - "9091:9091"
    depends_on:
      - rag-etcd
      - rag-minio

networks:
  default:
    name: rag-milvus-net

启动命令:

bash 复制代码
docker compose up -d

四、验证 Milvus 是否正常

telnet 验证端口

bash 复制代码
telnet 127.0.0.1 19530

若看到如下输出:

复制代码
Connected to 127.0.0.1.
HTTP/1.1 400 Bad Request

这是正常现象,因为 19530 是 gRPC 端口,并非 HTTP 接口。

Python 连接 Milvus

python 复制代码
from pymilvus import connections, utility, Collection

connections.connect(
    host="127.0.0.1",
    port="19530"
)

print("connected:", connections.has_connection("default"))
print("collections:", utility.list_collections())

五、理解 Milvus 里的 "tag / metadata"

Milvus 没有内置 tag 概念。所谓的 tag,本质是 Collection schema 中的 scalar 字段。

查看 collection schema:

python 复制代码
col = Collection("rag_qwen_prod")
print(col.schema)

典型结构如下:

复制代码
id (INT64, primary)
vector (FLOAT_VECTOR)
text (VARCHAR)
source (VARCHAR)
category (VARCHAR)

其中 source / category 即为 RAG 中的 tag。

六、LangChain + Ollama + Milvus 实战

Embedding(bge-m3)

python 复制代码
from langchain_ollama import OllamaEmbeddings

embeddings = OllamaEmbeddings(
    model="bge-m3",
    base_url="http://192.168.31.161:11434"
)

构造文档

python 复制代码
from langchain_core.documents import Document

docs = [
    Document(page_content="RAG 是检索增强生成"),
    Document(page_content="Milvus 是生产级向量数据库"),
    Document(page_content="Qwen2.5 是高质量中文大模型"),
]

文本切分

python 复制代码
from langchain_text_splitters import RecursiveCharacterTextSplitter

splitter = RecursiveCharacterTextSplitter(
    chunk_size=300,
    chunk_overlap=50
)
docs = splitter.split_documents(docs)

写入 Milvus

python 复制代码
from langchain_community.vectorstores import Milvus

vectorstore = Milvus.from_documents(
    docs,
    embedding=embeddings,
    collection_name="rag_qwen_prod",
    connection_args={
        "host": "localhost",
        "port": "19530"
    }
)

Retriever

python 复制代码
retriever = vectorstore.as_retriever(
    search_kwargs={"k": 3}
)

LLM(Qwen2.5)

python 复制代码
from langchain_ollama import ChatOllama

llm = ChatOllama(
    model="qwen2.5:7b",
    temperature=0
)

Prompt & LCEL RAG Chain

python 复制代码
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough

prompt = ChatPromptTemplate.from_messages([
    ("system", "你只能基于上下文回答问题,不允许编造"),
    ("human", "上下文:\n{context}\n\n问题:{question}")
])

rag_chain = (
    {
        "context": retriever,
        "question": RunnablePassthrough()
    }
    | prompt
    | llm
)

查询验证

python 复制代码
result = rag_chain.invoke("什么是 Milvus?")
print(result.content)

输出示例:

复制代码
Milvus 是一个生产级向量数据库,用于高效存储和检索向量数据。

RAG 生效。

七、完整代码与常见问题总结

python 复制代码
from langchain_ollama import ChatOllama, OllamaEmbeddings
from langchain_community.vectorstores import Milvus
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_core.documents import Document
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough

# 1. Embedding
embeddings = OllamaEmbeddings(
    model="bge-m3",
    base_url="http://192.168.31.161:11434"
)

# 2. 文档
docs = [
    Document(page_content="RAG 是检索增强生成"),
    Document(page_content="Milvus 是生产级向量数据库"),
    Document(page_content="Qwen2.5 是高质量中文大模型"),
]

# 3. 切分
splitter = RecursiveCharacterTextSplitter(
    chunk_size=300,
    chunk_overlap=50
)
docs = splitter.split_documents(docs)

# 4. Milvus Vector Store
vectorstore = Milvus.from_documents(
    docs,
    embedding=embeddings,
    collection_name="rag_qwen_prod",
    connection_args={
        "host": "localhost",
        "port": "19530"
    }
)

retriever = vectorstore.as_retriever(search_kwargs={"k": 3})

# 5. LLM
llm = ChatOllama(
    model="qwen2.5:7b",
    temperature=0
)

# 6. Prompt
prompt = ChatPromptTemplate.from_messages([
    ("system", "你只能基于上下文回答问题,不允许编造"),
    ("human", "上下文:\n{context}\n\n问题:{question}")
])

# 7. LCEL RAG Chain
rag_chain = (
    {
        "context": retriever,
        "question": RunnablePassthrough()
    }
    | prompt
    | llm
)

# 8. Query
result = rag_chain.invoke("什么是 Milvus?")
print(result.content)
问题 原因
19530 连接被拒绝 直接 docker run Milvus
容器重启 缺少 etcd / minio
telnet 返回 400 正常(gRPC)
查不到 tag schema 没定义 metadata
LangChain 无结果 embedding 不一致

八、下一步可以做什么?

  • 多 tag / 多租户 RAG
  • expr 过滤(category == 'ops'
  • Milvus IVF / HNSW 调优
  • Streaming RAG
  • Web UI + API 服务化

九、结语

Milvus + LangChain + Ollama 是目前本地 RAG 的黄金组合:

  • Milvus:性能与扩展性
  • Ollama:本地模型自由
  • LangChain:链路清晰、可组合

如果你已经走到这一步,说明你已经不是"入门玩家"了。

相关推荐
老蒋每日coding4 小时前
AI Agent 设计模式系列(十一)—— 目标设定和监控模式
人工智能·设计模式·langchain
linmoo19865 小时前
Langchain4j 系列之二十七 - Ollama集成Deepseek
人工智能·langchain·ollama·deepseek·langchain4j
TracyCoder1235 小时前
LLM应用开发框架技术选型指南:LangChain vs LlamaIndex
langchain
nvd1121 小时前
LangChain LCEL 工具调用实战:从确定性链到动态 Agent
langchain
北京地铁1号线1 天前
2.2 向量数据库
数据库·elasticsearch·milvus·faiss·向量数据库·hnsw
大数据001 天前
基于Ollama大模型学习
python·flask·大模型·alibaba·ollama·springai·deepseek
YHLG1 天前
LangChain v1.0+ 入门详解:概念、架构、组件、模板与实战
python·langchain
西柚小萌新1 天前
【人工智能:Agent】--7.Langchain短期记忆
langchain
眠りたいです1 天前
使用LangChain进行AI应用构建-快速上手,定义模型和调用工具部分
人工智能·langchain·llm·ollama·python3.13