Compare commits

..

43 Commits

Author SHA1 Message Date
Xiaomeng Zhao
80cbeb2a3f Merge pull request #3213 from myhloli/dev
fix: add support for additional keyword arguments in modeling_unimer_mbart.py to adaptation transformers 4.54.1
2025-07-30 16:56:05 +08:00
myhloli
be489ab780 chore: update changelog for version 2.1.9 release with transformers 4.54.1 adaptation 2025-07-30 16:53:15 +08:00
myhloli
0041919d22 chore: update Dockerfile and documentation for sglang version 0.4.9.post6 2025-07-30 16:51:44 +08:00
myhloli
f7affcefb7 fix: add support for additional keyword arguments in modeling_unimer_mbart.py to adaptation transformers 4.54.1 2025-07-30 16:42:54 +08:00
Xiaomeng Zhao
a11f6de370 Merge pull request #3198 from opendatalab/master
master->dev
2025-07-28 19:30:03 +08:00
myhloli
93a3bc776b Update version.py with new version 2025-07-28 11:24:37 +00:00
Xiaomeng Zhao
7ceee7f7bf Merge pull request #3197 from opendatalab/release-2.1.8
Release 2.1.8
2025-07-28 19:18:03 +08:00
Xiaomeng Zhao
8e7bf5148a Merge pull request #3196 from myhloli/dev
fix: update Mineru2ImageProcessor constructor to accept additional arguments to adaptation sglang 0.4.9.post5
2025-07-28 19:03:42 +08:00
myhloli
3920a8c1f3 chore: update changelog for sglang 0.4.9.post5 adaptation 2025-07-28 19:01:37 +08:00
myhloli
3c817536b1 chore: update changelog for sglang 0.4.9.post5 adaptation 2025-07-28 19:00:33 +08:00
myhloli
89e3e9e5ce chore: update changelog for sglang 0.4.9.post5 adaptation 2025-07-28 18:58:36 +08:00
myhloli
03276996ce fix: update Dockerfile and documentation to use sglang v0.4.9.post5 2025-07-28 18:49:18 +08:00
myhloli
6411cdfd7c fix: update Mineru2ImageProcessor constructor to accept additional arguments to adaptation sglang 0.4.9.post5 2025-07-28 18:45:41 +08:00
Xiaomeng Zhao
c27681642d Merge pull request #3189 from opendatalab/master
master->dev
2025-07-27 18:42:45 +08:00
myhloli
112e1967e7 Update version.py with new version 2025-07-27 10:38:00 +00:00
Xiaomeng Zhao
fe25040db5 Merge pull request #3187 from opendatalab/release-2.1.7
Release 2.1.7
2025-07-27 18:34:58 +08:00
Xiaomeng Zhao
b231f4493c Merge pull request #3186 from myhloli/dev
fix: update past_key_values handling to support custom sequence lengths
2025-07-27 18:32:39 +08:00
myhloli
4aef8fd168 fix: transformers 4.54.0 adaptation 2025-07-27 18:30:31 +08:00
myhloli
3ff7fee8a6 Merge remote-tracking branch 'origin/dev' into dev 2025-07-27 18:09:33 +08:00
myhloli
0490af1cd7 fix: transformers 4.54.0 adaptation 2025-07-27 18:03:43 +08:00
myhloli
1db99bb403 Merge remote-tracking branch 'origin/dev' into dev 2025-07-27 13:32:17 +08:00
myhloli
4267cfa2c3 chore: update changelog for version 2.1.7 release with transformers 4.54.0 adaptation 2025-07-27 13:31:58 +08:00
myhloli
f6f60b971a fix: update Dockerfile and documentation to use sglang:v0.4.9.post4 base image 2025-07-27 12:57:45 +08:00
myhloli
0f4dbbd0de Merge remote-tracking branch 'origin/dev' into dev 2025-07-26 23:50:40 +08:00
myhloli
e7ed7660e3 fix: update past_key_values handling to support custom sequence lengths 2025-07-26 23:50:29 +08:00
Xiaomeng Zhao
ab02c5943e Merge pull request #3184 from opendatalab/master
master->dev
2025-07-26 05:05:06 +08:00
myhloli
a8d3f789bb Update version.py with new version 2025-07-25 20:59:14 +00:00
Xiaomeng Zhao
9356552a04 Merge pull request #3183 from opendatalab/release-2.1.6
Release 2.1.6
2025-07-26 04:57:28 +08:00
Xiaomeng Zhao
1a773b01fb Merge pull request #3182 from myhloli/dev
Dev
2025-07-26 04:46:10 +08:00
myhloli
4ca963c860 Merge remote-tracking branch 'origin/dev' into dev 2025-07-26 04:36:43 +08:00
myhloli
050e1dbc70 chore: update changelog for version 2.1.6 release with fixes for table parsing and visualization box position 2025-07-26 04:36:33 +08:00
Xiaomeng Zhao
9d0ebd8a19 Merge pull request #3181 from myhloli/dev
refactor: enhance HTML table extraction and add block content conversion to HTML
2025-07-26 04:20:56 +08:00
Xiaomeng Zhao
6ed75347a6 Update mineru/utils/format_utils.py
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-26 04:20:30 +08:00
myhloli
825fc95a8a fix: ensure new pages are created for overlay merging in draw_bbox.py 2025-07-26 04:10:40 +08:00
myhloli
2ae1e3af16 Merge remote-tracking branch 'origin/dev' into dev 2025-07-26 03:49:59 +08:00
Xiaomeng Zhao
64e32bb57f Merge pull request #3175 from jinghuan-Chen/handle-pdf-rotation
Fix draw bbox when pdf rotate.
2025-07-26 03:49:21 +08:00
Xiaomeng Zhao
d0726b73c6 Update draw_bbox.py 2025-07-26 03:35:35 +08:00
Xiaomeng Zhao
8b552460da Update draw_bbox.py 2025-07-26 02:47:56 +08:00
myhloli
28553212c3 refactor: enhance HTML table extraction and add block content conversion to HTML 2025-07-26 02:37:10 +08:00
jinghuan-Chen
9c868484f5 Fix draw bbox when pdf rotate. 2025-07-25 00:12:45 +08:00
Xiaomeng Zhao
d878c7a3aa Merge pull request #3174 from opendatalab/master
master->dev
2025-07-24 21:39:21 +08:00
myhloli
30155bde3f Update version.py with new version 2025-07-24 13:36:50 +00:00
Xiaomeng Zhao
10e76530a5 Merge pull request #3173 from opendatalab/release-2.1.5
Release 2.1.5
2025-07-24 21:35:05 +08:00
13 changed files with 153 additions and 42 deletions

