Haystack 集成 Mistral 完全指南:OCR 文档转换、文本嵌入与对话生成
【免费下载链接】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 仓库中的 Mistral 集成参考文档(docs-website/reference_versioned_docs/version-2.20/integrations-api/mistral.md),系统讲解四个核心组件:MistralOCRDocumentConverter(OCR 文档转换)、MistralDocumentEmbedder(文档嵌入)、MistralTextEmbedder(文本嵌入)与MistralChatGenerator(对话生成)。读完本文,你将掌握如何在 Haystack 管道中集成 Mistral 的 OCR、Embedding 与 Chat Completion API,完成从 PDF/图片解析、向量化到对话式 RAG 的完整链路。
概览:Mistral 集成提供了什么
Haystack 的 Mistral 集成(haystack-integrations-mistral)由四个组件构成,覆盖了 LLM 应用中最常见的三个环节:
| 组件 | 所属模块 | 职责 |
|---|---|---|
MistralOCRDocumentConverter | components.converters.mistral | 调用 Mistral OCR API,从 PDF、图片、URL、ByteStream 等来源提取文本,并支持结构化标注 |
MistralDocumentEmbedder | components.embedders.mistral | 基于 Mistral 嵌入模型,为Document列表计算向量并写入embedding字段 |
MistralTextEmbedder | components.embedders.mistral | 基于 Mistral 嵌入模型,为单个文本字符串计算向量 |
MistralChatGenerator | components.generators.mistral.chat | 基于 Mistral 对话模型,使用ChatMessage格式进行文本生成,支持流式、工具调用与推理内容 |
其中嵌入器和生成器分别继承自 Haystack 核心库中的OpenAIDocumentEmbedder(见 haystack/components/embedders/openai_document_embedder.py)、OpenAITextEmbedder(见 haystack/components/embedders/openai_text_embedder.py)与OpenAIChatGenerator(见 haystack/components/generators/chat/openai.py),这保证了与 Haystack 官方 OpenAI 组件一致的使用体验、序列化能力和错误处理逻辑。
所有组件默认从MISTRAL_API_KEY环境变量读取密钥,底层统一使用haystack.utils.Secret管理凭据(见 haystack/utils/auth.py),无需在代码中硬编码。
环境准备与密钥管理
安装集成包后,先在环境中导出 Mistral API 密钥:
export MISTRAL_API_KEY=your-mistral-api-key组件默认通过Secret.from_env_var("MISTRAL_API_KEY")读取密钥,因此无需在构造函数中显式传入。如需在代码中显式指定,可这样写:
from haystack.utils import Secret converter = MistralOCRDocumentConverter(api_key=Secret.from_env_var("MISTRAL_API_KEY"))适用前提:以上组件均依赖 Mistral 云端 API,需要有效的 Mistral 账号与 API 密钥;
MistralOCRDocumentConverter的标注功能还需要额外的 Vision LLM 服务。
MistralOCRDocumentConverter:把文档交给 Mistral OCR
MistralOCRDocumentConverter是 Haystack 中调用 Mistral OCR API 的官方组件。它接收多种文档来源,通过 Mistral OCR 服务返回识别文本,并把每个来源包装成一个 HaystackDocument。
支持的输入来源
run()的sources参数接受混合类型列表,每种类型对应一种文档来源:
| 类型 | 含义 |
|---|---|
str | 本地文件路径 |
Path | pathlib.Path对象 |
ByteStream | Haystack 内存中的字节流数据(见 haystack/dataclasses/byte_stream.py) |
DocumentURLChunk | 文档 URL(签名或公开 URL,指向 PDF 等) |
ImageURLChunk | 图片 URL(签名或公开 URL) |
FileChunk | 已上传到 Mistral 的文件 ID |
本地文件(str、Path、ByteStream三种来源)会被自动上传到 Mistral 的存储;上传文件在默认情况下处理完毕后会被自动删除(见下文cleanup_uploaded_files参数)。
基本使用示例
from haystack.utils import Secret from haystack_integrations.mistral import MistralOCRDocumentConverter from mistralai.models import DocumentURLChunk, ImageURLChunk, FileChunk converter = MistralOCRDocumentConverter( api_key=Secret.from_env_var("MISTRAL_API_KEY"), model="mistral-ocr-2505" ) # 一次处理多个来源 sources = [ DocumentURLChunk(document_url="https://example.com/document.pdf"), ImageURLChunk(image_url="https://example.com/receipt.jpg"), FileChunk(file_id="file-abc123"), ] result = converter.run(sources=sources) documents = result["documents"] # List of 3 Documents raw_responses = result["raw_mistral_response"] # List of 3 raw responsesrun()返回字典包含两个键:
documents:每个来源一个Document。其content为 Markdown 格式的全部页面文本,页面之间以换页符\f连接;raw_mistral_response:Mistral API 的原始响应列表(每个来源一条),包含逐页详情、图片信息、标注结果和 token 用量。
构造函数参数详解
MistralOCRDocumentConverter的构造函数签名如下:
__init__( api_key: Secret = Secret.from_env_var("MISTRAL_API_KEY"), model: str = "mistral-ocr-2505", include_image_base64: bool = False, pages: list[int] | None = None, image_limit: int | None = None, image_min_size: int | None = None, cleanup_uploaded_files: bool = True, ) -> None各参数含义:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
api_key | Secret | MISTRAL_API_KEY环境变量 | Mistral API 密钥 |
model | str | "mistral-ocr-2505" | OCR 模型,必须是SUPPORTED_MODELS之一 |
include_image_base64 | bool | False | 为True时在响应中包含 base64 编码的图片,会显著增大响应体积并拖慢处理 |
pages | list[int] \| None | None | 要处理的页号列表(0 起始);None表示处理全部页面 |
image_limit | int \| None | None | 从文档中最多提取的图片数量 |
image_min_size | int \| None | None | 提取图片的最小宽高(像素) |
cleanup_uploaded_files | bool | True | 是否在处理后自动删除上传到 Mistral 的文件。仅影响本地来源(str、Path、ByteStream)上传的文件;FileChunk方式提供的文件不会被删除 |
SUPPORTED_MODELS列表为:
SUPPORTED_MODELS: list[str] = [ "mistral-ocr-2512", "mistral-ocr-latest", "mistral-ocr-2503", "mistral-ocr-2505", ]如需获取 Mistral 完整模型列表,可向https://api.mistral.ai/v1/models发送 GET 请求。
结构化标注(Structured Annotations)
当提供bbox_annotation_schema(按图像区域的边界框标注)或document_annotation_schema(整篇文档标注)时,OCR 模型会先抽取文本和结构,随后调用一个 Vision LLM 根据你定义的 Pydantic schema 生成结构化标注。
from pydantic import BaseModel, Field from haystack_integrations.mistral import MistralOCRDocumentConverter # 图像区域的结构化标注 schema class ImageAnnotation(BaseModel): image_type: str = Field(..., description="The type of image content") short_description: str = Field(..., description="Short natural-language description") summary: str = Field(..., description="Detailed summary of the image content") # 整篇文档的结构化标注 schema class DocumentAnnotation(BaseModel): language: str = Field(..., description="Primary language of the document") chapter_titles: List[str] = Field(..., description="Detected chapter or section titles") urls: List[str] = Field(..., description="URLs found in the text") converter = MistralOCRDocumentConverter(model="mistral-ocr-2505") sources = [DocumentURLChunk(document_url="https://example.com/report.pdf")] result = converter.run( sources=sources, bbox_annotation_schema=ImageAnnotation, document_annotation_schema=DocumentAnnotation, ) documents = result["documents"] raw_responses = result["raw_mistral_response"]标注行为的两个关键细节:
- 使用
bbox_annotation_schema时,文档content中的图片标签(Markdown 图像标签)会被替换为你定义的中文/自然语言描述; document_annotation_schema最多处理 8 页,超出该限制的文档不会被做文档级标注。
元数据与分页设计
run()的meta参数可以给生成的Document附加元数据:传单个字典则应用于所有文档,传列表则按顺序与sources一一对应(列表长度必须与来源数量一致)。
每个Document的meta会自动聚合为如下结构:
{"source_page_count": int, "source_total_images": int, "source_*": any}其中source_*前缀字段来自文档级标注——例如提供了document_annotation_schema时,language、chapter_titles、urls字段会以source_language、source_chapter_titles、source_urls的形式进入元数据。
所有页面文本以换页符\f连接,是刻意为之的兼容性设计:Haystack 的DocumentSplitter支持按page切分,即按换页符\f分割(见 haystack/components/preprocessors/document_splitter.py)。因此 OCR 转换结果可以直接接入DocumentSplitter(split_by="page"),实现准确的逐页切分、重叠(split_overlap)与阈值控制,避免跨页内容粘连。这也是典型的「PDF 转文档 → 分页切分 → 嵌入 → 检索」索引管道的第一个环节。
生命周期方法
warm_up():初始化 Mistral 客户端,在管道运行时由 Haystack 自动调用;close():关闭 Mistral 客户端,释放资源。
这两个方法配合 Haystack 的组件资源生命周期管理,确保长生命周期服务中客户端被正确复用与释放。
MistralDocumentEmbedder 与 MistralTextEmbedder:文本向量化
两个嵌入器组件分别负责「文档列表」与「单个文本」的向量化,计算得到的向量写入Document.embedding字段或随返回字典输出。
MistralDocumentEmbedder
from haystack import Document from haystack_integrations.components.embedders.mistral import MistralDocumentEmbedder doc = Document(content="I love pizza!") document_embedder = MistralDocumentEmbedder() result = document_embedder.run([doc]) print(result['documents'][0].embedding) # [0.017020374536514282, -0.023255806416273117, ...]MistralTextEmbedder
from haystack_integrations.components.embedders.mistral.text_embedder import MistralTextEmbedder text_to_embed = "I love pizza!" text_embedder = MistralTextEmbedder() print(text_embedder.run(text_to_embed)) # output: # {'embedding': [0.017020374536514282, -0.023255806416273117, ...], # 'meta': {'model': 'mistral-embed', # 'usage': {'prompt_tokens': 4, 'total_tokens': 4}}}两个组件共同支持的SUPPORTED_MODELS:
SUPPORTED_MODELS: list[str] = [ "mistral-embed-2312", "mistral-embed", "codestral-embed", "codestral-embed-2505", ]构造函数参数详解
MistralDocumentEmbedder的构造函数:
__init__( api_key: Secret = Secret.from_env_var("MISTRAL_API_KEY"), model: str = "mistral-embed", api_base_url: str | None = "https://api.mistral.ai/v1", prefix: str = "", suffix: str = "", 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 ) -> NoneMistralTextEmbedder的构造函数为上述参数的精简版(去掉了batch_size、progress_bar、meta_fields_to_embed、embedding_separator,其余相同)。
| 参数 | 默认值 | 说明 |
|---|---|---|
api_key | MISTRAL_API_KEY环境变量 | Mistral API 密钥 |
model | "mistral-embed" | 使用的嵌入模型名称 |
api_base_url | "https://api.mistral.ai/v1" | Mistral API 基础地址,可覆盖以对接代理或自建网关 |
prefix/suffix | "" | 拼接到每段文本开头/结尾的字符串,可用于加入指令式提示 |
batch_size | 32 | 每次批量编码的Document数量(仅文档嵌入器) |
progress_bar | True | 是否显示进度条;生产环境建议关闭以保持日志干净(仅文档嵌入器) |
meta_fields_to_embed | None | 需要与文档正文一同编码的元数据字段列表(仅文档嵌入器) |
embedding_separator | "\n" | 拼接元数据字段与正文的分隔符(仅文档嵌入器) |
timeout | 环境变量或 30 秒 | Mistral 客户端调用超时;未设置时回退到OPENAI_TIMEOUT环境变量,再回退到 30 秒 |
max_retries | 环境变量或 5 次 | 内部错误后重试最大次数;未设置时回退到OPENAI_MAX_RETRIES环境变量,再回退到 5 次 |
http_client_kwargs | None | 自定义httpx.Client/httpx.AsyncClient的关键字参数,用于配置代理、证书等 |
两个组件均提供to_dict()/from_dict()序列化方法,可无缝用于 Haystack 管道的 YAML/JSON 序列化与反序列化。
基类实现要点
从源码结构看,这两个组件直接继承 Haystack 核心库的OpenAIDocumentEmbedder/OpenAITextEmbedder基类,因而继承了批量编码、进度条、元数据拼接、超时重试等完整行为(见 haystack/components/embedders/openai_document_embedder.py)。在典型 RAG 管道中,两者配合使用:MistralDocumentEmbedder在索引阶段对文档库编码,MistralTextEmbedder在查询阶段对用户问题编码,确保二者处于同一向量空间。
MistralChatGenerator:对话生成与推理内容
MistralChatGenerator继承自OpenAIChatGenerator,与 Mistral Chat Completion 端点兼容,支持流式响应、工具调用、结构化输出与推理(reasoning)内容提取。它使用 Haystack 的ChatMessage数据结构组织输入输出。
基本用法
from haystack_integrations.components.generators.mistral import MistralChatGenerator from haystack.dataclasses import ChatMessage messages = [ChatMessage.from_user("What's Natural Language Processing?")] client = MistralChatGenerator() response = client.run(messages) print(response) >>{'replies': [ChatMessage(_role=<ChatRole.ASSISTANT: 'assistant'>, _content=[TextContent(text= >> "Natural Language Processing (NLP) is a branch of artificial intelligence >> that focuses on enabling computers to understand, interpret, and generate human language in a way that is >> meaningful and useful.")], _name=None, >> _meta={'model': 'mistral-small-latest', 'index': 0, 'finish_reason': 'stop', >> 'usage': {'prompt_tokens': 15, 'completion_tokens': 36, 'total_tokens': 51}})]}run()返回字典的replies键包含生成的ChatMessage列表,每条消息的_meta携带模型名、结束原因与 token 用量。
推理(Reasoning)内容
对于支持可调推理的模型(如mistral-small配合reasoning_effort参数,以及 magistral 系列模型),生成的内容会被解析并存储到ChatMessage的推理字段中:
from haystack_integrations.components.generators.mistral import MistralChatGenerator from haystack.dataclasses import ChatMessage messages = [ChatMessage.from_user("Solve: if x + 3 = 7, what is x?")] client = MistralChatGenerator( model="mistral-small-latest", generation_kwargs={"reasoning_effort": "high"}, ) response = client.run(messages) print(response["replies"][0].reasoning) # 访问推理内容 print(response["replies"][0].text) # 访问最终答案Haystack 的ChatMessage数据类原生支持ReasoningContent(见 haystack/dataclasses/chat_message.py),通过reasoning属性可取得第一条推理内容,reasonings属性可取得全部推理内容(见 haystack/dataclasses/chat_message.py)。这让「先推理、后作答」类模型的中间思考过程不再被丢弃。
构造函数参数详解
__init__( api_key: Secret = Secret.from_env_var("MISTRAL_API_KEY"), model: str = "mistral-small-latest", streaming_callback: StreamingCallbackT | None = None, api_base_url: str | None = "https://api.mistral.ai/v1", generation_kwargs: dict[str, Any] | None = None, tools: ToolsType | None = None, *, timeout: float | None = None, max_retries: int | None = None, http_client_kwargs: dict[str, Any] | None = None ) -> None| 参数 | 默认值 | 说明 |
|---|---|---|
api_key | MISTRAL_API_KEY环境变量 | Mistral API 密钥 |
model | "mistral-small-latest" | 使用的对话模型名称 |
streaming_callback | None | 流式回调函数,每个新 token 到达时被调用,接收StreamingChunk参数 |
api_base_url | "https://api.mistral.ai/v1" | Mistral API 基础地址 |
generation_kwargs | None | 透传给 Mistral 端点的生成参数(见下文) |
tools | None | Tool/Toolset对象列表,或单个Toolset,供模型准备调用;每个工具名称必须唯一 |
timeout | 环境变量或 30 秒 | API 调用超时,回退链同嵌入器 |
max_retries | 环境变量或 5 次 | 内部错误重试次数,回退链同嵌入器 |
http_client_kwargs | None | 自定义httpx.Client配置 |
generation_kwargs支持的主要生成参数:
| 参数 | 说明 |
|---|---|
max_tokens | 输出文本的最大 token 数 |
temperature | 采样温度;更高值更富创造性(可试 0.9),0 为贪心采样(argmax)适合答案明确的场景 |
top_p | 核采样;0.1 表示仅考虑概率质量前 10% 的 token |
stream | 是否流式返回增量;若开启,token 以 server-sent events 到达,并以data: [DONE]结束 |
safe_prompt | 是否在对话前注入安全提示 |
random_seed | 随机采样种子 |
reasoning_effort | 控制推理 token 数量,可接受值"high"、"none",适用于mistral-small-latest、mistral-medium等支持可调推理的模型 |
prompt_mode | 面向原生推理模型(magistral 系列);设为"reasoning"使用默认推理系统提示,省略则走模型默认行为 |
response_format | JSON schema 或 Pydantic 模型,强制模型输出结构;提供后输出总会经过格式校验(模型返回工具调用时除外)。注意:结构化输出配合流式使用时,response_format必须是 JSON schema 而非 Pydantic 模型 |
支持的模型列表
MistralChatGenerator的SUPPORTED_MODELS覆盖了 Mistral 当前主流与实验性模型:
SUPPORTED_MODELS: list[str] = [ "mistral-medium-2505", "mistral-medium-2508", "mistral-medium-latest", "mistral-medium", "mistral-vibe-cli-with-tools", "open-mistral-nemo", "open-mistral-nemo-2407", "mistral-tiny-2407", "mistral-tiny-latest", "codestral-2508", "codestral-latest", "devstral-2512", "mistral-vibe-cli-latest", "devstral-medium-latest", "devstral-latest", "mistral-small-2506", "mistral-small-latest", "labs-mistral-small-creative", "magistral-medium-2509", "magistral-medium-latest", "magistral-small-2509", "magistral-small-latest", "voxtral-small-2507", "voxtral-small-latest", "mistral-large-2512", "mistral-large-latest", "ministral-3b-2512", "ministral-3b-latest", "ministral-8b-2512", "ministral-8b-latest", "ministral-14b-2512", "ministral-14b-latest", "mistral-large-2411", "pixtral-large-2411", "pixtral-large-latest", "mistral-large-pixtral-2411", "devstral-small-2507", "devstral-medium-2507", "labs-devstral-small-2512", "devstral-small-latest", "voxtral-mini-2507", "voxtral-mini-latest", "voxtral-mini-2602", ]run 与 run_async
run()方法签名:
run( messages: list[ChatMessage] | str, streaming_callback: StreamingCallbackT | None = None, generation_kwargs: dict[str, Any] | None = None, *, tools: ToolsType | None = None, tools_strict: bool | None = None ) -> dict[str, list[ChatMessage]]messages:ChatMessage列表;也可以直接传字符串,内部会转换为一条user角色的消息;generation_kwargs:按 key 与初始化时的generation_kwargs合并,运行时传入的 key 优先,初始化时独有且未在运行时覆盖的 key 保留;tools:若传入,会覆盖初始化时的tools设置;tools_strict:是否对工具调用启用严格 schema 遵循。
组件还提供run_async()异步版本,签名与run()一致,适合与 Haystack 异步管道配合;异步模式下streaming_callback必须是协程(coroutine)。
实战:用 Mistral 构建 PDF 文档问答管道
将上述组件串联起来,即可构建一个典型的「上传 PDF → OCR 提取 → 分页切分 → 向量化 → 检索 → 对话生成」的 RAG 管道:
from haystack import Pipeline from haystack.components.preprocessors import DocumentSplitter from haystack.components.retrievers.in_memory import InMemoryEmbeddingRetriever from haystack.document_stores.in_memory import InMemoryDocumentStore from haystack_integrations.components.converters.mistral import MistralOCRDocumentConverter from haystack_integrations.components.embedders.mistral import MistralDocumentEmbedder, MistralTextEmbedder from haystack_integrations.components.generators.mistral import MistralChatGenerator from mistralai.models import DocumentURLChunk document_store = InMemoryDocumentStore() # 1. 索引管道:OCR → 按页切分 → 嵌入 → 写入文档库 indexing = Pipeline() indexing.add_component("ocr", MistralOCRDocumentConverter()) indexing.add_component("splitter", DocumentSplitter(split_by="page", split_length=1, split_overlap=0)) indexing.add_component("embedder", MistralDocumentEmbedder()) indexing.add_component("writer", DocumentWriter(document_store=document_store)) indexing.connect("ocr.documents", "splitter.documents") indexing.connect("splitter.documents", "embedder.documents") indexing.connect("embedder.documents", "writer.documents") indexing.run({"ocr": {"sources": [DocumentURLChunk(document_url="https://example.com/report.pdf")]}}) # 2. 查询管道:问题嵌入 → 检索 → 对话生成 query = Pipeline() query.add_component("query_embedder", MistralTextEmbedder()) query.add_component("retriever", InMemoryEmbeddingRetriever(document_store=document_store)) query.add_component("prompt", PromptBuilder(template="根据以下文档回答:\n{% for doc in documents %}{{ doc.content }}{% endfor %}\n问题:{{ question }}")) query.add_component("llm", MistralChatGenerator(model="mistral-small-latest")) query.connect("query_embedder.embedding", "retriever.query_embedding") query.connect("retriever.documents", "prompt.documents") query.connect("prompt", "llm") result = query.run({"query_embedder": {"text": "这份报告的核心结论是什么?"}, "prompt": {"question": "这份报告的核心结论是什么?"}}) print(result["llm"]["replies"][0].text)关键设计要点:
- OCR 输出的
\f分页符与DocumentSplitter(split_by="page")天然契合(见 haystack/components/preprocessors/document_splitter.py); - 索引与查询阶段分别使用
MistralDocumentEmbedder和MistralTextEmbedder,保证嵌入空间一致; MistralChatGenerator的generation_kwargs可在初始化或run()时按需覆盖,例如{"temperature": 0.2, "max_tokens": 512};- 如需结构化答案,可在
generation_kwargs中传入response_format(JSON schema 或 Pydantic 模型)。
常见问题与使用限制
- 密钥未配置:组件默认读取
MISTRAL_API_KEY环境变量,未设置时初始化会失败;也可在构造函数中通过Secret显式传入。 - OCR 文件清理:
cleanup_uploaded_files=True(默认)时,本地来源上传的文件处理完即被删除;如需保留,可显式设为False。 - 文档级标注页数上限:
document_annotation_schema仅处理前 8 页,超长文档不会进行文档级标注。 - 流式 + 结构化输出:
response_format配合流式时必须使用 JSON schema,不能用 Pydantic 模型。 - 异步流式回调:
run_async的streaming_callback必须是协程。 - 模型可用性:组件内置的
SUPPORTED_MODELS为文档生成时的快照;完整模型列表可通过GET https://api.mistral.ai/v1/models实时获取。
参考路径
- Mistral 集成参考文档:docs-website/reference_versioned_docs/version-2.20/integrations-api/mistral.md
- 嵌入器基类实现:haystack/components/embedders/openai_document_embedder.py 与 haystack/components/embedders/openai_text_embedder.py
- 生成器基类实现:haystack/components/generators/chat/openai.py
ChatMessage与推理内容:haystack/dataclasses/chat_message.py- 换页符分页支持:haystack/components/preprocessors/document_splitter.py
- 密钥管理与字节流数据类:haystack/utils/auth.py 与 haystack/dataclasses/byte_stream.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),仅供参考