模型摘要: Granite Vision 4.1 4B 是一款视觉语言模型(VLM),在结构化文档提取任务(图表提取、表格提取和语义键值对提取)上展现出前沿级性能。它仅需 40 亿参数的紧凑规模,为这些任务提供了一个轻量级替代方案,可与规模大得多的前沿模型相媲美:
该模型在 Granite-4.1-3B 的基础上进行微调,包含一个 34 亿参数的大型语言模型(LLM)以及 6 亿参数的视觉编码器和投影器。详情请参见模型架构。
本模型所使用的方法和数据(ChartNet)在论文《ChartNet: A Million-Scale, High-Quality Multimodal Dataset for Robust Chart Understanding》中有所描述,论文链接:https://huggingface.co/papers/2603.27064。
尽管我们的重点是专门的文档提取任务,但当前模型保留并扩展了 Granite Vision 4.0 3B 的功能,确保现有用户能够无缝采用,无需更改其工作流程。它继续支持视觉语言任务,例如从图像生成详细的自然语言描述(图像到文本)。该模型可单独使用,并能与 Docling 无缝集成,通过深度视觉理解能力增强文档处理管道。
该模型支持专门的提取任务,每个任务都可通过用户消息中的简单任务标签激活。聊天模板会自动将标签扩展为完整提示,无需编写冗长的指令。
| 标签 | 任务 | 输出 |
|---|---|---|
<chart2csv> | 图表转 CSV | 带标题和数值的 CSV 表格 |
<chart2code> | 图表转 Python 代码 | 用于重新创建图表的 Python 代码 |
<chart2summary> | 图表转摘要 | 图表的自然语言描述 |
<tables_json> | 表格提取(JSON 格式) | 包含维度和单元格的结构化 JSON |
<tables_html> | 表格提取(HTML 格式) | HTML <table> 标记 |
<tables_otsl> | 表格提取(OTSL 格式) | 带有单元格/合并标签的 OTSL 标记 |
| KVP(见下文提示说明) | 基于 schema 的键值对提取 | 包含嵌套字典和数组的 JSON |
Granite Vision 4.1 4B 为结构化文档提取基准测试提供了轻量级的前沿模型替代方案,以较少的参数数量实现了相当的性能。
我们使用 ChartNet 中经过人工验证的测试集来评估图表提取。通过 LLM 作为评判者(GPT4o)将预测结果与真实结果进行比较,为模型评分。我们报告了 Chart2CSV 和 Chart2Summary 任务的平均得分(0–100)。
为了对表格提取进行基准测试,我们构建了一个统一的评估套件,涵盖多个数据集和设置,以评估视觉语言模型的端到端表格提取能力:
为了统一评估,我们将每个数据集的原始标注(例如问答对)替换为单一指令:从图像中以 HTML 格式提取表格,并使用相应的 HTML 作为真实结果。对于全页面输入,仅考虑表格元素;当出现多个表格时,将它们聚合到一个 Python 列表中。
我们使用 TEDS(基于树编辑距离的相似度)报告结果,该指标用于衡量预测的 HTML 表格与真实 HTML 表格之间的结构和内容相似度。
结果分别针对裁剪表格和全页面设置呈现,以突出模型在受控场景和真实文档场景下的性能。
我们在 VAREX 上进行评估,这是一个用于从文档中进行多模态结构化提取的基准测试。Granite Vision 4.1 4B 实现了 94.2% 的精确匹配准确率(零样本),与更大规模的前沿模型相比具有竞争力(查看结果此处)。
已在 python=3.11 版本下测试通过
pip install torch==2.10.0 --index-url https://download.pytorch.org/whl/cu128
pip install transformers>=5.8.0 peft>=0.19.1 tokenizers>=0.22.2 pillow>=12.2.0若需原生支持,需 transformers>=5.8.0。在旧版本中,请在两次 from_pretrained 调用时传入 trust_remote_code=True,以使用捆绑的旧版建模代码。
import re
from io import StringIO
import pandas as pd
import torch
from transformers import AutoProcessor, AutoModelForImageTextToText
from PIL import Image
from huggingface_hub import hf_hub_download
model_id = "ibm-granite/granite-vision-4.1-4b"
device = "cuda" if torch.cuda.is_available() else "cpu"
processor = AutoProcessor.from_pretrained(model_id)
processor.tokenizer.padding_side = "left" # required for correct batched generation
model = AutoModelForImageTextToText.from_pretrained(
model_id,
dtype=torch.bfloat16,
device_map=device
).eval()
def run_inference(model, processor, images, prompts):
"""Run batched inference on image+prompt pairs (one image per prompt)."""
conversations = [
[{"role": "user", "content": [
{"type": "image"},
{"type": "text", "text": prompt},
]}]
for prompt in prompts
]
texts = [
processor.apply_chat_template(conv, tokenize=False, add_generation_prompt=True)
for conv in conversations
]
inputs = processor(
text=texts, images=images, return_tensors="pt", padding=True, do_pad=True
).to(model.device)
outputs = model.generate(
**inputs,
max_new_tokens=4096,
use_cache=True
)
results = []
for i in range(len(prompts)):
gen = outputs[i, inputs["input_ids"].shape[1]:]
results.append(processor.decode(gen, skip_special_tokens=True))
return results
def display_table(text):
"""Pretty-print CSV (possibly wrapped in ```csv```) or HTML table content via pandas."""
m = re.search(r"```csv\s*
(.*?)```", text, re.DOTALL)
if m:
df = pd.read_csv(StringIO(m.group(1)))
print(df.to_string(index=False))
elif "<table" in text.lower():
df = pd.read_html(StringIO(text))[0]
print(df.to_string(index=False))
else:
print(text)您只需传入标签,聊天模板会处理其余部分:
chart_path = hf_hub_download(repo_id=model_id, filename="chart.jpg")
table_path = hf_hub_download(repo_id=model_id, filename="table.png")
chart_img = Image.open(chart_path).convert("RGB")
table_img = Image.open(table_path).convert("RGB")
# Batched chart tasks
chart_prompts = ["<chart2csv>", "<chart2summary>", "<chart2code>"]
chart_results = run_inference(model, processor, [chart_img] * len(chart_prompts), chart_prompts)
for prompt, result in zip(chart_prompts, chart_results):
print(f"{prompt}:")
display_table(result)
print()
# Batched table tasks
table_prompts = ["<tables_html>", "<tables_otsl>"]
table_results = run_inference(model, processor, [table_img] * len(table_prompts), table_prompts)
for prompt, result in zip(table_prompts, table_results):
print(f"{prompt}:")
display_table(result)
print()进行键值对提取时,请使用VAREX提示格式。提供一个描述待提取字段的JSON模式,模型将返回一个包含提取值的JSON对象。
import json
invoice_path = hf_hub_download(repo_id=model_id, filename="invoice.png")
invoice_img = Image.open(invoice_path).convert("RGB")
schema = {
"type": "object",
"properties": {
"invoice_date": {"type": "string", "description": "The date the invoice was issued"},
"order_number": {"type": "string", "description": "The unique identifier for the order"},
"seller_tax_id": {"type": "string", "description": "The tax identification number of the seller"},
}
}
prompt = f"""Extract structured data from this document.
Return a JSON object matching this schema:
{json.dumps(schema, indent=2)}
Return null for fields you cannot find.
Return ONLY valid JSON.
Return an instance of the JSON with extracted values, not the schema itself."""
result = run_inference(model, processor, [invoice_img], [prompt])[0]
print(result)从 v0.21.0 版本开始,vLLM 原生支持 Granite Vision 4.1:
pip install vllm>=0.21.0vllm serve ibm-granite/granite-vision-4.1-4b --host 0.0.0.0 --port 8000使用 OpenAI 兼容 API 查询运行中的服务器:
import base64
from openai import OpenAI
from huggingface_hub import hf_hub_download
from PIL import Image
model_id = "ibm-granite/granite-vision-4.1-4b"
client = OpenAI(base_url="http://localhost:8000/v1", api_key="EMPTY")
def run_inference(client, model_id, image_path, tag):
with open(image_path, "rb") as f:
image_b64 = base64.b64encode(f.read()).decode("utf-8")
messages = [
{"role": "user", "content": [
{"type": "image_url", "image_url": {"url": f"data:image/png;base64,{image_b64}"}},
{"type": "text", "text": tag},
]}
]
response = client.chat.completions.create(
model=model_id, messages=messages, max_tokens=4096, temperature=0,
)
return response.choices[0].message.content
chart_path = hf_hub_download(repo_id=model_id, filename="chart.jpg")
table_path = hf_hub_download(repo_id=model_id, filename="table.png")
# Chart tasks
for tag in ["<chart2csv>", "<chart2summary>", "<chart2code>"]:
result = run_inference(client, model_id, chart_path, tag)
print(f"{tag}:
{result}
")
# Table tasks
for tag in ["<tables_json>", "<tables_html>", "<tables_otsl>"]:
result = run_inference(client, model_id, table_path, tag)
print(f"{tag}:
{result}
")MLX VLM 通过 MLX 框架在 Apple Silicon 上原生运行 Granite Vision 4.1 4B。
从源代码安装以获取最新功能:
pip install git+https://github.com/Blaizzy/mlx-vlm.gitmlx_vlm generate \
--model ibm-granite/granite-vision-4.1-4b \
--image chart.jpg \
--prompt "<chart2csv>"Docling 将 Granite Vision 集成到文档转换流程中:
pip install docling[granite_vision])该模型在精选的混合提取数据集上进行了微调,涵盖图表理解、复杂表格解析和文档键值对(KVP)提取,并辅以通用的 Granite Vision 指令遵循数据集 以实现广泛的视觉理解。
图表理解数据是通过一种新颖的代码引导增强方法创建的,该方法生成多样化、语义对齐的图表样本,包含渲染代码、图表图像、基础数据 CSV 以及自然语言摘要。借助此流程,我们还发布了 ChartNet,这是一个包含百万级样本的综合多模态数据集,富含真实世界、人工标注、安全性和基础事实子集。该数据集及其方法在论文 ChartNet: A Million-Scale, High-Quality Multimodal Dataset for Robust Chart Understanding 中有详细说明。
SigLIP2 视觉编码器:google/siglip2-so400m-patch16-384。输入图像被分割为 384×384 的补丁(始终包含一个基础的下采样视图),每个补丁独立编码。训练期间,视觉编码器使用 LoRA 适配器进行微调。该检查点提供已合并适配器的权重。
窗口 Q-Former 投影器:视觉特征通过窗口化 Q-Former 投影器压缩 4 倍:每个 4×4 补丁窗口通过交叉注意力减少为 2×2 个标记,其中查询从窗口特征的下采样版本初始化。这减少了输入到 LLM 的视觉标记数量。
特征注入:Deepstack 的一种变体,其中视觉特征通过两种互补机制以加法方式注入到 LLM 多个层的隐藏状态中:
总共有 8 个视觉到 LLM 的注入点,在网络中分布视觉信息以实现更强的视觉基础。
语言模型:Granite-4.1(3B),在所有自注意力投影和 MLP 层上使用 LoRA(秩 256)。该检查点提供已合并适配器的权重。
支持的输入:英文指令和图像(PNG、JPEG)。
Granite 4.1 Vision 是在 IBM 的 Blue Vela 超级计算集群上训练的,该集群配备了 NVIDIA H100 GPU。训练使用了 32 块 GPU,耗时约 200 小时。
在部署视觉语言模型前,应考虑其使用过程中涉及的特定风险:
为提高企业部署的安全性,我们建议将 Granite 4.1 Vision 与 Granite Guardian 配合使用。Granite Guardian 是一款旨在检测和标记输入与输出中存在的风险的模型,其覆盖范围基于 IBM AI Risk Atlas 中概述的关键维度。
@misc{granite-vision-4.1-4b,
title={Granite 4.1 Vision},
author={IBM Granite Vision Team},
year={2026},
url={https://huggingface.co/ibm-granite/granite-vision-4.1-4b}
}
@article{kondic2026chartnet,
title={ChartNet: A Million-Scale, High-Quality Multimodal Dataset for Robust Chart Understanding},
author={Kondic, Jovana and Li, Pengyuan and Joshi, Dhiraj and Sanchez, Isaac and Wiesel, Ben and Abedin, Shafiq and Alfassy, Amit and Schwartz, Eli and Caraballo, Daniel and Cinar, Yagmur Gizem and Scheidegger, Florian and Ross, Steven I. and Weidele, Daniel Karl I. and Hua, Hang and Arutyunova, Ekaterina and Herzig, Roei and He, Zexue and Wang, Zihan and Yu, Xinyue and Zhao, Yunfei and Jiang, Sicong and Liu, Minghao and Lin, Qunshu and Staar, Peter and Lastras, Luis and Oliva, Aude and Feris, Rogerio},
journal={arXiv preprint arXiv:2603.27064},
year={2026}
}