首页
/ vLLM 部署 RAG 检索增强生成系统:基于 LangChain 与 LlamaIndex 的 Milvus 向量库集成实战

vLLM 部署 RAG 检索增强生成系统:基于 LangChain 与 LlamaIndex 的 Milvus 向量库集成实战

2026-09-04 13:58:24作者:舒璇辛Bertina

本文基于 vLLM 官方文档 Retrieval-Augmented Generation 与仓库内两个 RAG 示例脚本(LangChain 版LlamaIndex 版),完整讲解如何用 vLLM 同时承载 Embedding 服务与 Chat 服务,配合 Milvus 向量库搭建一套可运行的检索增强生成(RAG)流水线。读完后你将掌握:双服务部署方式、两套框架的完整命令行参数、文档加载与分块策略,以及 vLLM OpenAI 兼容接口在 RAG 场景下的调用方式。

什么是 RAG,以及 vLLM 在其中的角色

Retrieval-Augmented Generation(RAG,检索增强生成) 是一种让生成式 AI 模型能够检索并融入新信息的技术。它改变 LLM 的交互方式:模型在回答用户问题时,会参考一组指定文档,用这些信息补充模型预训练数据中已有的知识,从而使用领域特定信息或最新信息。典型用例包括:让聊天机器人访问公司内部数据,或基于权威来源生成回答。

vLLM 在这条流水线中承担两个 OpenAI 兼容的推理服务

  • Embedding 服务(默认端口 8000):以 /v1/embeddings 接口提供文本向量化。从源码看,该路由定义在 vllm/entrypoints/pooling/embed/api_router.py 中,POST /v1/embeddings 请求经 validate_json_request 校验后交给 ServingEmbedding 处理器,因此任意 OpenAI 客户端库(如 langchain_openai.OpenAIEmbeddingsllama_index.embeddings.openai_like.OpenAILikeEmbedding)只需把 base URL 指向 vLLM 即可工作。
  • Chat 服务(默认端口 8001):以 /v1/chat/completions 接口提供基于检索上下文的生成回答。

仓库提供的两种集成方案为:

  • vLLM + LangChain + Milvus
  • vLLM + LlamaIndex + Milvus

两种方案的服务端部署完全一致,区别仅在客户端编排框架。

方案一:vLLM + LangChain + Milvus

1. 环境准备

安装 vLLM 与 LangChain 相关依赖:

pip install -U vllm \
            langchain_milvus langchain_openai \
            langchain_community beautifulsoup4 \
            langchain-text-splitters

其中 langchain_community(提供 WebBaseLoader 网页加载器)、beautifulsoup4(HTML 解析)与 langchain-text-splittersRecursiveCharacterTextSplitter 分块器)都是示例脚本的显式依赖,缺装会在 import 阶段报错。

2. 部署两个 vLLM 服务

# Start embedding service (port 8000)
vllm serve ssmits/Qwen2-7B-Instruct-embed-base

# Start chat service (port 8001)
vllm serve qwen/Qwen1.5-0.5B-Chat --port 8001

注意两个要点:

  • Embedding 模型与 Chat 模型分别运行在独立的 vLLM 实例上,端口分别为 8000 与 8001,客户端通过不同的 base URL 区分它们;
  • 首次运行可能需要较长时间下载模型权重(脚本注释中亦提示了这一点)。

3. 运行示例脚本

脚本位于 examples/applications/rag/retrieval_augmented_generation_with_langchain.py

python retrieval_augmented_generation_with_langchain.py

不带参数时,脚本会加载默认 URL 的文档、建库,并用固定问题 "How to install vLLM?" 做一次问答。

4. 完整命令行参数说明

脚本通过 argparse 暴露了全部可配置项(定义见 get_parser(),见 脚本 L136-L191):

参数 简写 默认值 说明
--vllm-api-key - EMPTY vLLM 兼容服务的 API key(vLLM 默认不校验,故可填 EMPTY)
--vllm-embedding-endpoint - http://localhost:8000/v1 Embedding 服务 base URL
--vllm-chat-endpoint - http://localhost:8001/v1 Chat 服务 base URL
--uri - ./milvus.db Milvus 数据库 URI(本地 SQLite 文件即轻量版 Milvus Lite)
--url - vLLM 官方 quickstart 文档页 待处理的文档 URL
--embedding-model - ssmits/Qwen2-7B-Instruct-embed-base 向量化模型名
--chat-model - qwen/Qwen1.5-0.5B-Chat 对话模型名
-i / --interactive - 关闭 开启交互式问答模式(输入 q/quit 退出)
-k / --top-k - 3 每次检索返回的文档块数量
-c / --chunk-size - 1000 文档分块大小(字符数)
-o / --chunk-overlap - 200 相邻分块重叠大小