View File

@@ -43,6 +43,15 @@
</div>
# Changelog
- 2025/07/30 version 2.1.9 Released
- `transformers` 4.54.1 version adaptation
- 2025/07/28 version 2.1.8 Released
- `sglang` 0.4.9.post5 version adaptation
- 2025/07/27 version 2.1.7 Released
- `transformers` 4.54.0 version adaptation
- 2025/07/26 2.1.6 Released
- Fixed table parsing issues in handwritten documents when using `vlm` backend
- Fixed visualization box position drift issue when document is rotated #3175
- 2025/07/24 2.1.5 Released
- `sglang` 0.4.9 version adaptation, synchronously upgrading the dockerfile base image to sglang 0.4.9.post3
- 2025/07/23 2.1.4 Released

View File

@@ -43,13 +43,22 @@
</div>
# 更新记录
- 2025/07/24 2.1.5发布
- 2025/07/30 2.1.9 发布
- `transformers` 4.54.1 版本适配
- 2025/07/28 2.1.8 发布
- `sglang` 0.4.9.post5 版本适配
- 2025/07/27 2.1.7 发布
- `transformers` 4.54.0 版本适配
- 2025/07/26 2.1.6 发布
- 修复`vlm`后端解析部分手写文档时的表格异常问题
- 修复文档旋转时可视化框位置漂移问题 #3175
- 2025/07/24 2.1.5 发布
- `sglang` 0.4.9 版本适配同步升级dockerfile基础镜像为sglang 0.4.9.post3
- 2025/07/23 2.1.4发布
- 2025/07/23 2.1.4 发布
- bug修复
- 修复`pipeline`后端中`MFR`步骤在某些情况下显存消耗过大的问题 #2771
- 修复某些情况下`image`/`table``caption`/`footnote`匹配不准确的问题 #3129
- 2025/07/16 2.1.1发布
- 2025/07/16 2.1.1 发布
- bug修复
- 修复`pipeline`在某些情况可能发生的文本块内容丢失问题 #3005
- 修复`sglang-client`需要安装`torch`等不必要的包的问题 #2968
@@ -57,7 +66,7 @@
- 易用性更新
- 更新`compose.yaml`,便于用户直接启动`sglang-server``mineru-api``mineru-gradio`服务
- 启用全新的[在线文档站点](https://opendatalab.github.io/MinerU/zh/)简化readme提供更好的文档体验
- 2025/07/05 2.1.0发布
- 2025/07/05 2.1.0 发布
- 这是 MinerU 2 的第一个大版本更新包含了大量新功能和改进包含众多性能优化、体验优化和bug修复具体更新内容如下
- 性能优化:
- 大幅提升某些特定分辨率长边2000像素左右文档的预处理速度

View File

@@ -1,7 +1,7 @@
# Use the official sglang image
FROM lmsysorg/sglang:v0.4.9.post3-cu126
FROM lmsysorg/sglang:v0.4.9.post6-cu126
# For blackwell GPU, use the following line instead:
# FROM lmsysorg/sglang:v0.4.9.post3-cu128-b200
# FROM lmsysorg/sglang:v0.4.9.post6-cu128-b200
# Install libgl for opencv support & Noto fonts for Chinese characters
RUN apt-get update && \

View File

@@ -1,7 +1,7 @@
# Use the official sglang image
FROM lmsysorg/sglang:v0.4.9.post3-cu126
FROM lmsysorg/sglang:v0.4.9.post6-cu126
# For blackwell GPU, use the following line instead:
# FROM lmsysorg/sglang:v0.4.9.post3-cu128-b200
# FROM lmsysorg/sglang:v0.4.9.post6-cu128-b200
# Install libgl for opencv support & Noto fonts for Chinese characters
RUN apt-get update && \

View File

@@ -10,8 +10,8 @@ docker build -t mineru-sglang:latest -f Dockerfile .
```
> [!TIP]
> The [Dockerfile](https://github.com/opendatalab/MinerU/blob/master/docker/global/Dockerfile) uses `lmsysorg/sglang:v0.4.9.post3-cu126` as the base image by default, supporting Turing/Ampere/Ada Lovelace/Hopper platforms.
> If you are using the newer `Blackwell` platform, please modify the base image to `lmsysorg/sglang:v0.4.9.post3-cu128-b200` before executing the build operation.
> The [Dockerfile](https://github.com/opendatalab/MinerU/blob/master/docker/global/Dockerfile) uses `lmsysorg/sglang:v0.4.9.post6-cu126` as the base image by default, supporting Turing/Ampere/Ada Lovelace/Hopper platforms.
> If you are using the newer `Blackwell` platform, please modify the base image to `lmsysorg/sglang:v0.4.9.post6-cu128-b200` before executing the build operation.
## Docker Description

View File

@@ -10,8 +10,8 @@ docker build -t mineru-sglang:latest -f Dockerfile .
```
> [!TIP]
> [Dockerfile](https://github.com/opendatalab/MinerU/blob/master/docker/china/Dockerfile)默认使用`lmsysorg/sglang:v0.4.9.post3-cu126`作为基础镜像支持Turing/Ampere/Ada Lovelace/Hopper平台
> 如您使用较新的`Blackwell`平台,请将基础镜像修改为`lmsysorg/sglang:v0.4.9.post3-cu128-b200` 再执行build操作。
> [Dockerfile](https://github.com/opendatalab/MinerU/blob/master/docker/china/Dockerfile)默认使用`lmsysorg/sglang:v0.4.9.post6-cu126`作为基础镜像支持Turing/Ampere/Ada Lovelace/Hopper平台
> 如您使用较新的`Blackwell`平台,请将基础镜像修改为`lmsysorg/sglang:v0.4.9.post6-cu128-b200` 再执行build操作。
## Docker说明

View File

@@ -256,9 +256,12 @@ class BatchAnalyze:
html_code, table_cell_bboxes, logic_points, elapse = table_model.predict(table_res_dict['table_img'])
# 判断是否返回正常
if html_code:
expected_ending = html_code.strip().endswith('</html>') or html_code.strip().endswith('</table>')
if expected_ending:
table_res_dict['table_res']['html'] = html_code
# 检查html_code是否包含'<table>'和'</table>'
if '<table>' in html_code and '</table>' in html_code:
# 选用<table>到</table>的内容放入table_res_dict['table_res']['html']
start_index = html_code.find('<table>')
end_index = html_code.rfind('</table>') + len('</table>')
table_res_dict['table_res']['html'] = html_code[start_index:end_index]
else:
logger.warning(
'table recognition processing fails, not found expected HTML table end'

View File

@@ -5,7 +5,7 @@ from loguru import logger
from mineru.utils.enum_class import ContentType, BlockType, SplitFlag
from mineru.backend.vlm.vlm_middle_json_mkcontent import merge_para_with_text
from mineru.utils.format_utils import convert_otsl_to_html
from mineru.utils.format_utils import block_content_to_html
from mineru.utils.magic_model_utils import reduct_overlap, tie_up_category_by_distance_v3
@@ -40,6 +40,10 @@ class MagicModel:
block_type = block_info[1].strip()
block_content = block_info[2].strip()
# 如果bbox是0,0,999,999且type为text按notes增加表格处理
if x1 == 0 and y1 == 0 and x2 == 999 and y2 == 999 and block_type == "text":
block_content = block_content_to_html(block_content)
# print(f"坐标: {block_bbox}")
# print(f"类型: {block_type}")
# print(f"内容: {block_content}")
@@ -77,16 +81,7 @@ class MagicModel:
"type": span_type,
}
if span_type == ContentType.TABLE:
if "<fcel>" in block_content or "<ecel>" in block_content:
lines = block_content.split("\n\n")
new_lines = []
for line in lines:
if "<fcel>" in line or "<ecel>" in line:
line = convert_otsl_to_html(line)
new_lines.append(line)
span["html"] = "\n\n".join(new_lines)
else:
span["html"] = block_content
span["html"] = block_content_to_html(block_content)
elif span_type in [ContentType.INTERLINE_EQUATION]:
span = {
"bbox": block_bbox,

View File

@@ -1416,7 +1416,11 @@ class UnimerMBartDecoder(UnimerMBartPreTrainedModel):
raise ValueError("You have to specify either decoder_input_ids or decoder_inputs_embeds")
# past_key_values_length
past_key_values_length = past_key_values[0][0].shape[2] if past_key_values is not None else 0
# past_key_values_length = past_key_values[0][0].shape[2] if past_key_values is not None else 0
past_key_values_length = 0
if past_key_values is not None:
if isinstance(past_key_values, (list, tuple)) and past_key_values:
past_key_values_length = past_key_values[0][0].shape[2]
if inputs_embeds is None:
inputs_embeds = self.embed_tokens(input_ids)
@@ -1501,7 +1505,12 @@ class UnimerMBartDecoder(UnimerMBartPreTrainedModel):
if dropout_probability < self.layerdrop:
continue
past_key_value = past_key_values[idx] if past_key_values is not None else None
# past_key_value = past_key_values[idx] if past_key_values is not None else None
past_key_value = past_key_values[idx] if (
past_key_values is not None and
isinstance(past_key_values, (list, tuple)) and
idx < len(past_key_values)
) else None
if self.gradient_checkpointing and self.training:
layer_outputs = self._gradient_checkpointing_func(
@@ -2182,6 +2191,7 @@ class UnimerMBartForCausalLM(UnimerMBartPreTrainedModel, GenerationMixin):
output_hidden_states: Optional[bool] = None,
return_dict: Optional[bool] = None,
count_gt: Optional[torch.LongTensor] = None,
**kwargs,
) -> Union[Tuple, CausalLMOutputWithCrossAttentions]:
r"""
Args:

View File

@@ -56,8 +56,8 @@ def process_anyres_image(image, processor, grid_pinpoints):
class Mineru2ImageProcessor(BaseProcessor):
def __init__(self, hf_config, server_args, _processor):
super().__init__(hf_config, server_args, _processor)
def __init__(self, hf_config, server_args, _processor, *args, **kwargs):
super().__init__(hf_config, server_args, _processor, *args, **kwargs)
@staticmethod
def _process_single_image_task(

View File

@@ -2,21 +2,64 @@ import json
from io import BytesIO
from loguru import logger
from pypdf import PdfReader, PdfWriter
from pypdf import PdfReader, PdfWriter, PageObject
from reportlab.pdfgen import canvas
from .enum_class import BlockType, ContentType
def cal_canvas_rect(page, bbox):
"""
Calculate the rectangle coordinates on the canvas based on the original PDF page and bounding box.
Args:
page: A PyPDF2 Page object representing a single page in the PDF.
bbox: [x0, y0, x1, y1] representing the bounding box coordinates.
Returns:
rect: [x0, y0, width, height] representing the rectangle coordinates on the canvas.
"""
page_width, page_height = float(page.cropbox[2]), float(page.cropbox[3])
actual_width = page_width # The width of the final PDF display
actual_height = page_height # The height of the final PDF display
rotation = page.get("/Rotate", 0)
rotation = rotation % 360
if rotation in [90, 270]:
# PDF is rotated 90 degrees or 270 degrees, and the width and height need to be swapped
actual_width, actual_height = actual_height, actual_width
x0, y0, x1, y1 = bbox
rect_w = abs(x1 - x0)
rect_h = abs(y1 - y0)
if 270 == rotation:
rect_w, rect_h = rect_h, rect_w
x0 = actual_height - y1
y0 = actual_width - x1
elif 180 == rotation:
x0 = page_width - x1
y0 = y0
elif 90 == rotation:
rect_w, rect_h = rect_h, rect_w
x0, y0 = y0, x0
else:
# 0 == rotation:
x0 = x0
y0 = page_height - y1
rect = [x0, y0, rect_w, rect_h]
return rect
def draw_bbox_without_number(i, bbox_list, page, c, rgb_config, fill_config):
new_rgb = [float(color) / 255 for color in rgb_config]
page_data = bbox_list[i]
page_width, page_height = page.cropbox[2], page.cropbox[3]
for bbox in page_data:
width = bbox[2] - bbox[0]
height = bbox[3] - bbox[1]
rect = [bbox[0], page_height - bbox[3], width, height] # Define the rectangle
rect = cal_canvas_rect(page, bbox) # Define the rectangle
if fill_config: # filled rectangle
c.setFillColorRGB(new_rgb[0], new_rgb[1], new_rgb[2], 0.3)
@@ -35,10 +78,8 @@ def draw_bbox_with_number(i, bbox_list, page, c, rgb_config, fill_config, draw_b
for j, bbox in enumerate(page_data):
# 确保bbox的每个元素都是float
x0, y0, x1, y1 = map(float, bbox)
width = x1 - x0
height = y1 - y0
rect = [x0, page_height - y1, width, height]
rect = cal_canvas_rect(page, bbox) # Define the rectangle
if draw_bbox:
if fill_config:
c.setFillColorRGB(*new_rgb, 0.3)
@@ -48,8 +89,23 @@ def draw_bbox_with_number(i, bbox_list, page, c, rgb_config, fill_config, draw_b
c.rect(rect[0], rect[1], rect[2], rect[3], stroke=1, fill=0)
c.setFillColorRGB(*new_rgb, 1.0)
c.setFontSize(size=10)
# 这里也要用float
c.drawString(x1 + 2, page_height - y0 - 10, str(j + 1))
c.saveState()
rotation = page.get("/Rotate", 0)
rotation = rotation % 360
if 0 == rotation:
c.translate(rect[0] + rect[2] + 2, rect[1] + rect[3] - 10)
elif 90 == rotation:
c.translate(rect[0] + 10, rect[1] + rect[3] + 2)
elif 180 == rotation:
c.translate(rect[0] - 2, rect[1] + 10)
elif 270 == rotation:
c.translate(rect[0] + rect[2] - 10, rect[1] - 2)
c.rotate(rotation)
c.drawString(0, 0, str(j + 1))
c.restoreState()
return c
@@ -185,6 +241,9 @@ def draw_layout_bbox(pdf_info, pdf_bytes, out_path, filename):
# 添加检查确保overlay_pdf.pages不为空
if len(overlay_pdf.pages) > 0:
new_page = PageObject(pdf=None)
new_page.update(page)
page = new_page
page.merge_page(overlay_pdf.pages[0])
else:
# 记录日志并继续处理下一个页面
@@ -300,6 +359,9 @@ def draw_span_bbox(pdf_info, pdf_bytes, out_path, filename):
# 添加检查确保overlay_pdf.pages不为空
if len(overlay_pdf.pages) > 0:
new_page = PageObject(pdf=None)
new_page.update(page)
page = new_page
page.merge_page(overlay_pdf.pages[0])
else:
# 记录日志并继续处理下一个页面

View File

@@ -317,3 +317,26 @@ def convert_otsl_to_html(otsl_content: str):
)
return export_to_html(table_data)
def block_content_to_html(block_content: str) -> str:
"""
Converts block content containing OTSL (Open Table Structure Language) tags into HTML.
This function processes a block of text, splitting it into lines and converting any lines
containing OTSL table tags (e.g., <fcel>, <ecel>) into HTML tables. Lines without these
tags are left unchanged.
Parameters:
block_content (str): A string containing block content with potential OTSL tags.
Returns:
str: The processed block content with OTSL tags converted to HTML tables.
"""
lines = block_content.split("\n\n")
new_lines = []
for line in lines:
if "<fcel>" in line or "<ecel>" in line:
line = convert_otsl_to_html(line)
new_lines.append(line)
return "\n\n".join(new_lines)

View File

@@ -1 +1 @@
__version__ = "2.1.4"
__version__ = "2.1.8"