跳至主要内容

Mistral OCR:实践示例指南

学习如何使用 Mistral 的 OCR API 与 Python 从文档中提取文本和图像,并将 OCR 功能集成到应用程序中。
· 12分钟 阅读

使用 AI 探索

上周,Mistral 发布了 Mistral OCR,这是一款创新的光学字符识别(OCR)API。该 API 为 AI 理解文档和图像的能力树立了新标准。它能够高精度地处理并解析包含图像、数学公式、表格等内容的文档。

在本文中,我将一步步讲解如何在 Python 中使用 Mistral OCR。我会向您展示如何用于文档、图像,以及如何与聊天结合,将提示与文档结合使用。

什么是 Mistral OCR?

光学字符识别(OCR)是一种将各类文档(如扫描的纸质文档、PDF 文件或数码相机拍摄的图像)转换为可编辑、可搜索数据的技术。

OCR 的工作原理是识别图像中的文本字符,分析其模式,并将这些视觉元素转换为机器编码文本。该技术改变了我们与印刷材料的互动方式,从历史档案数字化到自动化录入业务表单数据,皆由此实现。

Mistral 的 OCR API 在该领域实现了显著进步,为开发者提供了强大的工具,以卓越的准确率从图像和文档中提取文本。

Mistral OCR example

来源: Mistral

与仅能识别文本的传统 OCR 方案不同,Mistral 的 API 利用先进的 AI 模型理解文档的上下文与结构,在提取内容的同时保留格式。这意味着它可以识别复杂的版式,区分标题与正文,并正确解析表格和多栏布局。

Mistral 的 OCR API 之所以特别,在于其与 Mistral 的语言理解能力深度集成。系统不仅仅是提取文本——它还能理解文本。

这使得更复杂的文档处理工作流成为可能:API 不仅能识别文本,还能回答有关文档内容的问题、总结信息,或提取特定数据点。

此外,Mistral 的 OCR API 旨在支持多语言和多字符集,使其在全球应用场景中更具通用性。精确文本识别与深度语言理解的结合,让 Mistral 的方案不仅仅是一款简单的 OCR 工具,而是下一代文档智能解决方案。

Mistral OCR 的定价与限制

Mistral OCR API 并非免费,但价格仅为每 1,000 页 1 美元(即每页 0.001 美元)。在我看来,这个定价非常有竞争力且亲民。

文档文件大小不得超过 50 MB,页数不应超过 1,000 页。

更多信息请参见 其定价页面。

Mistral OCR API 设置

前往 Mistral API 密钥页面,点击“Create new key”。

在创建密钥的表单中,我们可以为其命名并设置过期日期。

  • 名称便于组织管理,尤其在我们有多个项目、各用不同密钥时。本教程可留空。
  • 过期日期有助于确保即使我们不小心泄露了密钥,别人也不会永久获取访问权限。

API key form mistral

创建密钥后,将其复制,并在我们将编写脚本的同一文件夹中创建一个名为 .env 的文件。

Creating an API key for using mistral OCR

将密钥粘贴到该文件,格式如下:

MISTRAL_API_KEY=<paste_api_key_here>

如果您使用 GitHub,请确保将该文件加入 .gitignore,以避免将 API 密钥上传至 GitHub。

Python 环境设置

要在 Python 中使用 Mistral 的 OCR API,请安装以下软件包:

  • mistralai:Mistral 提供的与其 API 交互的包。
  • python-dotenv:用于从 .env 文件便捷加载 API 密钥的包。
  • datauri:用于处理图像数据并将其保存为文件的包。

我们可以使用以下命令安装:

pip install mistralai python-dotenv datauri

建议创建独立环境,避免与默认 Python 安装冲突。一个可行的方法是使用 Anaconda:

conda create -n mistral -y python=3.9
conda activate mistral
pip install mistralai python-dotenv datauri

第一条命令创建名为 mistral 的环境并使用 Python 3.9。随后,我们激活该环境并安装上述软件包。

创建与 Mistral OCR 交互的 Python 脚本

让我们看看如何向 Mistral 的 OCR API 发出第一个请求。

导入必要依赖

在与 .env 文件相同的文件夹中,创建名为 ocr.py 的 Python 脚本,并导入必要包:

from mistralai import Mistral
from dotenv import load_dotenv
import datauri
import os

注意我们还导入了 os,用于将环境中的 API 密钥加载到变量。它为内置包,无需安装。

加载 API 密钥并初始化 Mistral 客户端

接着,添加以下代码以加载 API 密钥并初始化 Mistral 客户端:

load_dotenv()
api_key = os.environ["MISTRAL_API_KEY"]
client = Mistral(api_key=api_key)

向 Mistral OCR API 发起请求

使用 OCR API 最简单的方法是提供一个在线托管的 PDF URL。此处以 arXiv 上托管的 这篇 Mistral 7B 论文为例(arXiv 是一个托管研究论文预印本的平台):

ocr_response = client.ocr.process(
  model="mistral-ocr-latest",
  document={
    "type": "document_url",
    "document_url": "https://arxiv.org/pdf/2501.00663",
  },
)
print(ocr_response)

然后我们可使用命令 python ocr.py 运行脚本。这将生成如下响应:

pages=[OCRPageObject(index=0, markdown='# Mistral 7B \n\nAlbert Q. Jiang,
...

响应结构

响应包含多个字段。完整细节见 Mistral 的 API 文档。我们尤其关心 pages 字段,它为每一页提供该页的 markdown 文本。

我们可以打印页数,以确认与 PDF 文件一致:

print(len(ocr_response.pages))

结果:

9

每一页包含若干字段,最重要的是:

  • markdown:该页的 markdown 内容。
  • images:该页上的图像。

例如,我们可以打印第一页的 markdown 内容:

print(ocr_response.pages[0].markdown)
# Mistral 7B 

Albert Q. Jiang, Alexandre Sablayrolles, Arthur Mensch, Chris Bamford, Devendra Singh Chaplot, Diego de las Casas, Florian Bressand, Gianna Lengyel, Guillaume Lample, Lucile Saulnier, Lélio Renard Lavaud, Marie-Anne Lachaux, Pierre Stock, Teven Le Scao, Thibaut Lavril, Thomas Wang, Timothée Lacroix, William El Sayed

![img-0.jpeg](img-0.jpeg)

#### Abstract

We introduce Mistral 7B, a 7-billion-parameter language
...

将 PDF 转换为 Markdown

要将 PDF 转为 Markdown,我们遍历所有页面,并将每页的 Markdown 内容写入文件。下面是相应函数。

def create_markdown_file(ocr_response, output_filename = "output.md"):
  with open(output_filename, "wt") as f:
    for page in ocr_response.pages:
      f.write(page.markdown)

下图是原始 PDF 与我们生成的 Markdown 文件的并排对比:

Converting a PDF to markdown using Mistral OCR

处理图像

在前面的示例中,我们看到生成的 Markdown 文件没有 PDF 中的图像。这是因为我们只生成了 Markdown 文本,而没有创建图像文件。

如果查看 markdown 输出,可以看到它包含一个图像引用:

...
![img-0.jpeg](img-0.jpeg)
...

然而,该图像并未呈现。每页的图像存储在 images 属性中。

for page in ocr_response.pages:
  print(page.images)

输出:

[OCRImageObject(id='img-0.jpeg', top_left_x=425, top_left_y=600, bottom_right_x=1283, bottom_right_y=893, image_base64=None)]
[OCRImageObject(id='img-1.jpeg', top_left_x=294, top_left_y=638, bottom_right_x=1405, bottom_right_y=1064, image_base64=None)]
[OCRImageObject(id='img-2.jpeg', top_left_x=294, top_left_y=191, bottom_right_x=1405, bottom_right_y=380, image_base64=None)]
[OCRImageObject(id='img-3.jpeg', top_left_x=292, top_left_y=204, bottom_right_x=1390, bottom_right_y=552, image_base64=None)]
[OCRImageObject(id='img-4.jpeg', top_left_x=464, top_left_y=202, bottom_right_x=1232, bottom_right_y=734, image_base64=None)]
[]
[OCRImageObject(id='img-5.jpeg', top_left_x=727, top_left_y=794, bottom_right_x=975, bottom_right_y=1047, image_base64=None)]
[]
[]

从上述输出可见,我们确实有 img-0.jpeg 的引用。但数据不存在:image_base64=None。

要获取图像数据,需要在 OCR 请求中添加 include_image_base64=True 参数,以包含图像数据。

ocr_response = client.ocr.process(
  model="mistral-ocr-latest",
  document={
    "type": "document_url",
    "document_url": "https://arxiv.org/pdf/2310.06825",
  },
  include_image_base64=True,
)

如果再次打印图像,可以看到 image_base_64 字段已有内容。顾名思义,图像数据以 base64 存储。我们不深入展开 base64 图像表示的细节,而是提供一个使用之前安装的 datauri 包将图像写入文件的函数:

def save_image(image):
    parsed = datauri.parse(image.image_base64)
    with open(image.id, "wb") as file:
      file.write(parsed.data)

现在我们可以更新 create_markdown_file() 函数,同时将所有图像写入文件:

def create_markdown_file(ocr_response, output_filename = "output.md"):
  with open(output_filename, "wt") as f:
    for page in ocr_response.pages:
      f.write(page.markdown)
      for image in page.images:
        save_image(image)

运行更新后的代码并重新预览 Markdown,即可看到图像。

Processing document images

使用本地文件

在上述示例中,我们使用了已托管的文件。要处理我们电脑上的 PDF 文件,Mistral API 允许通过 client.files.upload() 函数上传文件。假设 PDF 文件 myfile.pdf 与脚本位于同一文件夹,可如下操作:

filename = "myfile.pdf"
uploaded_pdf = client.files.upload(
  file={
    "file_name": filename,
    "content": open(filename, "rb"),
  },
  purpose="ocr"
)

以这种方式上传的每个文件都会关联唯一 ID,后续引用该文件需要此 ID。我们可以通过结果的 id 属性获取:

print(uploaded_pdf.id)

要对该文件执行 OCR,我们需要提供其 URL。可通过提供文件 ID,使用 client.files.get_signed_url() 函数获取:

signed_url = client.files.get_signed_url(file_id=uploaded_pdf.id)

将上述步骤整合,我们可以实现一个使用 Mistral API 上传文件并获取其 URL 的函数:

def upload_pdf(filename):
  uploaded_pdf = client.files.upload(
    file={
      "file_name": filename,
      "content": open(filename, "rb"),
    },
    purpose="ocr"
  )
  signed_url = client.files.get_signed_url(file_id=uploaded_pdf.id)
  return signed_url.url

以下是使用本地文件发起 OCR 请求的示例:

ocr_response = client.ocr.process(
  model="mistral-ocr-latest",
  document={
    "type": "document_url",
    "document_url": upload_pdf("myfile.pdf"),
  },
  include_image_base64=True,
)

若要使用其他文件,只需将 myfile.pdf 替换为目标文件名。

对图像进行 OCR

OCR API 同样支持图像输入。要处理图像,我们将类型设置为 image_url,而非 document_url:

ocr_response = client.ocr.process(
  model="mistral-ocr-latest",
  document={
    "type": "image_url",
    "image_url": <url of the image>,
  },
)

在上例中,我们需要将 <url of the image> 替换为图像的 URL。

要使用本地图像,我们可以用下面的函数加载它:

def load_image(image_path):
  import base64
  mime_type, _ = mimetypes.guess_type(image_path)
  with open(image_path, "rb") as image_file:
    image_data = image_file.read()
  base64_encoded = base64.b64encode(image_data).decode('utf-8')
  base64_url = f"data:{mime_type};base64,{base64_encoded}"
  return base64_url

该函数使用内置包 base64,因此无需安装。

让我们尝试对一张保存在 receipt.jpeg 文件中的收据执行 OCR:

Receipt example for OCR

我们可以通过调用 load_image() 从电脑加载图像并发起 OCR 请求:

ocr_response = client.ocr.process(
  model="mistral-ocr-latest",
  document={
    "type": "image_url",
    "image_url": load_image("receipt.jpeg"),
  },
)

结果如下:

Using Mistral OCR with images

尽管不够完美,但结果已相当接近。

将 Mistral OCR 与聊天结合

OCR 能高效地将数据转换为适合 LLM 使用的文本格式。Mistral API 允许用户在 LLM 请求中组合文档与提示。在幕后,OCR API 会处理文档,使其可供 LLM 消化。

让我们尝试用这一能力来总结本文中一直引用的那篇文章。

如果您是首次使用 Mistral 的聊天 API,建议先阅读 这份 Mistral 综合指南,本文不再展开其工作原理细节。

以下是一个完整的 Python 示例,请求对文章做浅显易懂的解释:

from mistralai import Mistral
import os
from dotenv import load_dotenv
load_dotenv()
api_key = os.environ["MISTRAL_API_KEY"]
client = Mistral(api_key=api_key)
messages = [
  {
    "role": "user",
    "content": [
      {
        "type": "text",
        "text": "Explain this article in detail to someone who doesn't have a technical background",
      },
      {
        "type": "document_url",
        "document_url": "https://arxiv.org/pdf/2310.06825",
      },
    ],
  }
]
chat_response = client.chat.complete(
  model="mistral-small-latest",
  messages=messages,
)
print(chat_response.choices[0].message.content)

请注意,文件的提供格式与上文一致:

{
  "type": "document_url",
  "document_url": "https://arxiv.org/pdf/2310.06825",
}

Mistral OCR 的真实应用场景

现在您已经学会如何在 Python 项目中实现 Mistral OCR,接下来看看我们可以在哪些实践场景中应用所学内容。

科研论文分析

您可以从科学论文中提取文本、公式、表格和图形,构建个性化研究助理。您可以创建一个系统来总结关键发现、提取方法细节,或构建您所在领域论文的可搜索数据库。

文档数字化项目

您可以将实体档案或扫描文档转化为可搜索的数字化集合。这对需要保存与便捷访问的历史文献、家族记录或机构档案尤为有价值。

多语言文档处理

您可以利用 Mistral OCR 的多语言能力处理多种语言的文档。这对跨国企业、翻译服务或需要从不同文字体系的文档中提取信息的全球性研究项目大有裨益。

教育内容管理

您可以将教材、课件和手写笔记转换为数字格式。构建一个系统来提取关键概念、公式和图示,以生成个性化学习资料或题库。

财务文档处理

您可以自动化提取发票、收据、财务报表或税务文件中的数据。这有助于简化会计流程,或用于费用管理与财务分析。

结语

Mistral 的 OCR API 为从文档和图像中提取与理解文本提供了强大的工具。在本教程中,我们介绍了如何设置并将其用于各类文档处理任务。

按照本教程中的步骤,您可以将 Mistral 的 OCR 集成到您的应用程序中,无论是档案数字化、数据录入自动化,还是构建智能文档管理系统。随着技术持续演进,我们可以期待更高精度、更加理解上下文的文档处理能力,进一步弥合物理文档与数字化工作流之间的鸿沟。

François Aubry

作者

François Aubry

全栈工程师,CheapGPT 创始人。我一直热爱教学。从学生时代起,我就积极寻找机会为同学提供辅导与帮助。这份热情促使我攻读博士学位,并在此期间担任助教,以支持我的学术追求。那些年里,我在传统课堂环境中收获了极大的成就感,既建立联系也促进学习。随着在线学习平台的兴起,我也看到了数字教育的变革潜力。事实上,我曾参与我们大学一款此类平台的建设。我致力于将传统教学理念与创新的数字方法相融合。我的热情在于打造既有吸引力、信息量充足,又能让当代学习者轻松获取的课程。

主题