例如处理自定义网页并以交互模式问答:

python retrieval_augmented_generation_with_langchain.py \
    --url https://example.com/your-doc.html \
    -i -k 4

5. 脚本内部流程(源码剖析)

脚本的 main() 按顺序执行四个阶段,每一阶段都对应 RAG 流水线的标准环节:

  1. 文档加载与分块load_and_split_documents):用 WebBaseLoader 抓取网页正文,再用 RecursiveCharacterTextSplitter(chunk_size, chunk_overlap) 递归切分。分块参数直接影响检索粒度——块太大则向量语义被稀释,块太小则上下文不足,默认 1000/200 是常用起点。
  2. 向量库初始化init_vectorstore):Milvus.from_documents(..., drop_old=True) 将分块向量化后写入 Milvus;OpenAIEmbeddingsopenai_api_base 指向 vLLM 的 8000 端口,即所有 embedding 请求实际由 vLLM 计算。drop_old=True 保证重复运行时旧集合被清空。
  3. LLM 初始化init_llm):ChatOpenAI 指向 8001 端口的 vLLM Chat 服务。
  4. QA 链组装create_qa_chain):
return (
    {
        "context": retriever | format_docs,
        "question": RunnablePassthrough(),
    }
    | prompt
    | llm
    | StrOutputParser()
)

这是一个典型的 LangChain 可运行(Runnable)管道:检索器取回 top_k 个文档块并由 format_docs\n\n 拼接为 context,与 question 一起填入 QA prompt 模板(模板要求"若不知道答案就直说不知道,回答不超过三句"),最后经 LLM 生成并以字符串输出。

方案二:vLLM + LlamaIndex + Milvus

1. 环境准备

pip install vllm \
            llama-index llama-index-readers-web \
            llama-index-llms-openai-like    \
            llama-index-embeddings-openai-like \
            llama-index-vector-stores-milvus \

其中 llama-index-readers-web 提供 SimpleWebPageReaderllama-index-llms-openai-like / llama-index-embeddings-openai-like 提供 OpenAI 兼容端点的 LLM 与 Embedding 客户端,llama-index-vector-stores-milvus 提供 MilvusVectorStore

2. 部署 vLLM 服务

与方案一完全相同,两个服务的启动命令保持不变:

# Start embedding service (port 8000)
vllm serve ssmits/Qwen2-7B-Instruct-embed-base

# Start chat service (port 8001)
vllm serve qwen/Qwen1.5-0.5B-Chat --port 8001

3. 运行示例脚本

脚本位于 examples/applications/rag/retrieval_augmented_generation_with_llamaindex.py

python retrieval_augmented_generation_with_llamaindex.py

4. 完整命令行参数说明

参数定义见 脚本 L120-L175

参数 简写 默认值 说明
--url - vLLM 官方 quickstart 文档页 待处理的文档 URL
--embedding-model - ssmits/Qwen2-7B-Instruct-embed-base 向量化模型名
--chat-model - qwen/Qwen1.5-0.5B-Chat 对话模型名
--vllm-api-key - EMPTY vLLM 兼容服务的 API key
--embedding-endpoint - http://localhost:8000/v1 Embedding 服务 base URL
--chat-endpoint - http://localhost:8001/v1 Chat 服务 base URL
--db-path - ./milvus_demo.db Milvus 数据库文件路径
-i / --interactive - 关闭 开启交互式问答模式(输入 quit/exit/q 退出)
-c / --chunk-size - 1000 文档分块大小
-o / --chunk-overlap - 200 相邻分块重叠大小
-k / --top-k - 3 每次检索返回的文档块数量

5. 脚本内部流程(源码剖析)

