numb3r3 commited on
Commit
10de024
·
verified ·
1 Parent(s): 2a6c30a

trim unused model param tensors

Browse files
.eval_results/olmocrbench.yaml ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ - dataset:
2
+ id: allenai/olmOCR-bench
3
+ task_id: overall
4
+ value: 83.4
5
+ source:
6
+ url: https://huggingface.co/papers/2609.03181
7
+ name: Jina-OCR-v1 technical report
8
+ user: jinaai
9
+ - dataset:
10
+ id: allenai/olmOCR-bench
11
+ task_id: arxiv_math
12
+ value: 86.1
13
+ source:
14
+ url: https://huggingface.co/papers/2609.03181
15
+ name: Jina-OCR-v1 technical report
16
+ user: jinaai
17
+ - dataset:
18
+ id: allenai/olmOCR-bench
19
+ task_id: old_scans_math
20
+ value: 82.3
21
+ source:
22
+ url: https://huggingface.co/papers/2609.03181
23
+ name: Jina-OCR-v1 technical report
24
+ user: jinaai
25
+ - dataset:
26
+ id: allenai/olmOCR-bench
27
+ task_id: table_tests
28
+ value: 88.8
29
+ source:
30
+ url: https://huggingface.co/papers/2609.03181
31
+ name: Jina-OCR-v1 technical report
32
+ user: jinaai
33
+ - dataset:
34
+ id: allenai/olmOCR-bench
35
+ task_id: old_scans
36
+ value: 42.6
37
+ source:
38
+ url: https://huggingface.co/papers/2609.03181
39
+ name: Jina-OCR-v1 technical report
40
+ user: jinaai
41
+ - dataset:
42
+ id: allenai/olmOCR-bench
43
+ task_id: multi_column
44
+ value: 85.5
45
+ source:
46
+ url: https://huggingface.co/papers/2609.03181
47
+ name: Jina-OCR-v1 technical report
48
+ user: jinaai
49
+ - dataset:
50
+ id: allenai/olmOCR-bench
51
+ task_id: long_tiny_text
52
+ value: 93.2
53
+ source:
54
+ url: https://huggingface.co/papers/2609.03181
55
+ name: Jina-OCR-v1 technical report
56
+ user: jinaai
57
+ - dataset:
58
+ id: allenai/olmOCR-bench
59
+ task_id: headers_footers
60
+ value: 88.7
61
+ source:
62
+ url: https://huggingface.co/papers/2609.03181
63
+ name: Jina-OCR-v1 technical report
64
+ user: jinaai
65
+ - dataset:
66
+ id: allenai/olmOCR-bench
67
+ task_id: baseline
68
+ value: 99.9
69
+ source:
70
+ url: https://huggingface.co/papers/2609.03181
71
+ name: Jina-OCR-v1 technical report
72
+ user: jinaai
README.md CHANGED
@@ -3,15 +3,39 @@ library_name: transformers
3
  pipeline_tag: image-text-to-text
4
  license: cc-by-nc-4.0
5
  language:
6
- - multilingual
7
  tags:
8
- - multimodal
9
- - multilingual
10
- - ocr
11
- - vision-language
 
12
  base_model:
13
- - deepseek-ai/DeepSeek-OCR
14
  inference: false
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  ---
16
 
17
  <p align="center">
@@ -20,38 +44,32 @@ inference: false
20
 
21
  # Jina-OCR-v1: Efficient Document Parsing with Speculative Decoding and Reward-Dense Post-Training
22
 
