Haystack 与 vLLM 集成实战:基于 OpenAI 兼容接口接入文档嵌入、文本嵌入、Chat 生成与 Rerank 排序
【免费下载链接】haystackOpen-source AI orchestration framework for building context-engineered, production-ready LLM applications. Design modular pipelines and agent workflows with explicit control over retrieval, routing, memory, and generation. Built for scalable agents, RAG, multimodal applications, semantic search, and conversational systems.项目地址: https://gitcode.com/GitHub_Trending/ha/haystack
本篇技术指南围绕 Haystack 官方 vLLM 集成(haystack-integrations中的components.embedders.vllm、components.generators.vllm、components.rankers.vllm三个模块)展开,系统讲解如何在本机或远程启动 vLLM 服务,并在 Haystack 管道中通过VLLMDocumentEmbedder、VLLMTextEmbedder、VLLMChatGenerator、VLLMRanker四个组件完成文档向量化、查询向量化、对话生成与重排序。读完本文,你将掌握每个组件的完整初始化参数、run/run_async调用方式、vLLM 私有参数(如truncate_prompt_tokens、top_k、repetition_penalty)的透传方法,以及工具调用(tool calling)与推理模型(reasoning models)的端到端配置方案,可直接落地到 RAG、语义检索与 Agent 工作流中。
一、vLLM 集成的整体架构与设计思路
vLLM 集成遵循一条统一的设计原则:Haystack 组件不直接与 vLLM 内部推理引擎打交道,而是通过 vLLM 暴露的 OpenAI 兼容 HTTP 接口进行通信。这意味着:
- 四个组件都以
api_base_url定位服务地址,默认值为http://localhost:8000/v1,与 vLLM 默认的 OpenAI 兼容服务端口一致; - 认证统一走
api_key(默认从VLLM_API_KEY环境变量读取),仅当 vLLM 服务以--api-key启动时才需要; - 底层 HTTP 客户端基于
httpx,支持通过http_client_kwargs注入自定义httpx.Client/httpx.AsyncClient; - 嵌入类组件(Embedder)与 Chat 生成组件同时提供同步
run与异步run_async两种入口,便于在异步管道(AsyncPipeline)中使用; extra_parameters/generation_kwargs["extra_body"]机制承担"vLLM 私有能力透传"的职责,使组件能够使用标准 OpenAI API 之外的服务端特性。
从 Haystack 核心库看,这些组件产出的数据对象(Document.embedding、ChatMessage、StreamingChunk)均由核心数据类定义,见 document.py、chat_message.py 与 streaming_chunk.py,因此集成组件可以无缝嵌入任何 Haystack 管道。
二、VLLMDocumentEmbedder:批量文档嵌入
VLLMDocumentEmbedder位于haystack_integrations.components.embedders.vllm.document_embedder模块,用于对一批 Document计算向量,并将结果写入每个 Document 的embedding字段(即 document.py 中定义的Document.embedding)。
2.1 启动 vLLM 服务
使用前必须先启动一个加载了嵌入模型的 vLLM 服务:
vllm serve google/embeddinggemma-300m该命令会监听8000端口并提供 OpenAI 兼容的 Embeddings API。服务端更多启动选项(如--port、--api-key、量化参数等)可查阅 vLLM 官方 CLI 文档。
2.2 基本用法
from haystack import Document from haystack_integrations.components.embedders.vllm import VLLMDocumentEmbedder doc = Document(content="I love pizza!") document_embedder = VLLMDocumentEmbedder(model="google/embeddinggemma-300m") result = document_embedder.run([doc]) print(result["documents"][0].embedding)run接收list[Document],返回字典,包含两个键:
documents:输入 Document 列表,其embedding字段已被填充;meta:模型使用情况信息(如 token 用量等)。
run_async(documents)提供完全相同的语义,只是以异步方式执行。
2.3 透传 vLLM 私有参数
对于标准 OpenAI Embeddings API 之外的 vLLM 特有参数,通过extra_parameters字典传入,组件会将其作为extra_body转发给服务端:
document_embedder = VLLMDocumentEmbedder( model="google/embeddinggemma-300m", extra_parameters={"truncate_prompt_tokens": 256, "truncation_side": "right"}, )典型 vLLM 私有参数包括truncate_prompt_tokens(超长输入从哪一侧截断到多少 token)与truncation_side(截断方向)。
2.4 完整初始化参数
__init__签名(全部为关键字参数)如下:
__init__( *, model: str, api_key: Secret | None = Secret.from_env_var("VLLM_API_KEY", strict=False), api_base_url: str = "http://localhost:8000/v1", prefix: str = "", suffix: str = "", dimensions: int | None = None, batch_size: int = 32, progress_bar: bool = True, meta_fields_to_embed: list[str] | None = None, embedding_separator: str = "\n", timeout: float | None = None, max_retries: int | None = None, http_client_kwargs: dict[str, Any] | None = None, raise_on_failure: bool = False, extra_parameters: dict[str, Any] | None = None ) -> None各参数语义与实操要点:
| 参数 | 类型/默认值 | 说明 |
|---|---|---|
model | str(必填) | vLLM 服务所加载的模型名,须与vllm serve指定的模型一致 |
api_key | Secret \| None,默认读VLLM_API_KEY环境变量(strict=False,未设置不报错) | 仅当服务端以--api-key启动时需要 |
api_base_url | str,默认http://localhost:8000/v1 | vLLM 服务的基础 URL,远程部署时改为对应地址 |
prefix/suffix | str,默认空串 | 分别添加到每段待嵌入文本开头/结尾的字符串,常用于按模型要求的提示模板包裹文本 |
dimensions | int \| None | 输出向量的维度数;仅支持经过 Matryoshka Representation Learning(套娃表示学习)训练的模型,可据此裁剪输出维度以节省存储 |
batch_size | int,默认32 | 一次请求编码的 Document 数量 |
progress_bar | bool,默认True | 是否显示批处理进度条 |
meta_fields_to_embed | list[str] \| None | 需要拼接到文档正文上一并嵌入的 meta 字段名列表(如标题、作者等) |
embedding_separator | str,默认"\n" | 拼接 meta 字段与正文时使用的分隔符 |
timeout | float \| None | 单次客户端调用的超时秒数;不设置则采用 OpenAI 客户端默认值 |
max_retries | int \| None | 失败请求的最大重试次数;不设置则采用 OpenAI 客户端默认值 |
http_client_kwargs | dict[str, Any] \| None | 构造自定义httpx.Client/httpx.AsyncClient的关键字参数(如代理、TLS 配置) |
raise_on_failure | bool,默认False | 为True时嵌入请求失败直接抛异常;为False时记录错误日志并继续处理剩余文档 |
extra_parameters | dict[str, Any] \| None | 以extra_body形式透传给 vLLM 嵌入端点的私有参数 |
生命周期方法:warm_up()创建底层 OpenAI 客户端,应在管道warm_up()阶段被调用(Haystack 管道会自动触发各组件warm_up)。
三、VLLMTextEmbedder:单条文本嵌入
VLLMTextEmbedder位于haystack_integrations.components.embedders.vllm.text_embedder模块,面向RAG 查询侧:将单条查询字符串编码为向量,供相似度检索使用。它与VLLMDocumentEmbedder共用同一套服务端前置条件(同样执行vllm serve google/embeddinggemma-300m启动服务)。
3.1 基本用法
from haystack_integrations.components.embedders.vllm import VLLMTextEmbedder text_embedder = VLLMTextEmbedder(model="google/embeddinggemma-300m") print(text_embedder.run("I love pizza!"))run(text: str)返回字典:
embedding:输入文本的向量(list[float]);meta:模型使用情况信息。
run_async(text: str)语义相同,异步执行。
3.2 透传 vLLM 私有参数
与 Document 版一致,通过extra_parameters透传:
text_embedder = VLLMTextEmbedder( model="google/embeddinggemma-300m", extra_parameters={"truncate_prompt_tokens": 256, "truncation_side": "right"}, )3.3 完整初始化参数
__init__( *, model: str, api_key: Secret | None = Secret.from_env_var("VLLM_API_KEY", strict=False), api_base_url: str = "http://localhost:8000/v1", prefix: str = "", suffix: str = "", dimensions: int | None = None, timeout: float | None = None, max_retries: int | None = None, http_client_kwargs: dict[str, Any] | None = None, extra_parameters: dict[str, Any] | None = None ) -> None各参数含义与VLLMDocumentEmbedder对应项一致,差异在于:
- 没有
batch_size、progress_bar、meta_fields_to_embed、embedding_separator、raise_on_failure等批处理相关参数(因为只处理单条文本); model的示例值可以是"intfloat/e5-mistral-7b-instruct"这类需要按提示模板加prefix/suffix的指令型嵌入模型;extra_parameters支持范围更广,文档给出的示例还包括additional_data、use_activation等 vLLM 嵌入端点私有参数。
四、VLLMChatGenerator:对话生成、工具调用与推理模型
VLLMChatGenerator位于haystack_integrations.components.generators.vllm.chat.chat_generator模块,用于生成聊天补全(chat completions),是四个组件中能力最丰富的:支持流式输出、工具调用(tool calling)、推理模型(reasoning models)、结构化输出与序列化。
4.1 启动 vLLM 服务
基础启动命令:
vllm serve Qwen/Qwen3-4B-Instruct-2507针对三类特殊场景,启动命令需要附加参数:
推理模型(如 Qwen3 系列)需要指定对应的 reasoning parser:
vllm serve Qwen/Qwen3-0.6B --reasoning-parser qwen3工具调用场景必须同时开启--enable-auto-tool-choice并指定--tool-call-parser:
vllm serve Qwen/Qwen3-0.6B --enable-auto-tool-choice --tool-call-parser hermes注意:可用的 tool call parser 取决于模型本身,完整的 parser 列表以 vLLM 官方工具调用文档为准。
4.2 基本用法
from haystack.dataclasses import ChatMessage from haystack_integrations.components.generators.vllm import VLLMChatGenerator generator = VLLMChatGenerator( model="Qwen/Qwen3-0.6B", generation_kwargs={"max_tokens": 512, "temperature": 0.7}, ) messages = [ChatMessage.from_user("What's Natural Language Processing?")] response = generator.run(messages=messages) print(response["replies"][0].text)关键点:
- 消息对象使用 Haystack 核心数据类
ChatMessage,由 chat_message.py 定义,可通过from_user、from_system、from_assistant、from_tool等类方法构造,内部支持文本、工具调用(ToolCall)、工具结果(ToolCallResult)、图片/文件与推理内容等多种内容单元; run的messages参数既可以是list[ChatMessage],也可以是普通字符串——字符串会被自动转换为一个 role 为 user 的ChatMessage;- 返回值只含一个键
replies:生成的回复ChatMessage列表,可通过.text取正文。
4.3 透传 vLLM 私有参数
与嵌入组件不同,Chat 生成器的 vLLM 私有参数放在generation_kwargs的extra_body子字典中:
from haystack_integrations.components.generators.vllm import VLLMChatGenerator generator = VLLMChatGenerator( model="Qwen/Qwen3-0.6B", generation_kwargs={ "max_tokens": 512, "extra_body": { "top_k": 50, "min_tokens": 10, "repetition_penalty": 1.1, }, }, )generation_kwargs中支持的标准 OpenAI 参数包括:
max_tokens:生成的最大 token 数;temperature:采样温度;top_p:核采样(nucleus sampling)参数;n:每个提示生成的补全数量;stop:一个或多个停止序列,模型遇到后停止生成;response_format:JSON Schema 或 Pydantic 模型,用于强制约束响应结构(结构化输出)。
extra_body则承载 vLLM 私有参数,如top_k、min_tokens、repetition_penalty。
4.4 工具调用(Tool Calling)
服务端以--enable-auto-tool-choice --tool-call-parser hermes启动后,即可为模型注册 Haystack 工具。工具通过@tool装饰器(定义于 from_function.py)从普通函数生成:
from haystack.dataclasses import ChatMessage from haystack.tools import tool from haystack_integrations.components.generators.vllm import VLLMChatGenerator @tool def weather(city: str) -> str: """Get the weather in a given city.""" return f"The weather in {city} is sunny" generator = VLLMChatGenerator(model="Qwen/Qwen3-0.6B", tools=[weather]) messages = [ChatMessage.from_user("What is the weather in Paris?")] response = generator.run(messages=messages) print(response["replies"][0].tool_calls)要点:
tools参数接受ToolsType:可以是 Tool/Toolset 对象列表,也可以是单个 Toolset;每个工具名称必须唯一;- 模型返回的调用意向可通过
ChatMessage.tool_calls属性读取(见 chat_message.py 中的ToolCall类,包含tool_name、arguments、id等字段),拿到后由应用自行执行工具并回填结果; - 并非所有模型都支持工具调用,请以具体模型的 vLLM 支持情况为准。
4.5 推理模型(Reasoning Models)
服务端以--reasoning-parser qwen3启动后,回复中的推理过程与最终答案会分开返回:
from haystack.dataclasses import ChatMessage from haystack_integrations.components.generators.vllm import VLLMChatGenerator generator = VLLMChatGenerator(model="Qwen/Qwen3-0.6B") messages = [ChatMessage.from_user("Solve step by step: what is 15 * 37?")] response = generator.run(messages=messages) reply = response["replies"][0] if reply.reasoning: print("Reasoning:", reply.reasoning.reasoning_text) print("Answer:", reply.text)ChatMessage的reasoning属性返回包含reasoning_text字段的推理内容对象,该结构同样由 chat_message.py 定义。应用可根据需要选择展示、隐藏或继续引用推理文本。
4.6 完整初始化参数与序列化
__init__( *, model: str, api_key: Secret | None = Secret.from_env_var("VLLM_API_KEY", strict=False), streaming_callback: StreamingCallbackT | None = None, api_base_url: str = "http://localhost:8000/v1", generation_kwargs: dict[str, Any] | None = None, timeout: float | None = None, max_retries: int | None = None, tools: ToolsType | None = None, http_client_kwargs: dict[str, Any] | None = None ) -> None| 参数 | 说明 |
|---|---|
model | vLLM 服务所加载的模型名(如"Qwen/Qwen3-0.6B") |
api_key | 默认读VLLM_API_KEY环境变量,仅服务端启用--api-key时需要 |
streaming_callback | 流式回调函数,每收到一个新 token 即被调用;回调参数为StreamingChunk(定义见 streaming_chunk.py) |
api_base_url | vLLM 服务基础 URL,默认http://localhost:8000/v1 |
generation_kwargs | 生成参数,直接发送给 vLLM OpenAI 兼容端点(详见 4.3 节) |
timeout/max_retries | 客户端超时与重试,不设置则用 OpenAI 客户端默认值 |
tools | 可调用工具列表/Toolset,模型据此准备调用 |
http_client_kwargs | 自定义httpx客户端的关键字参数 |
生命周期与序列化:
warm_up():创建 OpenAI 客户端并预热工具;to_dict():将组件序列化为字典;from_dict(data):从字典反序列化恢复组件实例——这两个方法保证组件可以在 Haystack 的Pipeline/Pipeline.from_dict中保存与加载。
4.7 run 与 run_async 的运行时覆盖能力
run与run_async签名一致:
run( messages: list[ChatMessage] | str, streaming_callback: StreamingCallbackT | None = None, generation_kwargs: dict[str, Any] | None = None, *, tools: ToolsType | None = None ) -> dict[str, list[ChatMessage]]generation_kwargs在运行时传入时会覆盖初始化时设置的同名参数,便于在同一组件实例上按请求动态调整采样配置;tools在运行时传入时会覆盖初始化时的工具集合;run_async的streaming_callback必须为协程(coroutine);- 返回字典仅含
replies键:生成回复的ChatMessage列表。
五、VLLMRanker:基于 /rerank 端点的文档重排序
VLLMRanker位于haystack_integrations.components.rankers.vllm.ranker模块,使用 vLLM 暴露的/rerank端点,按查询与文档的相似度对文档排序,适合作为 RAG 管道检索后的精排环节。
5.1 启动 vLLM 服务
使用前需启动加载了 reranker 模型的服务:
vllm serve BAAI/bge-reranker-base注意:这里使用的是 vLLM 的 rerank(scoring)能力,因此必须加载支持 rerank 的模型(如 BGE Reranker 系列),支持的模型列表以 vLLM 官方文档为准。
5.2 基本用法
from haystack import Document from haystack_integrations.components.rankers.vllm import VLLMRanker ranker = VLLMRanker(model="BAAI/bge-reranker-base") docs = [ Document(content="The capital of Brazil is Brasilia."), Document(content="The capital of France is Paris."), ] result = ranker.run(query="What is the capital of France?", documents=docs) print(result["documents"][0].content)run(query, documents, top_k=None, score_threshold=None)返回字典:
documents:按相关性从高到低排序的 Document 列表;meta:模型与用量信息。
run_async语义相同。两者在top_k不合法(非正数)时都会抛出ValueError。
5.3 透传 vLLM 私有参数
与嵌入组件不同,extra_parameters在这里会被合并进发送到/rerank端点的请求体:
ranker = VLLMRanker( model="BAAI/bge-reranker-base", extra_parameters={"truncate_prompt_tokens": 256}, )5.4 完整初始化参数
__init__( *, model: str, api_key: Secret | None = Secret.from_env_var("VLLM_API_KEY", strict=False), api_base_url: str = "http://localhost:8000/v1", top_k: int | None = None, score_threshold: float | None = None, meta_fields_to_embed: list[str] | None = None, meta_data_separator: str = "\n", http_client_kwargs: dict[str, Any] | None = None, extra_parameters: dict[str, Any] | None = None ) -> None| 参数 | 类型/默认值 | 说明 |
|---|---|---|
model | str(必填) | vLLM 服务加载的 reranker 模型名 |
api_key | Secret \| None | 默认读VLLM_API_KEY,服务端启用--api-key时需要 |
api_base_url | str,默认http://localhost:8000/v1 | vLLM 服务基础 URL |
top_k | int \| None | 最多返回的 Document 数;为None时返回全部文档 |
score_threshold | float \| None | 相关性得分低于该值的文档被丢弃;在top_k之后应用,因此最终返回可能少于top_k条 |
meta_fields_to_embed | list[str] \| None | 重排前需要拼接到文档正文上的 meta 字段列表 |
meta_data_separator | str,默认"\n" | 拼接 meta 字段与正文的分隔符 |
http_client_kwargs | dict[str, Any] \| None | 自定义httpx客户端参数 |
extra_parameters | dict[str, Any] \| None | 合并进/rerank请求体的私有参数(如truncate_prompt_tokens) |
- 生命周期方法:
warm_up()创建 httpx 客户端(Reranker 直接走 HTTP,不使用 OpenAI 客户端); - 初始化时若
top_k不为正数会抛出ValueError; run时传入的top_k/score_threshold会覆盖初始化值。
六、在 Haystack 管道中的组合实践
四个组件可以组合成典型的 RAG 管道。例如一个"文档索引 + 检索 + 精排 + 生成"的完整链路可以这样组织:
from haystack import Document, Pipeline from haystack.components.retrievers.in_memory import InMemoryEmbeddingRetriever from haystack.document_stores.in_memory import InMemoryDocumentStore from haystack_integrations.components.embedders.vllm import VLLMDocumentEmbedder, VLLMTextEmbedder from haystack_integrations.components.rankers.vllm import VLLMRanker from haystack_integrations.components.generators.vllm import VLLMChatGenerator # 1) 索引:文档嵌入 doc_store = InMemoryDocumentStore() doc_embedder = VLLMDocumentEmbedder(model="google/embeddinggemma-300m") # 2) 查询:文本嵌入 + 检索 + 重排 query_embedder = VLLMTextEmbedder(model="google/embeddinggemma-300m") retriever = InMemoryEmbeddingRetriever(document_store=doc_store) ranker = VLLMRanker(model="BAAI/bge-reranker-base") # 3) 生成:基于检索结果的对话 generator = VLLMChatGenerator( model="Qwen/Qwen3-0.6B", generation_kwargs={"max_tokens": 512}, )组件设计上遵循 Haystack 标准组件协议(@component装饰器、run/warm_up接口),因此可以像使用任何内置组件一样通过Pipeline.add_component连接,并通过Pipeline.from_dict/component.to_dict完成整条管道的序列化与恢复。需要高吞吐时,可将run_async变体接入异步管道(AsyncPipeline)并行处理。
几个落地建议:
- 模型与服务端配置一致性:四个组件的
model必须与vllm serve加载的模型一致,否则请求会因模型不匹配而失败; - 认证开关:仅在服务端用
--api-key启动时才需要显式设置api_key;本地开发可直接依赖VLLM_API_KEY环境变量或默认无认证; - 长文本处理:嵌入与重排场景通过
truncate_prompt_tokens控制输入截断;Chat 场景通过max_tokens与stop控制输出; - 远程部署:将
api_base_url改为远程 vLLM 服务的地址,并通过http_client_kwargs注入代理、证书等传输层配置; - 失败策略:批量嵌入时默认
raise_on_failure=False会跳过失败文档并记录日志,适合大语料灌库;对结果敏感的场景可设为True及时暴露问题。
七、小结
vLLM 集成以 OpenAI 兼容协议为桥梁,为 Haystack 提供了完整的自托管 LLM 能力矩阵:
- 嵌入侧:
VLLMDocumentEmbedder(文档批量向量化,支持batch_size、meta_fields_to_embed、Matryoshkadimensions裁剪)与VLLMTextEmbedder(查询向量化); - 生成侧:
VLLMChatGenerator,覆盖流式回调、工具调用、推理模型、结构化输出与运行时参数覆盖,并支持to_dict/from_dict序列化; - 排序侧:
VLLMRanker,通过/rerank端点实现top_k+score_threshold双重过滤的精排。
四个组件均通过extra_parameters(或generation_kwargs["extra_body"])透传 vLLM 私有参数,且同步run与异步run_async双通道齐备,可直接嵌入 Haystack 的同步/异步管道体系,构建完全自托管的 RAG 与 Agent 应用。完整 API 定义见 vllm.md,配套的数据结构与工具定义可在 chat_message.py、streaming_chunk.py 与 from_function.py 中进一步查阅。
【免费下载链接】haystackOpen-source AI orchestration framework for building context-engineered, production-ready LLM applications. Design modular pipelines and agent workflows with explicit control over retrieval, routing, memory, and generation. Built for scalable agents, RAG, multimodal applications, semantic search, and conversational systems.项目地址: https://gitcode.com/GitHub_Trending/ha/haystack
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考