main() 的执行顺序为:加载文档 → 配置模型 → 初始化向量库 → 建索引 → 查询。

  • 加载文档load_documents):SimpleWebPageReader(html_to_text=True) 将网页 HTML 转为纯文本节点,与 LangChain 版中 WebBaseLoader 的作用对应。
  • 配置模型setup_models):把 OpenAILikeEmbeddingOpenAILike 挂到 LlamaIndex 的全局 Settings 上,两者的 api_base 分别指向 8000/8001 端口的 vLLM 服务;同时把 SentenceSplitter(chunk_size, chunk_overlap) 设为默认变换管道,在索引时完成分块。值得注意的是 OpenAILike 客户端硬编码了 context_window=128000 并声明 is_chat_model=True,从源码结构看这是为 LlamaIndex 的提示词填充逻辑预留的上下文窗口声明,与底层 Qwen1.5-0.5B 的实际窗口无直接关系。
  • 初始化向量库setup_vector_store):
sample_emb = Settings.embed_model.get_text_embedding("test")
print(f"Embedding dimension: {len(sample_emb)}")
return MilvusVectorStore(uri=db_path, dim=len(sample_emb), overwrite=True)

这是一个很实用的技巧:先向 vLLM Embedding 服务请求一条测试文本的向量,用返回向量的长度动态确定 dim 再建库,避免手工指定维度与模型不匹配。

  • 建索引create_index):通过 StorageContext.from_defaults(vector_store=...) 把 Milvus 向量库注入 VectorStoreIndex.from_documents
  • 查询query_document):index.as_query_engine(similarity_top_k=top_k) 生成查询引擎,按相似度取回 top-k 个节点后由 LLM 生成回答。

两套方案的对比与共同要点

维度 LangChain 方案 LlamaIndex 方案
网页加载 WebBaseLoader(langchain_community) SimpleWebPageReader(llama-index-readers-web)
分块器 RecursiveCharacterTextSplitter SentenceSplitter
向量库 API Milvus.from_documentsdrop_old=True MilvusVectorStore(overwrite=True)
维度获取 Milvus.from_documents 内部处理 显式请求一条样本向量推断 dim
检索入口 vectorstore.as_retriever(search_kwargs={"k": top_k}) index.as_query_engine(similarity_top_k=top_k)
向量库文件 ./milvus.db ./milvus_demo.db

两者在 vLLM 侧的行为完全一致:客户端都只依赖 OpenAI 兼容的 /v1/embeddings/v1/chat/completions 接口,vLLM 服务无需任何 RAG 相关定制。这也说明该部署方式可以平滑替换到你自己已有的 RAG 应用中——只需把原 OpenAI 的 base_url 改为 vLLM 端点,api_keyEMPTY 即可。

常见问题排查

  • 端口冲突:若 8000/8001 已被占用,用 --port 启动第二个 vLLM 实例,并同步修改脚本的 --vllm-embedding-endpoint / --vllm-chat-endpoint(LlamaIndex 版)或对应参数。
  • 模型不支持 Embedding/v1/embeddings 路由在 vllm/entrypoints/pooling/embed/api_router.py 中对不支持 Embeddings API 的模型会抛出 NotImplementedError。请确认 embedding 端点启动的是 embedding 模型而非纯生成模型。
  • 首次运行慢:脚本注释已说明首次运行可能需要较长时间下载模型;另需注意脚本默认 URL 为 vLLM 文档站页面,网络不通时会因 WebBaseLoader/SimpleWebPageReader 抓取失败而抛出异常(LangChain 版会打印 Error loading document from <url> 后重新抛出)。
  • 检索质量不佳:优先调整 -k(top-k)、-c(chunk-size)与 -o(chunk-overlap)三个参数,它们共同决定送入 prompt 的上下文规模与相关性。

小结

vLLM 的 RAG 集成遵循"服务端只做推理、编排交给框架"的清晰分工:两个 vllm serve 实例分别提供向量化与对话能力,LangChain 或 LlamaIndex 负责网页抓取、分块、Milvus 存取与提示词拼装,Milvus(本地 SQLite 文件形态)负责持久化向量索引。仓库内两个示例脚本提供了完整的可运行起点,所有关键行为(端点地址、模型名、分块与检索参数)均可通过命令行覆盖,便于按需扩展为内部知识库问答系统。

登录后查看全文
热门项目推荐
相关项目推荐