23
- [Blog](#) | [API](https://jina.ai) | AWS | Azure | GCP | [Arxiv](#)
24
 
25
- `jina-ocr-v1` is an end-to-end document parsing model designed for high-quality OCR at an *efficient serving point*. The model builds on `DeepSeek-OCR` and inherits two of its efficiency-oriented components: a **DeepEncoder** vision tower that represents a **1024×1024** global view with **256 visual tokens** and augments it with dynamic local tiles, and a **3B-parameter mixture-of-experts** decoder with approximately **570M active parameters** per token. On top of this backbone, we add a **FastMTP** speculative decoding head that recursively shares one dense draft block across **K=3** prediction steps. *Greedy verification* accepts the longest token-equality prefix, preserving the verifier’s greedy output sequence *by construction*.
26
 
27
  This repository ships the model weights **and** the custom code needed to load them (`trust_remote_code=True`). There is no separate training or serving package to install. Transformers uses the modeling files in this snapshot; vLLM needs a one-time architecture registration from `deepseek_ocr_mtp.py` (see [Using vLLM](#vllm-fastmtp)). A single script covers both backends: [`example.py`](example.py).
28
 
29
- | | |
30
- |---|---|
31
- | Backbone | DeepSeek-OCR (DeepEncoder + 3B MoE, ~570M active) |
32
- | Acceleration | FastMTP, one dense draft head, K=3 (vLLM only) |
33
- | Local run | [`example.py`](example.py) — Transformers or vLLM |
34
- | Hosted | OpenAI-compatible `https://api.jina.ai/v1/chat/completions` |
35
 
36
  ```bash
37
  python example.py --backend transformers --image document.png
38
  python example.py --backend vllm --image document.png
39
  ```
40
 
41
-
42
  ## Prompt
43
 
44
  ```text
45
  Transcribe the provided document image into a clean Markdown format, preserving the natural reading order.
46
- Convert all formulas into LaTeX format. Inline formulas should be enclosed in `$ $`. Display (block) formulas should be enclosed in `$$ $$`.
47
- Convert tables into HTML format (using <table border="1"><tr><td> tags).
48
- Ignore all graphical content in the image document. Do not attempt to describe or convert the images.
49
- Remove the headers and footers, but keep references and footnotes.
50
  ```
51
 
52
  Imported as `DEFAULT_OCR_PROMPT` from `deepseek_ocr_mtp.py` / the processor.
53
 
54
-
55
  ## Hosted API
56
 
57
  Key from [jina.ai](https://jina.ai). Image URL or `data:image/...;base64,...`. Add `"stream": true` to stream.
@@ -80,7 +98,6 @@ Local file:
80
 
81
  A cold start returns HTTP 503 — retry after 30–60s.
82
 
83
-
84
  ## Transformers
85
 
86
  Install `transformers`, `torch`, `torchvision`, `Pillow`. One PIL image per call. `eos` / `pad` come from `generation_config.json`; do not pass a fresh `GenerationConfig`.
@@ -106,8 +123,9 @@ print(processor.decode_ocr(output, inputs['input_ids']))
106
 
107
  `prepare_ocr_inputs(image, prompt=..., device=...)` overrides the default prompt.
108
 
109
- **No FastMTP here.** `generate()` is the 3B MoE decoder only. MTP keys (`mtp_module.*`, `mtp_embed_tokens.*`) are ignored on load.
110
 
 
111
 
112
  ## vLLM (FastMTP)
113
 
@@ -117,12 +135,12 @@ Requires [vLLM](https://github.com/vllm-project/vllm) ≥ 0.21. Call `register()
117
  import sys
118
  from huggingface_hub import snapshot_download
119
  from PIL import Image
120
- from vllm import LLM, SamplingParams
121
 
122
  sys.path.insert(0, snapshot_download('jinaai/jina-ocr-v1'))
123
  # local checkout: sys.path.insert(0, '/path/to/jina-ocr-v1')
124
 
125
- from deepseek_ocr_mtp import DEFAULT_OCR_PROMPT, log_spec_stats, register, vllm_llm_kwargs
126
 
127
  register()
128
 
@@ -144,7 +162,7 @@ outputs = llm.chat(
144
  {'type': 'text', 'text': DEFAULT_OCR_PROMPT},
145
  ],
146
  }],
147
- sampling_params=SamplingParams(temperature=0.0, max_tokens=4096, repetition_penalty=1.05),
148
  )
149
  log_spec_stats(llm)
150
  print(outputs[0].outputs[0].text)
@@ -152,22 +170,23 @@ print(outputs[0].outputs[0].text)
152
 
153
  `vllm_llm_kwargs()` sets `trust_remote_code`, the OCR architecture override, and `speculative_config.method="eagle"`. FastMTP was trained with recursive hidden-state feedback; vLLM's default `method="mtp"` re-grounds every draft step on the target and breaks that. `register()` also maps `EagleDeepSeekMTPModel` (vLLM prepends `Eagle` when `method="eagle"`).
154
 
 
 
155
  `log_spec_stats(llm)` flushes `SpecDecoding metrics` after a short run — vLLM otherwise prints them on a ~10s interval.
156
 
157
  Chat content types `image`, `image_pil`, and `image_url` all insert `<image>`. Do not pass `use_fast=False`; this checkpoint is `LlamaTokenizerFast`.
158
 
159
-
160
  ## Citation
161
 
162
  ```bibtex
163
- @misc{wang2026jinaocr,
164
- title={Jina-OCR-v1: Efficient Document Parsing with Speculative Decoding and Reward-Dense Post-Training},
165
- author={Feng Wang and Alejandro Barón García and Emilia Garcia Casademont and Han Xiao},
166
  year={2026},
167
- eprint={xxx},
168
  archivePrefix={arXiv},
169
  primaryClass={cs.CL},
170
- url={#},
171
  }
172
  ```
173
 
 
3
  pipeline_tag: image-text-to-text
4
  license: cc-by-nc-4.0
5
  language:
6
+ - multilingual
7
  tags:
8
+ - multimodal
9
+ - multilingual
10
+ - ocr
11
+ - vision-language
12
+ - document-intelligence
13
  base_model:
14
+ - deepseek-ai/DeepSeek-OCR
15
  inference: false
16
+ model-index:
17
+ - name: Jina-OCR-v1
18
+ results:
19
+ - task:
20
+ type: document-parsing
21
+ name: Document Parsing
22
+ dataset:
23
+ name: OmniDocBench v1.6
24
+ type: opendatalab/OmniDocBench
25
+ metrics:
26
+ - type: overall
27
+ value: 91.14
28
+ name: Overall Score
29
+ - task:
30
+ type: ocr
31
+ name: OCR
32
+ dataset:
33
+ name: OlmOCR Bench
34
+ type: allenai/olmOCR-bench
35
+ metrics:
36
+ - type: accuracy
37
+ value: 83.4
38
+ name: Overall Score
39
  ---
40
 
41
  <p align="center">
 
44
 
45
  # Jina-OCR-v1: Efficient Document Parsing with Speculative Decoding and Reward-Dense Post-Training
46
 
47
+ [Blog](#) | [API](https://jina.ai) | AWS | Azure | GCP | [Arxiv](https://arxiv.org/abs/2609.03181)
48
 
49
+ `jina-ocr-v1` is an end-to-end document parsing model designed for high-quality OCR at an _efficient serving point_. The model builds on `DeepSeek-OCR` and inherits two of its efficiency-oriented components: a **DeepEncoder** vision tower that represents a **1024×1024** global view with **256 visual tokens** and augments it with dynamic local tiles, and a **3B-parameter mixture-of-experts** decoder with approximately **570M active parameters** per token. On top of this backbone, we add a **FastMTP** speculative decoding head that recursively shares one dense draft block across **K=3** prediction steps. _Greedy verification_ accepts the longest token-equality prefix, preserving the verifier’s greedy output sequence _by construction_.
50
 
51
  This repository ships the model weights **and** the custom code needed to load them (`trust_remote_code=True`). There is no separate training or serving package to install. Transformers uses the modeling files in this snapshot; vLLM needs a one-time architecture registration from `deepseek_ocr_mtp.py` (see [Using vLLM](#vllm-fastmtp)). A single script covers both backends: [`example.py`](example.py).
52
 
53
+ | | |
54
+ | ------------ | ----------------------------------------------------------- |
55
+ | Backbone | DeepSeek-OCR (DeepEncoder + 3B MoE, ~570M active) |
56
+ | Acceleration | FastMTP, one dense draft head, K=3 (vLLM only) |
57
+ | Local run | [`example.py`](example.py) — Transformers or vLLM |
58
+ | Hosted | OpenAI-compatible `https://api.jina.ai/v1/chat/completions` |
59
 
60
  ```bash
61
  python example.py --backend transformers --image document.png
62
  python example.py --backend vllm --image document.png
63
  ```
64
 
 
65
  ## Prompt
66
 
67
  ```text
68
  Transcribe the provided document image into a clean Markdown format, preserving the natural reading order.
 
 
 
 
69
  ```
70
 
71
  Imported as `DEFAULT_OCR_PROMPT` from `deepseek_ocr_mtp.py` / the processor.
72
 
 
73
  ## Hosted API
74
 
75
  Key from [jina.ai](https://jina.ai). Image URL or `data:image/...;base64,...`. Add `"stream": true` to stream.
 
98
 
99
  A cold start returns HTTP 503 — retry after 30–60s.
100
 
 
101
  ## Transformers
102
 
103
  Install `transformers`, `torch`, `torchvision`, `Pillow`. One PIL image per call. `eos` / `pad` come from `generation_config.json`; do not pass a fresh `GenerationConfig`.
 
123
 
124
  `prepare_ocr_inputs(image, prompt=..., device=...)` overrides the default prompt.
125
 
126
+ `generate()` attaches `SlidingWindowNoRepeatNgramProcessor` with defaults `no_repeat_ngram_size=35`, `ngram_window=1024`, and whitelist `{128821, 128822}` (`<td>`, `</td>`). Override with those keyword arguments, or disable with `no_repeat_ngram_size=0`.
127
 
128
+ **No FastMTP here.** `generate()` is the 3B MoE decoder only. MTP keys (`mtp_module.*`, `mtp_embed_tokens.*`) are ignored on load.
129
 
130
  ## vLLM (FastMTP)
131
 
 
135
  import sys
136
  from huggingface_hub import snapshot_download
137
  from PIL import Image
138
+ from vllm import LLM
139
 
140
  sys.path.insert(0, snapshot_download('jinaai/jina-ocr-v1'))
141
  # local checkout: sys.path.insert(0, '/path/to/jina-ocr-v1')
142
 
143
+ from deepseek_ocr_mtp import DEFAULT_OCR_PROMPT, log_spec_stats, register, vllm_llm_kwargs, vllm_sampling_params
144
 
145
  register()
146
 
 
162
  {'type': 'text', 'text': DEFAULT_OCR_PROMPT},
163
  ],
164
  }],
165
+ sampling_params=vllm_sampling_params(max_tokens=4096),
166
  )
167
  log_spec_stats(llm)
168
  print(outputs[0].outputs[0].text)
 
170
 
171
  `vllm_llm_kwargs()` sets `trust_remote_code`, the OCR architecture override, and `speculative_config.method="eagle"`. FastMTP was trained with recursive hidden-state feedback; vLLM's default `method="mtp"` re-grounds every draft step on the target and breaks that. `register()` also maps `EagleDeepSeekMTPModel` (vLLM prepends `Eagle` when `method="eagle"`).
172
 
173
+ `vllm_sampling_params()` sets `temperature=0.0`, `repetition_penalty=1.05`, and `repetition_detection` (`max_pattern_size=35`, `min_pattern_size=35`, `min_count=10`). That uses vLLM's built-in n-gram stop instead of a custom logits processor, so it works with FastMTP. Pass `repetition_detection=None` to disable.
174
+
175
  `log_spec_stats(llm)` flushes `SpecDecoding metrics` after a short run — vLLM otherwise prints them on a ~10s interval.
176
 
177
  Chat content types `image`, `image_pil`, and `image_url` all insert `<image>`. Do not pass `use_fast=False`; this checkpoint is `LlamaTokenizerFast`.
178
 
 
179
  ## Citation
180
 
181
  ```bibtex
182
+ @misc{garcía2026jinaocr,
183
+ title={Jina-OCR-v1: Efficient Document Parsing with Speculative Decoding and Dense Verifiable Rewards},
184
+ author={Alejandro Barón García and Feng Wang and Emilia Garcia Casademont and Han Xiao},
185
  year={2026},
186
+ eprint={2609.03181},
187
  archivePrefix={arXiv},
188
  primaryClass={cs.CL},
189
+ url={https://arxiv.org/abs/2609.03181},
190
  }
191
  ```
192
 
deepseek_ocr_mtp.py CHANGED
@@ -42,7 +42,7 @@ _STACKED_PARAMS = [
42
  ("gate_up_proj", "up_proj", 1),
43
  ("qkv_proj", "q_proj", "q"),
44
  ("qkv_proj", "k_proj", "k"),
45
- ("qkv_proj", "v_proj", "v")
46
  ]
47
 
48
 
@@ -148,7 +148,6 @@ class DeepSeekOCRMultiTokenPredictor(DeepSeekMultiTokenPredictor):
148
  return logits
149
 
150
 
151
-
152
  # This file postpones annotations, so vLLM cannot infer dims from live
153
  # types. Pass them explicitly or class import raises.
154
  @support_torch_compile(
@@ -321,9 +320,7 @@ _OURS = {
321
  }
322
 
323
  _NESTED_TEXT_CONFIG_KEYS = ("text_config", "language_config")
324
- _NESTED_TEXT_SKIP = frozenset(
325
- (*_NESTED_TEXT_CONFIG_KEYS, "vision_config", "projector_config", "auto_map")
326
- )
327
 
328
 
329
  def _flatten_nested_text_config(hf_config) -> None:
@@ -403,6 +400,38 @@ def register() -> None:
403
  _registered = True
404
 
405
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
406
  def vllm_llm_kwargs(
407
  model: str,
408
  *,
@@ -417,6 +446,8 @@ def vllm_llm_kwargs(
417
 
418
  FastMTP (``mtp_recursive=True``) sets ``speculative_config.method="eagle"``
419
  so each draft step consumes the previous step's hidden state.
 
 
420
  """
421
  kwargs = {
422
  "model": model,
@@ -461,12 +492,7 @@ def log_spec_stats(llm) -> None:
461
 
462
  DEFAULT_OCR_PROMPT = (
463
  "Transcribe the provided document image into a clean Markdown format, "
464
- "preserving the natural reading order.\n"
465
- "Convert all formulas into LaTeX format. Inline formulas should be enclosed in `$ $`. "
466
- "Display (block) formulas should be enclosed in `$$ $$`.\n"
467
- 'Convert tables into HTML format (using <table border="1"><tr><td> tags).\n'
468
- "Ignore all graphical content in the image document. Do not attempt to describe or convert the images.\n"
469
- "Remove the headers and footers, but keep references and footnotes."
470
  )
471
 
472
 
 
42
  ("gate_up_proj", "up_proj", 1),
43
  ("qkv_proj", "q_proj", "q"),
44
  ("qkv_proj", "k_proj", "k"),
45
+ ("qkv_proj", "v_proj", "v"),
46
  ]
47
 
48
 
 
148
  return logits
149
 
150
 
 
151
  # This file postpones annotations, so vLLM cannot infer dims from live
152
  # types. Pass them explicitly or class import raises.
153
  @support_torch_compile(
 
320
  }
321
 
322
  _NESTED_TEXT_CONFIG_KEYS = ("text_config", "language_config")
323
+ _NESTED_TEXT_SKIP = frozenset((*_NESTED_TEXT_CONFIG_KEYS, "vision_config", "projector_config", "auto_map"))
 
 
324
 
325
 
326
  def _flatten_nested_text_config(hf_config) -> None:
 
400
  _registered = True
401
 
402
 
403
+ def _default_repetition_detection():
404
+ """Built-in n-gram loop stopper; works with FastMTP (custom logits processors do not)."""
405
+ try:
406
+ from vllm.sampling_params import RepetitionDetectionParams
407
+ except ImportError:
408
+ return None
409
+ return RepetitionDetectionParams(
410
+ max_pattern_size=35,
411
+ min_pattern_size=35,
412
+ min_count=10,
413
+ )
414
+
415
+
416
+ def vllm_sampling_params(**kwargs):
417
+ """``SamplingParams`` with OCR defaults. Pass ``repetition_detection=None`` to disable."""
418
+ from vllm import SamplingParams
419
+
420
+ kwargs.setdefault("temperature", 0.0)
421
+ kwargs.setdefault("repetition_penalty", 1.05)
422
+ if "repetition_detection" not in kwargs:
423
+ detection = _default_repetition_detection()
424
+ if detection is not None:
425
+ kwargs["repetition_detection"] = detection
426
+ try:
427
+ return SamplingParams(**kwargs)
428
+ except TypeError as exc:
429
+ if "repetition_detection" in kwargs and "repetition_detection" in str(exc):
430
+ kwargs.pop("repetition_detection")
431
+ return SamplingParams(**kwargs)
432
+ raise
433
+
434
+
435
  def vllm_llm_kwargs(
436
  model: str,
437
  *,
 
446
 
447
  FastMTP (``mtp_recursive=True``) sets ``speculative_config.method="eagle"``
448
  so each draft step consumes the previous step's hidden state.
449
+ Use ``vllm_sampling_params()`` for n-gram repetition detection; vLLM rejects
450
+ custom logits processors while speculative decoding is enabled.
451
  """
452
  kwargs = {
453
  "model": model,
 
492
 
493
  DEFAULT_OCR_PROMPT = (
494
  "Transcribe the provided document image into a clean Markdown format, "
495
+ "preserving the natural reading order."
 
 
 
 
 
496
  )
497
 
498
 
example.py CHANGED
@@ -40,9 +40,14 @@ def run_vllm(
40
  max_new_tokens: int,
41
  num_speculative_tokens: int,
42
  ) -> str:
43
- from vllm import LLM, SamplingParams
44
-
45
- from deepseek_ocr_mtp import DEFAULT_OCR_PROMPT, log_spec_stats, register, vllm_llm_kwargs
 
 
 
 
 
46
 
47
  register()
48
  llm = LLM(
@@ -64,7 +69,7 @@ def run_vllm(
64
  ]
65
  outputs = llm.chat(
66
  messages,
67
- sampling_params=SamplingParams(temperature=0.0, max_tokens=max_new_tokens, repetition_penalty=1.05),
68
  )
69
  if num_speculative_tokens > 0:
70
  log_spec_stats(llm)
 
40
  max_new_tokens: int,
41
  num_speculative_tokens: int,
42
  ) -> str:
43
+ from deepseek_ocr_mtp import (
44
+ DEFAULT_OCR_PROMPT,
45
+ log_spec_stats,
46
+ register,
47
+ vllm_llm_kwargs,
48
+ vllm_sampling_params,
49
+ )
50
+ from vllm import LLM
51
 
52
  register()
53
  llm = LLM(
 
69
  ]
70
  outputs = llm.chat(
71
  messages,
72
+ sampling_params=vllm_sampling_params(max_tokens=max_new_tokens),
73
  )
74
  if num_speculative_tokens > 0:
75
  log_spec_stats(llm)
model-00002-of-00002.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:71a318aefacd340c3fdbc478b222988ea21ea8eec7488eb4ca9dff9c6867394a
3
- size 3113227120
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:809f8de9023bb5217d0aa396deb9e093f89862e85d66a28720bad1a6627f86e5
3
+ size 2451310608
model.safetensors.index.json CHANGED
@@ -1,6 +1,6 @@
1
  {
2
  "metadata": {
3
- "total_size": 7406392320
4
  },
5
  "weight_map": {
6
  "lm_head.weight": "model-00001-of-00002.safetensors",
@@ -2713,7 +2713,6 @@
2713
  "model.vision_model.transformer.layers.9.self_attn.out_proj.weight": "model-00002-of-00002.safetensors",
2714
  "model.vision_model.transformer.layers.9.self_attn.qkv_proj.bias": "model-00002-of-00002.safetensors",
2715
  "model.vision_model.transformer.layers.9.self_attn.qkv_proj.weight": "model-00002-of-00002.safetensors",
2716
- "mtp_embed_tokens.weight": "model-00002-of-00002.safetensors",
2717
  "mtp_module.heads.0.eh_proj.weight": "model-00002-of-00002.safetensors",
2718
  "mtp_module.heads.0.enorm.weight": "model-00002-of-00002.safetensors",
2719
  "mtp_module.heads.0.hnorm.weight": "model-00002-of-00002.safetensors",
@@ -2725,8 +2724,6 @@
2725
  "mtp_module.heads.0.mtp_block.self_attn.k_proj.weight": "model-00002-of-00002.safetensors",
2726
  "mtp_module.heads.0.mtp_block.self_attn.o_proj.weight": "model-00002-of-00002.safetensors",
2727
  "mtp_module.heads.0.mtp_block.self_attn.q_proj.weight": "model-00002-of-00002.safetensors",
2728
- "mtp_module.heads.0.mtp_block.self_attn.v_proj.weight": "model-00002-of-00002.safetensors",
2729
- "mtp_module.heads.0.shared_head.local_head.weight": "model-00002-of-00002.safetensors",
2730
- "mtp_module.heads.0.shared_head.norm.weight": "model-00002-of-00002.safetensors"
2731
  }
2732
- }
 
1
  {
2
  "metadata": {
3
+ "total_size": 6744476160
4
  },
5
  "weight_map": {
6
  "lm_head.weight": "model-00001-of-00002.safetensors",
 
2713
  "model.vision_model.transformer.layers.9.self_attn.out_proj.weight": "model-00002-of-00002.safetensors",
2714
  "model.vision_model.transformer.layers.9.self_attn.qkv_proj.bias": "model-00002-of-00002.safetensors",
2715
  "model.vision_model.transformer.layers.9.self_attn.qkv_proj.weight": "model-00002-of-00002.safetensors",
 
2716
  "mtp_module.heads.0.eh_proj.weight": "model-00002-of-00002.safetensors",
2717
  "mtp_module.heads.0.enorm.weight": "model-00002-of-00002.safetensors",
2718
  "mtp_module.heads.0.hnorm.weight": "model-00002-of-00002.safetensors",
 
2724
  "mtp_module.heads.0.mtp_block.self_attn.k_proj.weight": "model-00002-of-00002.safetensors",
2725
  "mtp_module.heads.0.mtp_block.self_attn.o_proj.weight": "model-00002-of-00002.safetensors",
2726
  "mtp_module.heads.0.mtp_block.self_attn.q_proj.weight": "model-00002-of-00002.safetensors",
2727
+ "mtp_module.heads.0.mtp_block.self_attn.v_proj.weight": "model-00002-of-00002.safetensors"
 
 
2728
  }
2729
+ }
modeling_deepseekocr.py CHANGED
@@ -7,7 +7,7 @@ import torch.nn as nn
7
  from PIL import Image, ImageDraw, ImageFont, ImageOps
8
  from torch.nn import CrossEntropyLoss
9
  from tqdm import tqdm
10
- from transformers import TextStreamer
11
  from transformers.modeling_outputs import BaseModelOutputWithPast, MoeCausalLMOutputWithPast
12
  from transformers.utils import logging
13
 
@@ -33,6 +33,7 @@ class CausalLMOutputWithPastForMTP(MoeCausalLMOutputWithPast):
33
  position_ids: Optional[torch.Tensor] = None
34
  mtp_hidden_states: Optional[list[torch.Tensor]] = None
35
 
 
36
  class NoEOSTextStreamer(TextStreamer):
37
  def on_finalized_text(self, text: str, stream_end: bool = False):
38
 
@@ -41,6 +42,44 @@ class NoEOSTextStreamer(TextStreamer):
41
  print(text, flush=True, end="")
42
 
43
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  class DeepseekOCRConfig(DeepseekV2Config):
45
  model_type = "deepseek_vl_v2"
46
 
@@ -392,6 +431,26 @@ class DeepseekOCRForCausalLM(DeepseekV2ForCausalLM):
392
  def prepare_inputs_for_generation(self, input_ids, **kwargs):
393
  return _prepare_inputs_for_generation(self, input_ids, **kwargs)
394
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
395
  def disable_torch_init(self):
396
  """
397
  Disable the redundant torch default initialization to accelerate model creation.
 
7
  from PIL import Image, ImageDraw, ImageFont, ImageOps
8
  from torch.nn import CrossEntropyLoss
9
  from tqdm import tqdm
10
+ from transformers import LogitsProcessorList, TextStreamer
11
  from transformers.modeling_outputs import BaseModelOutputWithPast, MoeCausalLMOutputWithPast
12
  from transformers.utils import logging
13
 
 
33
  position_ids: Optional[torch.Tensor] = None
34
  mtp_hidden_states: Optional[list[torch.Tensor]] = None
35
 
36
+
37
  class NoEOSTextStreamer(TextStreamer):
38
  def on_finalized_text(self, text: str, stream_end: bool = False):
39
 
 
42
  print(text, flush=True, end="")
43
 
44
 
45
+ # Match Unlimited-OCR generate() defaults.
46
+ _DEFAULT_NGRAM_SIZE = 35
47
+ _DEFAULT_NGRAM_WINDOW = 1024
48
+ _DEFAULT_NGRAM_WHITELIST = frozenset({128821, 128822}) # <td>, </td>
49
+
50
+
51
+ class SlidingWindowNoRepeatNgramProcessor:
52
+ """Ban tokens that would complete an n-gram already seen in the last ``window`` tokens."""
53
+
54
+ def __init__(self, ngram_size, window, whitelist_token_ids=None):
55
+ self.ngram_size = ngram_size
56
+ self.window = window
57
+ self.whitelist = set(whitelist_token_ids) if whitelist_token_ids else set()
58
+
59
+ def __call__(self, input_ids, scores):
60
+ for batch_idx in range(input_ids.shape[0]):
61
+ sequence = input_ids[batch_idx].tolist()
62
+ if len(sequence) < self.ngram_size:
63
+ continue
64
+ search_start = max(0, len(sequence) - self.window)
65
+ search_end = len(sequence) - self.ngram_size + 1
66
+ if search_end <= search_start:
67
+ continue
68
+ if self.ngram_size > 1:
69
+ current_prefix = tuple(sequence[-(self.ngram_size - 1) :])
70
+ else:
71
+ current_prefix = tuple()
72
+ banned = set()
73
+ for idx in range(search_start, search_end):
74
+ ngram = sequence[idx : idx + self.ngram_size]
75
+ if self.ngram_size == 1 or tuple(ngram[:-1]) == current_prefix:
76
+ banned.add(ngram[-1])
77
+ banned.difference_update(self.whitelist)
78
+ for token_id in banned:
79
+ scores[batch_idx, token_id] = float("-inf")
80
+ return scores
81
+
82
+
83
  class DeepseekOCRConfig(DeepseekV2Config):
84
  model_type = "deepseek_vl_v2"
85
 
 
431
  def prepare_inputs_for_generation(self, input_ids, **kwargs):
432
  return _prepare_inputs_for_generation(self, input_ids, **kwargs)
433
 
434
+ def generate(self, *args, **kwargs):
435
+ ngram_size = kwargs.pop("no_repeat_ngram_size", _DEFAULT_NGRAM_SIZE)
436
+ window_size = kwargs.pop("ngram_window", _DEFAULT_NGRAM_WINDOW)
437
+ whitelist_token_ids = kwargs.pop("whitelist_token_ids", _DEFAULT_NGRAM_WHITELIST)
438
+ processors = kwargs.get("logits_processor")
439
+ if processors is None:
440
+ processors = LogitsProcessorList()
441
+ elif not isinstance(processors, (list, tuple)):
442
+ processors = LogitsProcessorList([processors])
443
+ else:
444
+ processors = LogitsProcessorList(processors)
445
+ already = any(isinstance(p, SlidingWindowNoRepeatNgramProcessor) for p in processors)
446
+ if ngram_size and window_size and not already:
447
+ processors.append(
448
+ SlidingWindowNoRepeatNgramProcessor(ngram_size, window_size, whitelist_token_ids)
449
+ )
450
+ if processors:
451
+ kwargs["logits_processor"] = processors
452
+ return super().generate(*args, **kwargs)
453
+
454
  def disable_torch_init(self):
455
  """
456
  Disable the redundant torch default initialization to accelerate model creation.
modeling_deepseekv2.py CHANGED
@@ -1214,9 +1214,7 @@ class _LlamaRotaryEmbedding(nn.Module):
1214
  seq_len = x.shape[-2]
1215
  if position_ids is None or position_ids.dim() != 2:
1216
  position_ids = torch.arange(seq_len, device=x.device).unsqueeze(0)
1217
- inv_freq = 1.0 / (
1218
- self.base ** (torch.arange(0, self.dim, 2, device=x.device, dtype=torch.float32) / self.dim)
1219
- )
1220
  inv_freq_expanded = inv_freq[None, :, None].expand(position_ids.shape[0], -1, 1)
1221
  position_ids_expanded = position_ids[:, None, :].to(dtype=torch.float32)
1222
  freqs = (inv_freq_expanded @ position_ids_expanded).transpose(1, 2)
@@ -1905,7 +1903,7 @@ class DeepseekV2Model(DeepseekV2PreTrainedModel):
1905
 
1906
 
1907
  class DeepseekV2ForCausalLM(DeepseekV2PreTrainedModel, GenerationMixin):
1908
- _tied_weights_keys = ["lm_head.weight"]
1909
 
1910
  def __init__(self, config):
1911
  super().__init__(config)
 
1214
  seq_len = x.shape[-2]
1215
  if position_ids is None or position_ids.dim() != 2:
1216
  position_ids = torch.arange(seq_len, device=x.device).unsqueeze(0)
1217
+ inv_freq = 1.0 / (self.base ** (torch.arange(0, self.dim, 2, device=x.device, dtype=torch.float32) / self.dim))
 
 
1218
  inv_freq_expanded = inv_freq[None, :, None].expand(position_ids.shape[0], -1, 1)
1219
  position_ids_expanded = position_ids[:, None, :].to(dtype=torch.float32)
1220
  freqs = (inv_freq_expanded @ position_ids_expanded).transpose(1, 2)
 
1903
 
1904
 
1905
  class DeepseekV2ForCausalLM(DeepseekV2PreTrainedModel, GenerationMixin):
1906
+ _tied_weights_keys = {"lm_head.weight": "model.embed_tokens.weight"}
1907
 
1908
  def __init__(self, config):
1909
  super().__init__(config)
processing_deepseek_ocr.py CHANGED
@@ -28,12 +28,7 @@ DS_OCR_BASE_SIZE = 1024
28
 
29
  DEFAULT_OCR_PROMPT = (
30
  "Transcribe the provided document image into a clean Markdown format, "
31
- "preserving the natural reading order.\n"
32
- "Convert all formulas into LaTeX format. Inline formulas should be enclosed in `$ $`. "
33
- "Display (block) formulas should be enclosed in `$$ $$`.\n"
34
- 'Convert tables into HTML format (using <table border="1"><tr><td> tags).\n'
35
- "Ignore all graphical content in the image document. Do not attempt to describe or convert the images.\n"
36
- "Remove the headers and footers, but keep references and footnotes."
37
  )
38
 
39
  DS_OCR_DEFAULT_CHAT_TEMPLATE = dedent(
 
28
 
29
  DEFAULT_OCR_PROMPT = (
30
  "Transcribe the provided document image into a clean Markdown format, "
31
+ "preserving the natural reading order."
 
 
 
 
 
32
  )
33
 
34
  DS_OCR_DEFAULT_CHAT_TEMPLATE = dedent(