Haystack × Ollama 集成指南:OllamaDocumentEmbedder、OllamaTextEmbedder 与 OllamaChatGenerator 实战解析
【免费下载链接】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 官方集成文档(integrations-api/ollama.md)系统性地收录了 Ollama 生态的三个核心组件:OllamaDocumentEmbedder、OllamaTextEmbedder与OllamaChatGenerator。本文以此为骨架,结合仓库内的组件使用文档与 API 参考,深入讲解每个组件的初始化参数、run调用签名、同步/异步生命周期,以及如何将它们接入索引管道与 RAG 查询管道,帮助你完全掌握"本地大模型 + Haystack 编排"的实战路径。
Ollama 是一个专注于本地运行 LLM 的开源项目,默认使用量化 GGUF 格式,因此即使在无 GPU 的普通机器上也能运行主流模型,且无需复杂安装流程。Haystack 通过ollama-haystack集成包,将 Ollama 提供的 embedding 与 chat completion 能力封装为标准的 Haystack 组件,可直接嵌入Pipeline中,与文档转换、清洗、切分、写入、检索等组件无缝衔接。
环境准备:安装与启动 Ollama
在使用任意 Ollama 组件之前,需要完成两项准备工作。
第一步:安装ollama-haystack集成包
pip install ollama-haystack第二步:准备一个正在运行的 Ollama 实例
Ollama 既可以本机安装,也可以通过 Docker 快速启动:
docker run -d -p 11434:11434 --name ollama ollama/ollama:latest随后拉取所需的模型(以 zephyr 为例,本机安装则直接执行ollama pull zephyr):
docker exec ollama ollama pull zephyr如需指定量化版本,可以使用 tag 精确拉取:
# ollama pull model:tag ollama pull zephyr:7b-alpha-q3_K_S需要注意:OllamaChatGenerator所需的对话模型必须已 pull 到运行中的 Ollama 实例中;embedding 组件所需的嵌入模型(默认nomic-embed-text)同理。所有组件默认连接http://localhost:11434,因为大多数环境(Mac、Linux、Docker)的默认端口均为 11434。
文档嵌入:OllamaDocumentEmbedder
OllamaDocumentEmbedder计算一组Document的嵌入向量,并将结果写入每个 Document 的embedding字段。它在索引管道中通常位于DocumentWriter之前(参见 documentwriter.mdx),文档向量是后续 embedding 检索的必要前提:检索阶段会用查询向量与文档向量比较,找出最相似的相关文档。
初始化参数详解
__init__( model: str = "nomic-embed-text", url: str = "http://localhost:11434", generation_kwargs: dict[str, Any] | None = None, timeout: int = 120, keep_alive: float | str | None = None, prefix: str = "", suffix: str = "", progress_bar: bool = True, meta_fields_to_embed: list[str] | None = None, embedding_separator: str = "\n", batch_size: int = 32, dimensions: int | None = None, ) -> None各参数含义如下:
| 参数 | 默认值 | 说明 |
|---|---|---|
model | "nomic-embed-text" | 使用的嵌入模型名称,须在运行的 Ollama 实例中可用 |
url | "http://localhost:11434" | 运行中的 Ollama 实例 URL |
generation_kwargs | None | 传递给 Ollama generation 端点的可选参数,如temperature、top_p等(有效参数见 Ollama Modelfile 文档) |
timeout | 120 | 抛出 Ollama API 超时错误前的等待秒数 |
keep_alive | None | 控制请求后模型在内存中驻留时长,未设置时使用 Ollama 默认值(5 分钟) |
prefix | "" | 添加在每段文本开头的字符串 |
suffix | "" | 添加在每段文本末尾的字符串 |
progress_bar | True | 为True时运行中显示进度条 |
meta_fields_to_embed | None | 需随文档文本一起嵌入的元数据字段列表 |
embedding_separator | "\n" | 拼接元数据字段与文档文本时使用的分隔符 |
batch_size | 32 | 一次处理的文档数量 |
dimensions | None | 嵌入输出期望的向量维度 |
其中keep_alive的取值规则较为灵活,支持四类值:
- 时长字符串,如
"10m"、"24h"; - 秒数,如
3600; - 任意负数表示让模型一直驻留内存,如
-1或"-1m"; '0'表示响应生成后立即卸载模型。
dimensions参数仅对实现了 Matryoshka Representation Learning(MRL)的模型生效,例如nomic-embed-text-v1.5、mxbai-embed-large、qwen3-embedding。设置为None(默认)时返回完整向量;该特性要求ollama-python >= 0.6.2。meta_fields_to_embed与embedding_separator的组合允许把元数据(如标题、来源)拼入文本一起编码,从而提升检索语义相关性。
run 与生命周期方法
run( documents: list[Document], generation_kwargs: dict[str, Any] | None = None ) -> dict[str, list[Document] | dict[str, Any]]- 参数
documents:待计算嵌入的 Document 列表; - 参数
generation_kwargs:可选的按次调用端点参数(覆盖或补充初始化时的配置); - 返回字典包含两个键:
documents(已附加嵌入信息的文档列表)与meta(嵌入过程中收集的元数据)。
组件同时提供run_async异步版本,以及用于创建/销毁底层客户端的生命周期方法:
warm_up():创建同步 Ollama 客户端;warm_up_async():创建异步 Ollama 客户端;close():关闭同步客户端;close_async():关闭异步客户端。
独立使用
from haystack import Document from haystack_integrations.components.embedders.ollama import OllamaDocumentEmbedder doc = Document(content="What do llamas say once you have thanked them? No probllama!") document_embedder = OllamaDocumentEmbedder() result = document_embedder.run([doc]) print(result['documents'][0].embedding) # Calculating embeddings: 100%|██████████| 1/1 [00:02<00:00, 2.82s/it] # [-0.16412407159805298, -3.8359334468841553, ... ]输出中的meta会自动带上模型名,例如使用 nomic-embed-text 时形如{"meta": {"model": "nomic-embed-text"}}。
接入索引管道
将 OllamaDocumentEmbedder 与转换、清洗、切分、写入组件串联,即可构建一条完整的本地索引管道(完整示例见 ollamadocumentembedder.mdx):
from haystack import Pipeline from haystack_integrations.components.embedders.ollama import OllamaDocumentEmbedder from haystack.components.preprocessors import DocumentCleaner, DocumentSplitter from haystack.components.converters import PyPDFToDocument from haystack.components.writers import DocumentWriter from haystack.document_stores.types import DuplicatePolicy from haystack.document_stores.in_memory import InMemoryDocumentStore document_store = InMemoryDocumentStore(embedding_similarity_function="cosine") embedder = OllamaDocumentEmbedder( model="nomic-embed-text", url="http://localhost:11434", ) # 默认模型与默认 URL cleaner = DocumentCleaner() splitter = DocumentSplitter() file_converter = PyPDFToDocument() writer = DocumentWriter(document_store=document_store, policy=DuplicatePolicy.OVERWRITE) indexing_pipeline = Pipeline() indexing_pipeline.add_component("embedder", embedder) indexing_pipeline.add_component("converter", file_converter) indexing_pipeline.add_component("cleaner", cleaner) indexing_pipeline.add_component("splitter", splitter) indexing_pipeline.add_component("writer", writer) indexing_pipeline.connect("converter", "cleaner") indexing_pipeline.connect("cleaner", "splitter") indexing_pipeline.connect("splitter", "embedder") indexing_pipeline.connect("embedder", "writer") indexing_pipeline.run({"converter": {"sources": ["files/test_pdf_data.pdf"]}}) # Calculating embeddings: 100%|██████████| 115/115 # {'embedder': {'meta': {'model': 'nomic-embed-text'}}, 'writer': {'documents_written': 115}}文本嵌入:OllamaTextEmbedder
OllamaTextEmbedder计算单个字符串的嵌入向量,通常放在 embeddingRetriever之前(参见 retrievers.mdx),用于把查询(query)转换为向量,再由检索器据此查找相关文档。如果需要嵌入一批文档,则应使用OllamaDocumentEmbedder。
初始化参数详解
__init__( model: str = "nomic-embed-text", url: str = "http://localhost:11434", generation_kwargs: dict[str, Any] | None = None, timeout: int = 120, keep_alive: float | str | None = None, dimensions: int | None = None, ) -> None参数语义与OllamaDocumentEmbedder完全一致:model默认"nomic-embed-text"、url默认http://localhost:11434、timeout默认 120 秒;generation_kwargs透传给 Ollama 端点;keep_alive支持时长字符串、秒数、负数(常驻内存)与'0'(立即卸载);dimensions仅对支持 MRL 的模型(如nomic-embed-text-v1.5、mxbai-embed-large、qwen3-embedding)生效,None时返回完整向量。
run 与生命周期方法
run( text: str, generation_kwargs: dict[str, Any] | None = None ) -> dict[str, list[float] | dict[str, Any]]- 参数
text:待嵌入的字符串; - 返回字典包含
embedding(计算得到的向量,float 列表)与meta(嵌入过程收集的元数据,同样会自动包含模型名)。
组件同样提供run_async异步版本及warm_up/warm_up_async/close/close_async生命周期方法。
独立使用
from haystack_integrations.components.embedders.ollama import OllamaTextEmbedder embedder = OllamaTextEmbedder() result = embedder.run(text="What do llamas say once you have thanked them? No probllama!") print(result['embedding'])构建完整的本地 RAG 查询管道
将两个 embedding 组件配合InMemoryDocumentStore与InMemoryEmbeddingRetriever,即可实现"本地向量化 + 检索"的闭环(完整示例见 ollamatextembedder.mdx):
from haystack import Document from haystack import Pipeline from haystack.document_stores.in_memory import InMemoryDocumentStore from haystack_integrations.components.embedders.ollama import ( OllamaDocumentEmbedder, OllamaTextEmbedder, ) from haystack.components.retrievers.in_memory import InMemoryEmbeddingRetriever document_store = InMemoryDocumentStore(embedding_similarity_function="cosine") documents = [ Document(content="My name is Wolfgang and I live in Berlin"), Document(content="I saw a black horse running"), Document(content="Germany has many big cities"), ] document_embedder = OllamaDocumentEmbedder() documents_with_embeddings = document_embedder.run(documents)["documents"] document_store.write_documents(documents_with_embeddings) query_pipeline = Pipeline() query_pipeline.add_component("text_embedder", OllamaTextEmbedder()) query_pipeline.add_component( "retriever", InMemoryEmbeddingRetriever(document_store=document_store), ) query_pipeline.connect("text_embedder.embedding", "retriever.query_embedding") query = "Who lives in Berlin?" result = query_pipeline.run({"text_embedder": {"text": query}}) print(result["retriever"]["documents"][0])对话生成:OllamaChatGenerator
OllamaChatGenerator是面向 Ollama 服务的 Haystack Chat Generator,支持流式输出、工具调用、推理(thinking)与结构化输出。它接收ChatMessage对象进行多轮对话,在管道中通常位于ChatPromptBuilder之后(参见 chatpromptbuilder.mdx)。ChatMessage是包含消息内容、角色(user、assistant、system、tool)与可选元数据的数据类,详见 chatmessage.mdx。
初始化参数详解
__init__( model: str = "qwen3:0.6b", url: str = "http://localhost:11434", generation_kwargs: dict[str, Any] | None = None, timeout: int = 120, max_retries: int = 0, keep_alive: float | str | None = None, streaming_callback: Callable[[StreamingChunk], None] | None = None, tools: ToolsType | None = None, response_format: None | Literal["json"] | JsonSchemaValue | None = None, think: bool | Literal["low", "medium", "high"] = False, ) -> None| 参数 | 默认值 | 说明 |
|---|---|---|
model | "qwen3:0.6b" | 使用的模型名,必须已 pull 到运行中的 Ollama 实例 |
url | "http://localhost:11434" | Ollama 服务器基础 URL |
generation_kwargs | None | 透传给 Ollama 生成端点的可选参数,如temperature、top_p |
timeout | 120 | 抛出 Ollama API 超时错误前的秒数 |
max_retries | 0 | 失败请求(HTTP 429、5xx、连接/超时错误)的最大重试次数,采用指数退避;设为 0(默认)禁用重试 |
keep_alive | None | 模型驻留内存时长控制,取值规则与 embedding 组件一致 |
streaming_callback | None | 收到新 token 时被调用的回调函数,接收StreamingChunk参数 |
tools | None | 可供模型调用准备的Tool和/或Toolset对象列表,或单个Toolset;每个工具名须唯一。并非所有模型支持工具 |
response_format | None | 结构化输出格式,见下文 |
think | False | 若为True,模型在产出响应前先"思考";仅思考型模型支持,部分模型(如 gpt-oss)支持"low"、"medium"、"high"不同思考级别。中间"思考"输出可通过返回ChatMessage的reasoning属性查看 |
response_format支持三种取值:
None:不施加任何结构约束,响应原样返回;"json":响应格式化为 JSON 对象;- JSON Schema(
JsonSchemaValue):响应按指定 JSON Schema 格式化为 JSON 对象(需要 Ollama ≥ 0.1.34)。
run、run_async 与序列化
run( messages: list[ChatMessage] | str, generation_kwargs: dict[str, Any] | None = None, tools: ToolsType | None = None, *, streaming_callback: StreamingCallbackT | None = None ) -> dict[str, list[ChatMessage]]messages:输入消息的ChatMessage列表;若传入字符串,会被转换为包含一条 user 角色消息的列表;generation_kwargs:按次调用覆盖,会与实例级generation_kwargs合并;tools:若设置,将覆盖初始化时的tools参数;streaming_callback:在构造函数或此处提供回调都会使组件进入流式模式;- 返回字典包含键
replies:模型响应的ChatMessage列表。
run_async为run的异步版本,签名一致。此外,该组件还实现了to_dict()/from_dict()序列化接口,可配合 Haystack 的 YAML/JSON 管道序列化机制使用。
独立使用
from haystack_integrations.components.generators.ollama.chat import OllamaChatGenerator from haystack.dataclasses import ChatMessage llm = OllamaChatGenerator(model="qwen3:0.6b") result = llm.run(messages=[ChatMessage.from_user("What is the capital of France?")]) print(result)带系统提示词与生成参数控制的完整示例:
from haystack_integrations.components.generators.ollama import OllamaChatGenerator from haystack.dataclasses import ChatMessage generator = OllamaChatGenerator( model="zephyr", url="http://localhost:11434", generation_kwargs={ "num_predict": 100, "temperature": 0.9, }, ) messages = [ ChatMessage.from_system("\nYou are a helpful, respectful and honest assistant"), ChatMessage.from_user("What's Natural Language Processing?"), ] print(generator.run(messages=messages)) # >> { # >> "replies": [ # >> ChatMessage( # >> _role=<ChatRole.ASSISTANT: 'assistant'>, # >> _content=[TextContent(text="Natural Language Processing (NLP) is a subfield of ...")], # >> _meta={"model": "zephyr", ...} # >> ) # >> ] # >> }多模态输入
Ollama 的视觉模型(如llava)支持图像输入,配合 Haystack 的ImageContent数据类即可完成多模态问答:
from haystack.dataclasses import ChatMessage, ImageContent from haystack_integrations.components.generators.ollama import OllamaChatGenerator llm = OllamaChatGenerator(model="llava", url="http://localhost:11434") image = ImageContent.from_file_path("apple.jpg") user_message = ChatMessage.from_user( content_parts=["What does the image show? Max 5 words.", image], ) response = llm.run([user_message])["replies"][0].text print(response) # Red apple on straw.工具调用(Function Calling)
通过tools参数可以启用函数调用,它接受三种灵活的配置形态(详细机制见 tool.mdx 与 toolset.mdx):
- Tool 对象列表:逐个传入独立工具;
- 单个 Toolset:直接传入整个 Toolset;
- Tool 与 Toolset 混合列表:在同一个列表中组合多个 Toolset 与独立工具。
from haystack.tools import Tool, Toolset from haystack_integrations.components.generators.ollama import OllamaChatGenerator # 创建独立工具 weather_tool = Tool( name="weather", description="Get weather info", parameters=..., function=... ) news_tool = Tool( name="news", description="Get latest news", parameters=..., function=... ) # 将相关工具分组为 toolset math_toolset = Toolset([add_tool, subtract_tool, multiply_tool]) # 混合传入 toolset 与独立工具 generator = OllamaChatGenerator( model="llama2", tools=[math_toolset, weather_tool, news_tool], )流式输出(Streaming)
通过streaming_callback参数可以按 token 流式接收输出。可以优先使用 Haystack 内置的print_streaming_chunk(同时打印文本 token 与工具事件),仅在需要特定传输方式(如 SSE/WebSocket)或自定义 UI 时才编写自定义回调,详见 choosing-the-right-generator.mdx。
from haystack.components.generators.utils import print_streaming_chunk component = SomeGeneratorOrChatGenerator(streaming_callback=print_streaming_chunk)需要注意:流式模式仅支持单个响应,若提供方支持多候选,应设置n=1。
流式 + 工具调用组合
流式可以与工具调用同时使用。同时传入tools与streaming_callback后,当模型决定调用工具时,流式 chunk 携带的是工具调用增量而非文本 token,最终重建的ChatMessage会在replies[0]暴露完整的tool_calls列表:
from haystack.dataclasses import ChatMessage from haystack.dataclasses.streaming_chunk import StreamingChunk from haystack.tools import create_tool_from_function from haystack_integrations.components.generators.ollama import OllamaChatGenerator def get_weather(city: str) -> str: """Get current weather for a city.""" return f"Sunny, 22°C in {city}" def callback(chunk: StreamingChunk) -> None: if chunk.tool_calls: print(f"[tool delta] {chunk.tool_calls}") elif chunk.content: print(chunk.content, end="", flush=True) generator = OllamaChatGenerator( model="llama3.1:8b", generation_kwargs={"temperature": 0.0}, tools=[create_tool_from_function(get_weather)], streaming_callback=callback, ) response = generator.run( messages=[ ChatMessage.from_user( "What's the weather in Berlin? Use the get_weather tool.", ), ], ) # 最终重建的消息:tool_calls 已填充,text 为 None assistant_message = response["replies"][0] print(assistant_message.tool_calls) # -> [ToolCall(tool_name='get_weather', arguments={'city': 'Berlin'}, ...)]在管道中使用
将OllamaChatGenerator与ChatPromptBuilder连接,即可构建一个带模板提示的本地对话管道:
from haystack.components.builders import ChatPromptBuilder from haystack_integrations.components.generators.ollama import OllamaChatGenerator from haystack.dataclasses import ChatMessage from haystack import Pipeline prompt_builder = ChatPromptBuilder() generator = OllamaChatGenerator( model="zephyr", url="http://localhost:11434", generation_kwargs={"temperature": 0.9}, ) pipe = Pipeline() pipe.add_component("prompt_builder", prompt_builder) pipe.add_component("llm", generator) pipe.connect("prompt_builder.prompt", "llm.messages") location = "Berlin" messages = [ ChatMessage.from_system( "Always respond in Spanish even if some input data is in other languages." ), ChatMessage.from_user("Tell me about {{location}}"), ] print( pipe.run( data={ "prompt_builder": { "template_variables": {"location": location}, "template": messages, } } ) )组件选型速查
| 组件 | 输入 | 输出 | 典型位置 |
|---|---|---|---|
OllamaDocumentEmbedder | documents: list[Document] | documents(带嵌入)、meta | 索引管道中DocumentWriter之前 |
OllamaTextEmbedder | text: str | embedding(float 列表)、meta | 查询/RAG 管道中 embeddingRetriever之前 |
OllamaChatGenerator | messages(ChatMessage 列表或字符串) | replies(ChatMessage 列表) | 对话管道中ChatPromptBuilder之后 |
三者共用同一套 Ollama 连接约定(默认 URLhttp://localhost:11434、timeout=120、keep_alive四类取值),并统一遵循 Haystack 的warm_up/close生命周期与run_async异步接口,因此可以自然地混合编排:用两个 embedding 组件构建本地向量索引与检索,再用 ChatGenerator 基于检索结果完成生成式问答。
延伸阅读
- 完整 API 参考:integrations-ollama
- 组件使用文档:ollamadocumentembedder.mdx、ollamatextembedder.mdx、ollamachatgenerator.mdx
- 选型对比:choosing-the-right-embedder.mdx、choosing-the-right-generator.mdx
- 快速上手:Ollama 集成入门可参考 get-started.mdx
【免费下载链接】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),仅供参考