Skip to content

Add DeepSeek OCR notebook - #576

Merged
morteza89 merged 7 commits into
mainfrom
deepseek-ocr
Sep 15, 2026
Merged

morteza89 merged 7 commits into
mainfrom
deepseek-ocr

Conversation

@morteza89

Copy link
Copy Markdown
Contributor

No description provided.

Comment thread openvino_notebooks/deepseek-ocr/deepencoder.py Fixed
Comment thread openvino_notebooks/deepseek-ocr/deepencoderv2.py Fixed
Comment thread openvino_notebooks/deepseek-ocr/deepencoderv2.py Fixed

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

One or more issues must be addressed before approval.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

Adds an isolated DeepSeek OCR notebook workflow for OpenVINO conversion, inference, quantization, and an interactive Gradio demo.

Changes:

  • Adds model selection, download, conversion, and inference notebook cells.
  • Implements OpenVINO model conversion and runtime helpers.
  • Adds encoder implementations and isolated Python environment configuration.
File summaries
File Description
openvino_notebooks/deepseek-ocr/README.md Updated as part of this pull request.
openvino_notebooks/deepseek-ocr/pyproject.toml Updated as part of this pull request.
openvino_notebooks/deepseek-ocr/ov_deepseek_ocr_helper.py Updated as part of this pull request.
openvino_notebooks/deepseek-ocr/gradio_helper.py Updated as part of this pull request.
openvino_notebooks/deepseek-ocr/deepseek-ocr.ipynb Updated as part of this pull request.
openvino_notebooks/deepseek-ocr/deepencoderv2.py Updated as part of this pull request.
openvino_notebooks/deepseek-ocr/deepencoder.py Updated as part of this pull request.
openvino_notebooks/deepseek-ocr/.python-version Updated as part of this pull request.
openvino_notebooks/deepseek-ocr/.gitignore Updated as part of this pull request.
Review details

Suppressed comments (11)

openvino_notebooks/deepseek-ocr/deepseek-ocr.ipynb:431

  • The notebook text misspells the OpenVINO API as core.complie_model; readers following this description cannot find that method. Correct it to core.compile_model.
    "DeepSeek-OCR is PyTorch model. OpenVINO supports PyTorch models via conversion to OpenVINO Intermediate Representation (IR). [OpenVINO model conversion API](https://docs.openvino.ai/2024/openvino-workflow/model-preparation.html#convert-a-model-with-python-convert-model) should be used for these purposes. `ov.convert_model` function accepts original PyTorch model instance and example input for tracing and returns `ov.Model` representing this model in OpenVINO framework. Converted model can be used for saving on disk using `ov.save_model` function or directly loading on device using `core.complie_model`. \n",

openvino_notebooks/deepseek-ocr/gradio_helper.py:240

  • For an empty PDF, len(doc) - 1 is -1, so this clamp still selects page 0 and load_page(0) raises. Handle zero-page PDFs before clamping/loading and avoid exposing a 1-based selector for a document with no pages.
            page_idx = max(0, min(int(page_num) - 1, len(doc) - 1))
            page = doc.load_page(page_idx)

openvino_notebooks/deepseek-ocr/gradio_helper.py:78

  • Model-generated <|det|> contents are parsed without validation; a malformed coordinate payload makes ast.literal_eval raise and aborts the whole Gradio request. Parse each reference defensively and skip invalid boxes, as the notebook helper does.
            coords = ast.literal_eval(ref[2])

openvino_notebooks/deepseek-ocr/gradio_helper.py:24

  • These presets are not all valid for OVDeepseekOCR2ForCausalLM: its extract_image_features accepts only 144 or 256 queries, while 512/640/1280 inputs produce 64/100/400 queries and raise ValueError. Since this demo is used with either model variant, make the dropdown model-specific or restrict it to dimensions supported by the loaded model.
    "Gundam": {"base_size": 1024, "image_size": 640, "crop_mode": True},
    "Tiny": {"base_size": 512, "image_size": 512, "crop_mode": False},
    "Small": {"base_size": 640, "image_size": 640, "crop_mode": False},
    "Base": {"base_size": 1024, "image_size": 1024, "crop_mode": False},
    "Large": {"base_size": 1280, "image_size": 1280, "crop_mode": False},

