From ca7a567e6fb37af55bf91a7458df74e2db21a163 Mon Sep 17 00:00:00 2001 From: myhloli Date: Wed, 9 Jul 2025 11:10:42 +0800 Subject: [PATCH 1/3] feat: add option to select LaTeX delimiters type in Gradio app --- mineru/cli/gradio_app.py | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/mineru/cli/gradio_app.py b/mineru/cli/gradio_app.py index 7d33dce5..82d22d1f 100644 --- a/mineru/cli/gradio_app.py +++ b/mineru/cli/gradio_app.py @@ -114,12 +114,15 @@ async def to_markdown(file_path, end_pages=10, is_ocr=False, formula_enable=True return md_content, txt_content, archive_zip_path, new_pdf_path -latex_delimiters = [ +latex_delimiters_type_a = [ {'left': '$$', 'right': '$$', 'display': True}, {'left': '$', 'right': '$', 'display': False}, +] +latex_delimiters_type_b = [ {'left': '\\(', 'right': '\\)', 'display': False}, {'left': '\\[', 'right': '\\]', 'display': True}, ] +latex_delimiters_type_all = latex_delimiters_type_a + latex_delimiters_type_b header_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'resources', 'header.html') with open(header_path, 'r') as header_file: @@ -234,13 +237,30 @@ def update_interface(backend_choice): help="Set the server port for the Gradio app.", default=None, ) +@click.option( + '--latex-delimiters-type', + 'latex_delimiters_type', + type=click.Choice(['a', 'b', 'all']), + help="Set the type of LaTeX delimiters to use in Markdown rendering:" + "'a' for type '$', 'b' for type '()[]', 'all' for both types.", + default='all', +) def main(ctx, example_enable, sglang_engine_enable, api_enable, max_convert_pages, - server_name, server_port, **kwargs + server_name, server_port, latex_delimiters_type, **kwargs ): kwargs.update(arg_parse(ctx)) + if latex_delimiters_type == 'a': + latex_delimiters = latex_delimiters_type_a + elif latex_delimiters_type == 'b': + latex_delimiters = latex_delimiters_type_b + elif latex_delimiters_type == 'all': + latex_delimiters = latex_delimiters_type_all + else: + raise Exception (f"Invalid latex delimiters type: {latex_delimiters_type}. ") + if sglang_engine_enable: try: print("Start init SgLang engine...") From 7e6926ffb84b13bc41c40f27bba5bc59a487b279 Mon Sep 17 00:00:00 2001 From: myhloli Date: Wed, 9 Jul 2025 15:15:02 +0800 Subject: [PATCH 2/3] feat: enhance heading level feature with conditional imports and error handling --- mineru/backend/vlm/token_to_middle_json.py | 63 ++++++++++++---------- pyproject.toml | 4 +- 2 files changed, 37 insertions(+), 30 deletions(-) diff --git a/mineru/backend/vlm/token_to_middle_json.py b/mineru/backend/vlm/token_to_middle_json.py index 07878ef0..2edad38f 100644 --- a/mineru/backend/vlm/token_to_middle_json.py +++ b/mineru/backend/vlm/token_to_middle_json.py @@ -1,18 +1,24 @@ import time -import cv2 -import numpy as np from loguru import logger - -from mineru.backend.pipeline.model_init import AtomModelSingleton +import numpy as np +import cv2 from mineru.utils.config_reader import get_llm_aided_config from mineru.utils.cut_image import cut_image_and_table from mineru.utils.enum_class import ContentType from mineru.utils.hash_utils import str_md5 from mineru.backend.vlm.vlm_magic_model import MagicModel -from mineru.utils.llm_aided import llm_aided_title from mineru.utils.pdf_image_tools import get_crop_img from mineru.version import __version__ +heading_level_import_success = False +try: + from mineru.utils.llm_aided import llm_aided_title + from mineru.backend.pipeline.model_init import AtomModelSingleton + heading_level_import_success = True +except Exception as e: + logger.warning("The heading level feature cannot be used. If you need to use the heading level feature, " + "please execute `pip install mineru[pipeline]` to install the required packages.") + def token_to_page_info(token, image_dict, page, image_writer, page_index) -> dict: """将token转换为页面信息""" @@ -37,26 +43,27 @@ def token_to_page_info(token, image_dict, page, image_writer, page_index) -> dic title_aided_config = llm_aided_config.get('title_aided', None) if title_aided_config is not None: if title_aided_config.get('enable', False): - atom_model_manager = AtomModelSingleton() - ocr_model = atom_model_manager.get_atom_model( - atom_model_name='ocr', - ocr_show_log=False, - det_db_box_thresh=0.3, - lang='ch_lite' - ) - for title_block in title_blocks: - title_pil_img = get_crop_img(title_block['bbox'], page_pil_img, scale) - title_np_img = np.array(title_pil_img) - # 给title_pil_img添加上下左右各50像素白边padding - title_np_img = cv2.copyMakeBorder( - title_np_img, 50, 50, 50, 50, cv2.BORDER_CONSTANT, value=[255, 255, 255] + if heading_level_import_success: + atom_model_manager = AtomModelSingleton() + ocr_model = atom_model_manager.get_atom_model( + atom_model_name='ocr', + ocr_show_log=False, + det_db_box_thresh=0.3, + lang='ch_lite' ) - title_img = cv2.cvtColor(title_np_img, cv2.COLOR_RGB2BGR) - ocr_det_res = ocr_model.ocr(title_img, rec=False)[0] - if len(ocr_det_res) > 0: - # 计算所有res的平均高度 - avg_height = np.mean([box[2][1] - box[0][1] for box in ocr_det_res]) - title_block['line_avg_height'] = round(avg_height/scale) + for title_block in title_blocks: + title_pil_img = get_crop_img(title_block['bbox'], page_pil_img, scale) + title_np_img = np.array(title_pil_img) + # 给title_pil_img添加上下左右各50像素白边padding + title_np_img = cv2.copyMakeBorder( + title_np_img, 50, 50, 50, 50, cv2.BORDER_CONSTANT, value=[255, 255, 255] + ) + title_img = cv2.cvtColor(title_np_img, cv2.COLOR_RGB2BGR) + ocr_det_res = ocr_model.ocr(title_img, rec=False)[0] + if len(ocr_det_res) > 0: + # 计算所有res的平均高度 + avg_height = np.mean([box[2][1] - box[0][1] for box in ocr_det_res]) + title_block['line_avg_height'] = round(avg_height/scale) text_blocks = magic_model.get_text_blocks() interline_equation_blocks = magic_model.get_interline_equation_blocks() @@ -86,15 +93,15 @@ def result_to_middle_json(token_list, images_list, pdf_doc, image_writer): """llm优化""" llm_aided_config = get_llm_aided_config() - if llm_aided_config is not None: """标题优化""" title_aided_config = llm_aided_config.get('title_aided', None) if title_aided_config is not None: if title_aided_config.get('enable', False): - llm_aided_title_start_time = time.time() - llm_aided_title(middle_json["pdf_info"], title_aided_config) - logger.info(f'llm aided title time: {round(time.time() - llm_aided_title_start_time, 2)}') + if heading_level_import_success: + llm_aided_title_start_time = time.time() + llm_aided_title(middle_json["pdf_info"], title_aided_config) + logger.info(f'llm aided title time: {round(time.time() - llm_aided_title_start_time, 2)}') # 关闭pdf文档 pdf_doc.close() diff --git a/pyproject.toml b/pyproject.toml index 7081ab78..17444785 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,6 +33,8 @@ dependencies = [ "modelscope>=1.26.0", "huggingface-hub>=0.32.4", "json-repair>=0.46.2", + "opencv-python>=4.11.0.86", + "fast-langdetect>=0.2.3,<0.3.0", ] [project.optional-dependencies] @@ -60,7 +62,6 @@ pipeline = [ "torch>=2.2.2,!=2.5.0,!=2.5.1,<3", "torchvision", "transformers>=4.49.0,!=4.51.0,<5.0.0", - "fast-langdetect>=0.2.3,<0.3.0", ] api = [ "fastapi", @@ -97,7 +98,6 @@ pipeline_old_linux = [ "torch>=2.2.2,!=2.5.0,!=2.5.1,<3", "torchvision", "transformers>=4.49.0,!=4.51.0,<5.0.0", - "fast-langdetect>=0.2.3,<0.3.0", ] [project.urls] From 374f464bbaba247971ad5e4c23fe4e8d8177e969 Mon Sep 17 00:00:00 2001 From: Xiaomeng Zhao Date: Wed, 9 Jul 2025 15:37:52 +0800 Subject: [PATCH 3/3] Update mineru/cli/gradio_app.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- mineru/cli/gradio_app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mineru/cli/gradio_app.py b/mineru/cli/gradio_app.py index 82d22d1f..0678f86d 100644 --- a/mineru/cli/gradio_app.py +++ b/mineru/cli/gradio_app.py @@ -259,7 +259,7 @@ def main(ctx, elif latex_delimiters_type == 'all': latex_delimiters = latex_delimiters_type_all else: - raise Exception (f"Invalid latex delimiters type: {latex_delimiters_type}. ") + raise ValueError(f"Invalid latex delimiters type: {latex_delimiters_type}.") if sglang_engine_enable: try: