Views
No views yet

DeepSeek-OCR-Latest-BF16.I64 is an optimized and updated version of the original DeepSeek-OCR. It is an open-source vision-language OCR model designed to extract text from images and scanned documents—including both digital and handwritten content—and can output results as plain text or Markdown. This model leverages a powerful multimodal backbone (3B VLM) to improve reading comprehension and layout understanding for both typed and cursive handwriting. It also excels at preserving document structures such as headings, tables, and lists in its outputs.
transformers: 4.57.1
torch: 2.6.0+cu124 (or) the latest version (i.e., torch 2.9.0)
cuda: 12.4
device: NVIDIA H200 MIG 3g.71gbCurrently supported up to `transformers==4.57.2`. Support for Transformers v5 will be added soon.flash_attention or sdpa—for performance optimization or standardization. Users can also opt out of specific attention implementations if desired.gradio
torch
torchvision
transformers==4.57.1
accelerate
matplotlib
einops
addict
easydict1import gradio as gr
2import torch
3import requests
4from transformers import AutoModel, AutoTokenizer
5from typing import Iterable
6import os
7import tempfile
8from PIL import Image, ImageDraw
9import re
10from gradio.themes import Soft
11from gradio.themes.utils import colors, fonts, sizes
12
13device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
14
15css = """
16#main-title h1 {
17 font-size: 2.3em !important;
18}
19#output-title h2 {
20 font-size: 2.1em !important;
21}
22"""
23
24print("Determining device...")
25device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
26print(f"✅ Using device: {device}")
27
28print("Loading model and tokenizer...")
29model_name = "prithivMLmods/DeepSeek-OCR-Latest-BF16.I64"
30tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)
31
32model = AutoModel.from_pretrained(
33 model_name,
34 #_attn_implementation="flash_attention_2",
35 trust_remote_code=True,
36 use_safetensors=True,
37).to(device).eval() # Move to device and set to eval mode
38
39if device.type == 'cuda':
40 model = model.to(torch.bfloat16)
41
42print("✅ Model loaded successfully to device and in eval mode.")
43
44def find_result_image(path):
45 for filename in os.listdir(path):
46 if "grounding" in filename or "result" in filename:
47 try:
48 image_path = os.path.join(path, filename)
49 return Image.open(image_path)
50 except Exception as e:
51 print(f"Error opening result image {filename}: {e}")
52 return None
53
54def process_ocr_task(image, model_size, task_type, ref_text):
55 """
56 Processes an image with DeepSeek-OCR. The model is already on the correct device.
57 """
58 if image is None:
59 return "Please upload an image first.", None
60
61 print("✅ Model is already on the designated device.")
62
63 with tempfile.TemporaryDirectory() as output_path:
64 # Build the prompt
65 if task_type == "Free OCR":
66 prompt = "<image>\nFree OCR."
67 elif task_type == "Convert to Markdown":
68 prompt = "<image>\n<|grounding|>Convert the document to markdown."
69 elif task_type == "Parse Figure":
70 prompt = "<image>\nParse the figure."
71 elif task_type == "Locate Object by Reference":
72 if not ref_text or ref_text.strip() == "":
73 raise gr.Error("For the 'Locate' task, you must provide the reference text to find!")
74 prompt = f"<image>\nLocate <|ref|>{ref_text.strip()}<|/ref|> in the image."
75 else:
76 prompt = "<image>\nFree OCR."
77
78 temp_image_path = os.path.join(output_path, "temp_image.png")
79 image.save(temp_image_path)
80
81 size_configs = {
82 "Tiny": {"base_size": 512, "image_size": 512, "crop_mode": False},
83 "Small": {"base_size": 640, "image_size": 640, "crop_mode": False},
84 "Base": {"base_size": 1024, "image_size": 1024, "crop_mode": False},
85 "Large": {"base_size": 1280, "image_size": 1280, "crop_mode": False},
86 "Gundam (Recommended)": {"base_size": 1024, "image_size": 640, "crop_mode": True},
87 }
88 config = size_configs.get(model_size, size_configs["Gundam (Recommended)"])
89
90 print(f"🏃 Running inference with prompt: {prompt}")
91 text_result = model.infer(
92 tokenizer,
93 prompt=prompt,
94 image_file=temp_image_path,
95 output_path=output_path,
96 base_size=config["base_size"],
97 image_size=config["image_size"],
98 crop_mode=config["crop_mode"],
99 save_results=True,
100 test_compress=True,
101 eval_mode=True,
102 )
103
104 print(f"====\n📄 Text Result: {text_result}\n====")
105
106 result_image_pil = None
107 pattern = re.compile(r"<\|det\|>\[\[(\d+),\s*(\d+),\s*(\d+),\s*(\d+)\]\]<\|/det\|>")
108 matches = list(pattern.finditer(text_result))
109
110 if matches:
111 print(f"✅ Found {len(matches)} bounding box(es). Drawing on the original image.")
112 image_with_bboxes = image.copy()
113 draw = ImageDraw.Draw(image_with_bboxes)
114 w, h = image.size
115
116 for match in matches:
117 coords_norm = [int(c) for c in match.groups()]
118 x1_norm, y1_norm, x2_norm, y2_norm = coords_norm
119
120 x1 = int(x1_norm / 1000 * w)
121 y1 = int(y1_norm / 1000 * h)
122 x2 = int(x2_norm / 1000 * w)
123 y2 = int(y2_norm / 1000 * h)
124
125 draw.rectangle([x1, y1, x2, y2], outline="red", width=3)
126
127 result_image_pil = image_with_bboxes
128 else:
129 print("⚠️ No bounding box coordinates found in text result. Falling back to search for a result image file.")
130 result_image_pil = find_result_image(output_path)
131
132 return text_result, result_image_pil
133
134with gr.Blocks() as demo:
135 gr.Markdown("# **DeepSeek OCR [exp]**", elem_id="main-title")
136
137 with gr.Row():
138 with gr.Column(scale=1):
139 image_input = gr.Image(type="pil", label="Upload Image", sources=["upload", "clipboard"])
140 model_size = gr.Dropdown(choices=["Tiny", "Small", "Base", "Large", "Gundam (Recommended)"], value="Large", label="Resolution Size")
141 task_type = gr.Dropdown(choices=["Free OCR", "Convert to Markdown", "Parse Figure", "Locate Object by Reference"], value="Convert to Markdown", label="Task Type")
142 ref_text_input = gr.Textbox(label="Reference Text (for Locate task)", placeholder="e.g., the teacher, 20-10, a red car...", visible=False)
143 submit_btn = gr.Button("Process Image", variant="primary")
144
145 with gr.Column(scale=2):
146 output_text = gr.Textbox(label="Output (OCR)", lines=8, show_copy_button=True)
147 output_image = gr.Image(label="Layout Detection (If Any)", type="pil")
148
149 with gr.Accordion("Note", open=False):
150 gr.Markdown("Inference using Huggingface transformers on NVIDIA GPUs. This app is running with transformers version 4.57.1 and torch version 2.6.0.")
151
152 def toggle_ref_text_visibility(task):
153 return gr.Textbox(visible=True) if task == "Locate Object by Reference" else gr.Textbox(visible=False)
154
155 task_type.change(fn=toggle_ref_text_visibility, inputs=task_type, outputs=ref_text_input)
156 submit_btn.click(fn=process_ocr_task, inputs=[image_input, model_size, task_type, ref_text_input], outputs=[output_text, output_image])
157
158if __name__ == "__main__":
159 demo.queue(max_size=20).launch(css=css, share=True, mcp_server=True, ssr_mode=False)| Resource Type | Description | Link |
|---|---|---|
| Original Model Card | Official DeepSeek-OCR release by deepseek-ai | deepseek-ai/DeepSeek-OCR |
| Test Model (StrangerZone HF) | Community test deployment (experimental) | strangervisionhf/deepseek-ocr-latest-transformers |
| Standard Model Card | Optimized version supporting Transformers v4.57.1 (BF16 precision) | DeepSeek-OCR-Latest-BF16.I64 |
| Research Paper | DeepSeek-OCR: Contexts Optical Compression | arXiv:2510.18234 |
| Demo Space | Interactive demo hosted on Hugging Face Spaces | DeepSeek-OCR Experimental Demo |