Views
No views yet

1# Prerequisites:
2# pip install torch
3# pip install docling_core
4# pip install transformers
5
6import torch
7from docling_core.types.doc import DoclingDocument
8from docling_core.types.doc.document import DocTagsDocument
9from transformers import AutoProcessor, AutoModelForVision2Seq
10from transformers.image_utils import load_image
11from pathlib import Path
12
13DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
14
15# Load images
16image = load_image("https://upload.wikimedia.org/wikipedia/commons/7/76/GazettedeFrance.jpg")
17
18# Initialize processor and model
19processor = AutoProcessor.from_pretrained("ds4sd/SmolDocling-256M-preview")
20model = AutoModelForVision2Seq.from_pretrained(
21 "ds4sd/SmolDocling-256M-preview",
22 torch_dtype=torch.bfloat16,
23 _attn_implementation="flash_attention_2" if DEVICE == "cuda" else "eager",
24).to(DEVICE)
25
26# Create input messages
27messages = [
28 {
29 "role": "user",
30 "content": [
31 {"type": "image"},
32 {"type": "text", "text": "Convert this page to docling."}
33 ]
34 },
35]
36
37# Prepare inputs
38prompt = processor.apply_chat_template(messages, add_generation_prompt=True)
39inputs = processor(text=prompt, images=[image], return_tensors="pt")
40inputs = inputs.to(DEVICE)
41
42# Generate outputs
43generated_ids = model.generate(**inputs, max_new_tokens=8192)
44prompt_length = inputs.input_ids.shape[1]
45trimmed_generated_ids = generated_ids[:, prompt_length:]
46doctags = processor.batch_decode(
47 trimmed_generated_ids,
48 skip_special_tokens=False,
49)[0].lstrip()
50
51# Populate document
52doctags_doc = DocTagsDocument.from_doctags_and_image_pairs([doctags], [image])
53print(doctags)
54# create a docling document
55doc = DoclingDocument.load_from_doctags(doctags_doc, document_name="Document")
56
57# export as any format
58# HTML
59# Path("Out/").mkdir(parents=True, exist_ok=True)
60# output_path_html = Path("Out/") / "example.html"
61# doc.save_as_html(output_path_html)
62# MD
63print(doc.export_to_markdown())1# Prerequisites:
2# pip install vllm
3# pip install docling_core
4# place page images you want to convert into "img/" dir
5
6import time
7import os
8from vllm import LLM, SamplingParams
9from PIL import Image
10from docling_core.types.doc import DoclingDocument
11from docling_core.types.doc.document import DocTagsDocument
12from pathlib import Path
13
14# Configuration
15MODEL_PATH = "ds4sd/SmolDocling-256M-preview"
16IMAGE_DIR = "img/" # Place your page images here
17OUTPUT_DIR = "out/"
18PROMPT_TEXT = "Convert page to Docling."
19
20# Ensure output directory exists
21os.makedirs(OUTPUT_DIR, exist_ok=True)
22
23# Initialize LLM
24llm = LLM(model=MODEL_PATH, limit_mm_per_prompt={"image": 1})
25
26sampling_params = SamplingParams(
27 temperature=0.0,
28 max_tokens=8192)
29
30chat_template = f"<|im_start|>User:<image>{PROMPT_TEXT}<end_of_utterance>
31Assistant:"
32
33image_files = sorted([f for f in os.listdir(IMAGE_DIR) if f.lower().endswith((".png", ".jpg", ".jpeg"))])
34
35start_time = time.time()
36total_tokens = 0
37
38for idx, img_file in enumerate(image_files, 1):
39 img_path = os.path.join(IMAGE_DIR, img_file)
40 image = Image.open(img_path).convert("RGB")
41
42 llm_input = {"prompt": chat_template, "multi_modal_data": {"image": image}}
43 output = llm.generate([llm_input], sampling_params=sampling_params)[0]
44
45 doctags = output.outputs[0].text
46 img_fn = os.path.splitext(img_file)[0]
47 output_filename = img_fn + ".dt"
48 output_path = os.path.join(OUTPUT_DIR, output_filename)
49
50 with open(output_path, "w", encoding="utf-8") as f:
51 f.write(doctags)
52
53 # To convert to Docling Document, MD, HTML, etc.:
54 doctags_doc = DocTagsDocument.from_doctags_and_image_pairs([doctags], [image])
55 doc = DoclingDocument.load_from_doctags(doctags_doc, document_name="Document")
56 # export as any format
57 # HTML
58 # output_path_html = Path(OUTPUT_DIR) / f"{img_fn}.html"
59 # doc.save_as_html(output_path_html)
60 # MD
61 output_path_md = Path(OUTPUT_DIR) / f"{img_fn}.md"
62 doc.save_as_markdown(output_path_md)
63print(f"Total time: {time.time() - start_time:.2f} sec")1# Prerequisites:
2# pip install onnxruntime
3# pip install onnxruntime-gpu
4from transformers import AutoConfig, AutoProcessor
5from transformers.image_utils import load_image
6import onnxruntime
7import numpy as np
8import os
9from docling_core.types.doc import DoclingDocument
10from docling_core.types.doc.document import DocTagsDocument
11
12os.environ["OMP_NUM_THREADS"] = "1"
13# cuda
14os.environ["ORT_CUDA_USE_MAX_WORKSPACE"] = "1"
15
16# 1. Load models
17## Load config and processor
18model_id = "ds4sd/SmolDocling-256M-preview"
19config = AutoConfig.from_pretrained(model_id)
20processor = AutoProcessor.from_pretrained(model_id)
21
22## Load sessions
23# !wget https://huggingface.co/ds4sd/SmolDocling-256M-preview/resolve/main/onnx/vision_encoder.onnx
24# !wget https://huggingface.co/ds4sd/SmolDocling-256M-preview/resolve/main/onnx/embed_tokens.onnx
25# !wget https://huggingface.co/ds4sd/SmolDocling-256M-preview/resolve/main/onnx/decoder_model_merged.onnx
26# cpu
27# vision_session = onnxruntime.InferenceSession("vision_encoder.onnx")
28# embed_session = onnxruntime.InferenceSession("embed_tokens.onnx")
29# decoder_session = onnxruntime.InferenceSession("decoder_model_merged.onnx"
30
31# cuda
32vision_session = onnxruntime.InferenceSession("vision_encoder.onnx", providers=["CUDAExecutionProvider"])
33embed_session = onnxruntime.InferenceSession("embed_tokens.onnx", providers=["CUDAExecutionProvider"])
34decoder_session = onnxruntime.InferenceSession("decoder_model_merged.onnx", providers=["CUDAExecutionProvider"])
35
36## Set config values
37num_key_value_heads = config.text_config.num_key_value_heads
38head_dim = config.text_config.head_dim
39num_hidden_layers = config.text_config.num_hidden_layers
40eos_token_id = config.text_config.eos_token_id
41image_token_id = config.image_token_id
42end_of_utterance_id = processor.tokenizer.convert_tokens_to_ids("<end_of_utterance>")
43
44# 2. Prepare inputs
45## Create input messages
46messages = [
47 {
48 "role": "user",
49 "content": [
50 {"type": "image"},
51 {"type": "text", "text": "Convert this page to docling."}
52 ]
53 },
54]
55
56## Load image and apply processor
57image = load_image("https://ibm.biz/docling-page-with-table")
58prompt = processor.apply_chat_template(messages, add_generation_prompt=True)
59inputs = processor(text=prompt, images=[image], return_tensors="np")
60
61## Prepare decoder inputs
62batch_size = inputs['input_ids'].shape[0]
63past_key_values = {
64 f'past_key_values.{layer}.{kv}': np.zeros([batch_size, num_key_value_heads, 0, head_dim], dtype=np.float32)
65 for layer in range(num_hidden_layers)
66 for kv in ('key', 'value')
67}
68image_features = None
69input_ids = inputs['input_ids']
70attention_mask = inputs['attention_mask']
71position_ids = np.cumsum(inputs['attention_mask'], axis=-1)
72
73
74# 3. Generation loop
75max_new_tokens = 8192
76generated_tokens = np.array([[]], dtype=np.int64)
77for i in range(max_new_tokens):
78 inputs_embeds = embed_session.run(None, {'input_ids': input_ids})[0]
79
80 if image_features is None:
81 ## Only compute vision features if not already computed
82 image_features = vision_session.run(
83 ['image_features'], # List of output names or indices
84 {
85 'pixel_values': inputs['pixel_values'],
86 'pixel_attention_mask': inputs['pixel_attention_mask'].astype(np.bool_)
87 }
88 )[0]
89
90 ## Merge text and vision embeddings
91 inputs_embeds[inputs['input_ids'] == image_token_id] = image_features.reshape(-1, image_features.shape[-1])
92
93 logits, *present_key_values = decoder_session.run(None, dict(
94 inputs_embeds=inputs_embeds,
95 attention_mask=attention_mask,
96 position_ids=position_ids,
97 **past_key_values,
98 ))
99
100 ## Update values for next generation loop
101 input_ids = logits[:, -1].argmax(-1, keepdims=True)
102 attention_mask = np.ones_like(input_ids)
103 position_ids = position_ids[:, -1:] + 1
104 for j, key in enumerate(past_key_values):
105 past_key_values[key] = present_key_values[j]
106
107 generated_tokens = np.concatenate([generated_tokens, input_ids], axis=-1)
108 if (input_ids == eos_token_id).all() or (input_ids == end_of_utterance_id).all():
109 break # Stop predicting
110
111doctags = processor.batch_decode(
112 generated_tokens,
113 skip_special_tokens=False,
114)[0].lstrip()
115
116print(doctags)
117
118doctags_doc = DocTagsDocument.from_doctags_and_image_pairs([doctags], [image])
119print(doctags)
120# create a docling document
121doc = DoclingDocument.load_from_doctags(doctags_doc, document_name="Document")
122
123print(doc.export_to_markdown())
| Description | Instruction | Comment |
| Full conversion | Convert this page to docling. | DocTags represetation |
| Chart | Convert chart to table. | (e.g., <chart>) |
| Formula | Convert formula to LaTeX. | (e.g., <formula>) |
| Code | Convert code to text. | (e.g., <code>) |
| Table | Convert table to OTSL. | (e.g., <otsl>) OTSL: Lysak et al., 2023 |
| Actions and Pipelines | OCR the text in a specific location: <loc_155><loc_233><loc_206><loc_237> | |
| Identify element at: <loc_247><loc_482><10c_252><loc_486> | ||
| Find all 'text' elements on the page, retrieve all section headers. | ||
| Detect footer elements on the page. |
@misc{nassar2025smoldoclingultracompactvisionlanguagemodel,
title={SmolDocling: An ultra-compact vision-language model for end-to-end multi-modal document conversion},
author={Ahmed Nassar and Andres Marafioti and Matteo Omenetti and Maksym Lysak and Nikolaos Livathinos and Christoph Auer and Lucas Morin and Rafael Teixeira de Lima and Yusik Kim and A. Said Gurbuz and Michele Dolfi and Miquel Farré and Peter W. J. Staar},
year={2025},
eprint={2503.11576},
archivePrefix={arXiv},
primaryClass={cs.CV},
url={https://arxiv.org/abs/2503.11576},
}