openvino_notebooks/deepseek-ocr/ov_deepseek_ocr2_helper.py:1460

  • dynamic_preprocess is called without image_size, so it always creates 768×768 local tiles, while the token sequence below uses the caller's image_size (the default is 640). For a high-resolution image this produces 144 local feature vectors but only 100 image-token slots, causing masked_scatter_ to fail. Keep preprocessing and token counting tied to the same supported tile size and validate that size.
                        images_crop_raw, crop_ratio = dynamic_preprocess(image)

openvino_notebooks/deepseek-ocr/ov_deepseek_ocr2_helper.py:335

  • The no-normalization branch calls nn.Identity(), but this module never imports nn; constructing BasicImageTransform(..., normalize=False) therefore raises NameError. Use None for the no-op branch (the following condition already omits it) or import torch.nn as nn.
        normalize = normalize_transform(mean, std) if normalize else nn.Identity()

openvino_notebooks/deepseek-ocr/ov_deepseek_ocr2_helper.py:1377

  • infer defaults output_path to an empty string and then calls os.makedirs(output_path, exist_ok=True), which raises FileNotFoundError when callers rely on the default. Use output_path="." as the default or guard the directory creation.
        output_path="",

openvino_notebooks/deepseek-ocr/ov_deepseek_ocr2_helper.py:1430

  • The elif prompt branch creates a conversation without images, so load_pil_images returns an empty list; the next images[0] access then always raises IndexError for the text-only call path. Reject missing image_file before this branch or implement a real text-only path.
        image_draw = images[0].copy()

openvino_notebooks/deepseek-ocr/ov_deepseek_ocr_helper.py:735

  • nncf.compress_weights returns the compressed ov.Model, but its return value is discarded here before saving. As a result, the requested vision INT8 compression is not included in the saved IR; the language-model path below correctly assigns the return value.
            nncf.compress_weights(ov_model, **quantization_config["vision"])

openvino_notebooks/deepseek-ocr/ov_deepseek_ocr_helper.py:1269

  • infer defaults output_path to an empty string and then calls os.makedirs(output_path, exist_ok=True), which raises FileNotFoundError when callers rely on the default. Use output_path="." as the default or guard the directory creation.
        output_path="",

openvino_notebooks/deepseek-ocr/ov_deepseek_ocr_helper.py:1322

  • The elif prompt branch creates a conversation without images, so load_pil_images returns an empty list; the next images[0] access then always raises IndexError for the text-only call path. Reject missing image_file before this branch or implement a real text-only path.
        image_draw = images[0].copy()
  • Files reviewed: 10/11 changed files
  • Comments generated: 7
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread openvino_notebooks/deepseek-ocr/deepseek-ocr.ipynb Outdated
Comment on lines +47 to +48
with requests.get(url, stream=True, timeout=30) as response:
response.raise_for_status()
Comment on lines +159 to +160
stdout = sys.stdout
sys.stdout = StringIO()
Comment thread openvino_notebooks/deepseek-ocr/ov_deepseek_ocr_helper.py Outdated

transform_pipelines = [transforms.ToTensor()]

normalize = normalize_transform(mean, std) if normalize else nn.Identity()
self.token_emb_request = None
self._device = device.upper()
self.device = torch.device("cpu")
self.ov_config = {"KV_CACHE_PRECISION": "f32", "DYNAMIC_QUANTIZATION_GROUP_SIZE": "0"}
Comment thread openvino_notebooks/deepseek-ocr/README.md Outdated
morteza89 and others added 3 commits September 14, 2026 15:09
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI and others added 2 commits September 14, 2026 22:15
Co-authored-by: morteza89 <51894034+morteza89@users.noreply.github.com>
Co-authored-by: morteza89 <51894034+morteza89@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@morteza89
morteza89 merged commit 676fd32 into main Sep 15, 2026
3 checks passed
@morteza89
morteza89 deleted the deepseek-ocr branch September 15, 2026 15:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants