From a42e6c9f6fb3e1945103fc0d69199c712a39d17b Mon Sep 17 00:00:00 2001 From: Espoir Murhabazi Date: Thu, 11 Sep 2025 22:22:27 +0100 Subject: [PATCH 1/8] add the code for the pdf table parser with pdf plumber --- pyproject.toml | 2 + src/openparse/doc_parser.py | 20 ++++++--- src/openparse/tables/__init__.py | 5 ++- src/openparse/tables/parse.py | 76 +++++++++++++++++++++++++++----- src/openparse/tables/utils.py | 27 +++++++++++- 5 files changed, 111 insertions(+), 19 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index c35a224..c432661 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,6 +19,8 @@ dependencies = [ "tiktoken >= 0.3", "openai >= 1.0.0", "numpy", + "pdfplumber==0.11.7", + "pypdfium2==4.30.0" ] [project.urls] diff --git a/src/openparse/doc_parser.py b/src/openparse/doc_parser.py index 5caf975..41d3862 100644 --- a/src/openparse/doc_parser.py +++ b/src/openparse/doc_parser.py @@ -13,7 +13,8 @@ from openparse.schemas import ImageElement -IngestionPipelineType = TypeVar("IngestionPipelineType", bound=IngestionPipeline) +IngestionPipelineType = TypeVar( + "IngestionPipelineType", bound=IngestionPipeline) class UnitableArgsDict(TypedDict, total=False): @@ -34,15 +35,22 @@ class PyMuPDFArgsDict(TypedDict, total=False): table_output_format: Literal["markdown", "html"] +class PDfPlumberArgsDict(TypedDict, total=False): + parsing_algorithm: Literal["pdfplumber"] + table_output_format: Literal["markdown", "html"] + + def _table_args_dict_to_model( - args_dict: Union[TableTransformersArgsDict, PyMuPDFArgsDict], -) -> Union[tables.TableTransformersArgs, tables.PyMuPDFArgs]: + args_dict: Union[TableTransformersArgsDict, PyMuPDFArgsDict, PDfPlumberArgsDict], +) -> Union[tables.TableTransformersArgs, tables.PyMuPDFArgs, tables.PDfPlumberArgs]: if args_dict["parsing_algorithm"] == "table-transformers": return tables.TableTransformersArgs(**args_dict) elif args_dict["parsing_algorithm"] == "pymupdf": return tables.PyMuPDFArgs(**args_dict) elif args_dict["parsing_algorithm"] == "unitable": return tables.UnitableArgs(**args_dict) + elif args_dict["parsing_algorithm"] == "pdfplumber": + return tables.PDfPlumberArgs(**args_dict) else: raise ValueError( f"Unsupported parsing_algorithm: {args_dict['parsing_algorithm']}" @@ -63,7 +71,8 @@ class DocumentParser: def __init__( self, *, - processing_pipeline: Union[IngestionPipeline, NotGiven, None] = NOT_GIVEN, + processing_pipeline: Union[IngestionPipeline, + NotGiven, None] = NOT_GIVEN, table_args: Union[ TableTransformersArgsDict, PyMuPDFArgsDict, NotGiven ] = NOT_GIVEN, @@ -104,7 +113,8 @@ def parse( table_args_obj = None if self.table_args: table_args_obj = _table_args_dict_to_model(self.table_args) - table_elems = tables.ingest(doc, table_args_obj, verbose=self._verbose) + table_elems = tables.ingest( + doc, table_args_obj, verbose=self._verbose) table_nodes = self._elems_to_nodes(table_elems) nodes = text_nodes + table_nodes diff --git a/src/openparse/tables/__init__.py b/src/openparse/tables/__init__.py index 007f45e..bae36fb 100644 --- a/src/openparse/tables/__init__.py +++ b/src/openparse/tables/__init__.py @@ -1,3 +1,4 @@ -from .parse import PyMuPDFArgs, TableTransformersArgs, UnitableArgs, ingest +from .parse import PyMuPDFArgs, TableTransformersArgs, UnitableArgs, ingest, PDfPlumberArgs -__all__ = ["ingest", "TableTransformersArgs", "PyMuPDFArgs", "UnitableArgs"] +__all__ = ["ingest", "TableTransformersArgs", + "PyMuPDFArgs", "UnitableArgs", "PDfPlumberArgs"] diff --git a/src/openparse/tables/parse.py b/src/openparse/tables/parse.py index 54ffbbb..12af93b 100644 --- a/src/openparse/tables/parse.py +++ b/src/openparse/tables/parse.py @@ -1,17 +1,18 @@ -from typing import List, Literal, Union +from typing import List, Literal, Union, Dict from pydantic import BaseModel, ConfigDict, Field from openparse.pdf import Pdf from openparse.schemas import Bbox, TableElement -from openparse.tables.utils import adjust_bbox_with_padding, crop_img_with_padding +from openparse.tables.utils import adjust_bbox_with_padding, crop_img_with_padding, pdf_plumber_table_data_to_markdown from . import pymupdf class ParsingArgs(BaseModel): parsing_algorithm: str - table_output_format: Literal["str", "markdown", "html"] = Field(default="html") + table_output_format: Literal["str", + "markdown", "html"] = Field(default="html") class TableTransformersArgs(BaseModel): @@ -20,14 +21,16 @@ class TableTransformersArgs(BaseModel): ) min_table_confidence: float = Field(default=0.75, ge=0.0, le=1.0) min_cell_confidence: float = Field(default=0.95, ge=0.0, le=1.0) - table_output_format: Literal["str", "markdown", "html"] = Field(default="html") + table_output_format: Literal["str", + "markdown", "html"] = Field(default="html") model_config = ConfigDict(extra="forbid") class PyMuPDFArgs(BaseModel): parsing_algorithm: Literal["pymupdf"] = Field(default="pymupdf") - table_output_format: Literal["str", "markdown", "html"] = Field(default="html") + table_output_format: Literal["str", + "markdown", "html"] = Field(default="html") model_config = ConfigDict(extra="forbid") @@ -40,6 +43,13 @@ class UnitableArgs(BaseModel): model_config = ConfigDict(extra="forbid") +class PDfPlumberArgs(BaseModel): + parsing_algorithm: Literal["pdfplumber"] = Field(default="pdfplumber") + table_output_format: Literal["markdown"] = Field(default="html") + table_parse_settings: Dict = Field(default_factory=dict) + model_config = ConfigDict(extra="forbid") + + def _ingest_with_pymupdf( doc: Pdf, parsing_args: PyMuPDFArgs, @@ -69,7 +79,8 @@ def _ingest_with_pymupdf( print(f"Page {page_num} - Table {i + 1}:\n{text}\n") # Flip y-coordinates to match the top-left origin system - bbox = pymupdf.combine_header_and_table_bboxes(tab.bbox, tab.header.bbox) + bbox = pymupdf.combine_header_and_table_bboxes( + tab.bbox, tab.header.bbox) fy0 = page.rect.height - bbox[3] fy1 = page.rect.height - bbox[1] @@ -108,7 +119,8 @@ def _ingest_with_table_transformers( pages_with_tables = {} for page_num, img in enumerate(pdf_as_imgs): - pages_with_tables[page_num] = find_table_bboxes(img, args.min_table_confidence) + pages_with_tables[page_num] = find_table_bboxes( + img, args.min_table_confidence) tables = [] for page_num, table_bboxes in pages_with_tables.items(): @@ -177,7 +189,8 @@ def _ingest_with_unitable( pages_with_tables = {} for page_num, img in enumerate(pdf_as_imgs): - pages_with_tables[page_num] = find_table_bboxes(img, args.min_table_confidence) + pages_with_tables[page_num] = find_table_bboxes( + img, args.min_table_confidence) tables = [] for page_num, table_bboxes in pages_with_tables.items(): @@ -190,7 +203,8 @@ def _ingest_with_unitable( page_height=page.rect.height, padding_pct=padding_pct, ) - table_img = crop_img_with_padding(pdf_as_imgs[page_num], padded_bbox) + table_img = crop_img_with_padding( + pdf_as_imgs[page_num], padded_bbox) table_str = table_img_to_html(table_img) @@ -216,9 +230,49 @@ def _ingest_with_unitable( return tables +def _ingest_with_pdfplumber( + doc: Pdf, + args: PDfPlumberArgs, + verbose: bool = False, +) -> List[TableElement]: + try: + import pdfplumber + except ImportError as e: + raise ImportError( + "Table detection and extraction requires the `pdfplumber` library to be installed.", + e, + ) from e + + pdf_plumber_doc = pdfplumber.open(doc.file_path) + found_tables = [] + table_settings = getattr(args, "table_parse_settings", {}) + for page_number, page in enumerate(pdf_plumber_doc.pages): + + tables = page.find_tables(table_settings) + if not tables: + continue + for table in tables: + table_bounding_box = table.bbox + table_data = table.extract() + table_markdown = pdf_plumber_table_data_to_markdown(table_data) + table_bbox = Bbox( + page=page_number, + x0=table_bounding_box[0], + y0=table_bounding_box[1], + x1=table_bounding_box[2], + y1=table_bounding_box[3], + page_width=page.width, + page_height=page.height) + table_element = TableElement( + bbox=table_bbox, text=table_markdown) + found_tables.append(table_element) + return found_tables + + def ingest( doc: Pdf, - parsing_args: Union[TableTransformersArgs, PyMuPDFArgs, UnitableArgs, None] = None, + parsing_args: Union[TableTransformersArgs, + PyMuPDFArgs, UnitableArgs, None] = None, verbose: bool = False, ) -> List[TableElement]: if isinstance(parsing_args, TableTransformersArgs): @@ -227,5 +281,7 @@ def ingest( return _ingest_with_pymupdf(doc, parsing_args, verbose) elif isinstance(parsing_args, UnitableArgs): return _ingest_with_unitable(doc, parsing_args, verbose) + elif isinstance(parsing_args, PDfPlumberArgs): + return _ingest_with_pdfplumber(doc, parsing_args, verbose) else: raise ValueError("Unsupported parsing_algorithm.") diff --git a/src/openparse/tables/utils.py b/src/openparse/tables/utils.py index 780d4df..0c6712d 100644 --- a/src/openparse/tables/utils.py +++ b/src/openparse/tables/utils.py @@ -62,7 +62,8 @@ def doc_to_imgs(doc) -> List[Image.Image]: for n in page_numbers: page = doc[n] pix = page.get_pixmap() - image = Image.frombytes("RGB", [pix.width, pix.height], pix.samples) + image = Image.frombytes( + "RGB", [pix.width, pix.height], pix.samples) images.append(image) except ValueError as e: @@ -189,9 +190,31 @@ def adjust_bbox_with_padding( # Adjust the bounding box coordinates with padding padded_x0 = max(x0 - padding_x, 0) # Ensure x0 is not less than 0 padded_y0 = max(y0 - padding_y, 0) # Ensure y0 is not less than 0 - padded_x1 = min(x1 + padding_x, page_width) # Ensure x1 does not exceed page width + # Ensure x1 does not exceed page width + padded_x1 = min(x1 + padding_x, page_width) padded_y1 = min( y1 + padding_y, page_height ) # Ensure y1 does not exceed page height return padded_x0, padded_y0, padded_x1, padded_y1 + + +# pdf plumber utils + +def pdf_plumber_table_data_to_markdown(table_data: List[List[str | None]]) -> str: + """ Convert a 2D list of table data into a markdown table string.""" + if not table_data or not table_data[0]: + return "" + header = table_data[0] + rows = table_data[1:] + # Build header row + table_markdown = "| " + \ + " | ".join(str(h) if h is not None else "" for h in header) + " |\n" + # Build separator row + table_markdown += "| " + " | ".join("---" for _ in header) + " |\n" + # Build data rows + for row in rows: + table_markdown += "| " + \ + " | ".join( + str(cell) if cell is not None else "" for cell in row) + " |\n" + return table_markdown From f53b18cfdd0c4c00498db05ae390e617c634b614 Mon Sep 17 00:00:00 2001 From: Espoir Murhabazi Date: Thu, 11 Sep 2025 23:08:10 +0100 Subject: [PATCH 2/8] fix the table parsing --- src/openparse/tables/parse.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/openparse/tables/parse.py b/src/openparse/tables/parse.py index 12af93b..960c8de 100644 --- a/src/openparse/tables/parse.py +++ b/src/openparse/tables/parse.py @@ -247,7 +247,6 @@ def _ingest_with_pdfplumber( found_tables = [] table_settings = getattr(args, "table_parse_settings", {}) for page_number, page in enumerate(pdf_plumber_doc.pages): - tables = page.find_tables(table_settings) if not tables: continue @@ -266,7 +265,7 @@ def _ingest_with_pdfplumber( table_element = TableElement( bbox=table_bbox, text=table_markdown) found_tables.append(table_element) - return found_tables + return found_tables def ingest( From 6ce16425177ccbf6d6b039876f852d4d1ac6c2ed Mon Sep 17 00:00:00 2001 From: Espoir Murhabazi Date: Fri, 12 Sep 2025 01:24:46 +0100 Subject: [PATCH 3/8] fix the table caption --- src/openparse/processing/basic_transforms.py | 10 ++++++---- src/openparse/tables/parse.py | 11 +++++++++-- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/openparse/processing/basic_transforms.py b/src/openparse/processing/basic_transforms.py index 5070c1d..88fbe82 100644 --- a/src/openparse/processing/basic_transforms.py +++ b/src/openparse/processing/basic_transforms.py @@ -109,11 +109,13 @@ def process(self, nodes: List[Node]) -> List[Node]: for page, page_nodes in nodes_by_page.items(): image_nodes = [e for e in page_nodes if e.variant == {"image"}] if image_nodes: - image_elements = get_elements_of_type(image_nodes, ImageElement) + image_elements = get_elements_of_type( + image_nodes, ImageElement) text_elements = get_elements_of_type(page_nodes, TextElement) combined_image = self._combine_images_in_group(image_elements) - new_nodes.append(Node(elements=(combined_image, *text_elements))) + new_nodes.append( + Node(elements=(combined_image, *text_elements))) else: new_nodes.extend(page_nodes) return new_nodes @@ -130,7 +132,8 @@ def process(self, nodes: List[Node]) -> List[Node]: for node in nodes: if node.variant == {"table"}: for table_element in node.elements: - tables_by_page[table_element.page].append(table_element.bbox) + tables_by_page[table_element.page].append( + table_element.bbox) updated_nodes = [] for node in nodes: @@ -148,7 +151,6 @@ def process(self, nodes: List[Node]) -> List[Node]: ) if should_include: new_elements.append(element) - if new_elements and len(new_elements) != len(node.elements): updated_nodes.append(Node(elements=tuple(new_elements))) elif len(new_elements) == len(node.elements): diff --git a/src/openparse/tables/parse.py b/src/openparse/tables/parse.py index 960c8de..be08649 100644 --- a/src/openparse/tables/parse.py +++ b/src/openparse/tables/parse.py @@ -254,12 +254,19 @@ def _ingest_with_pdfplumber( table_bounding_box = table.bbox table_data = table.extract() table_markdown = pdf_plumber_table_data_to_markdown(table_data) + # the application seems to use pdfminer style coordinates system, let make sure their are align with the pdfplumber ones. + + # check this discussion https://github.com/jsvine/pdfplumber/issues/198 + # table bounding 3 is the bottom + # table bounding 1 is the top + y0 = page.height - table_bounding_box[3] + y1 = page.height - table_bounding_box[1] table_bbox = Bbox( page=page_number, x0=table_bounding_box[0], - y0=table_bounding_box[1], + y0=y0, x1=table_bounding_box[2], - y1=table_bounding_box[3], + y1=y1, page_width=page.width, page_height=page.height) table_element = TableElement( From 681617b23873da5f54493eece44605d599c6941d Mon Sep 17 00:00:00 2001 From: Espoir Murhabazi Date: Wed, 24 Sep 2025 16:01:29 +0100 Subject: [PATCH 4/8] remove pdf --- src/evals/data/full-pdfs/Response_Letter.pdf | Bin 131 -> 0 bytes .../data/full-pdfs/attention-is-all-you-need.pdf | Bin 132 -> 0 bytes .../data/full-pdfs/insurance-product-guide.pdf | Bin 131 -> 0 bytes src/evals/data/full-pdfs/meta-2022-10k.pdf | Bin 132 -> 0 bytes src/evals/data/full-pdfs/mobile-home-manual.pdf | Bin 130 -> 0 bytes src/evals/data/full-pdfs/mock-1-page-lease.pdf | Bin 130 -> 0 bytes .../data/full-pdfs/summary-of-rate-indication.pdf | Bin 131 -> 0 bytes 7 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/evals/data/full-pdfs/Response_Letter.pdf delete mode 100644 src/evals/data/full-pdfs/attention-is-all-you-need.pdf delete mode 100644 src/evals/data/full-pdfs/insurance-product-guide.pdf delete mode 100644 src/evals/data/full-pdfs/meta-2022-10k.pdf delete mode 100644 src/evals/data/full-pdfs/mobile-home-manual.pdf delete mode 100644 src/evals/data/full-pdfs/mock-1-page-lease.pdf delete mode 100644 src/evals/data/full-pdfs/summary-of-rate-indication.pdf diff --git a/src/evals/data/full-pdfs/Response_Letter.pdf b/src/evals/data/full-pdfs/Response_Letter.pdf deleted file mode 100644 index 04c0462ac5e3b99ae4bd53aceb368f1b8d28d475..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 131 zcmWN{K@P$o5J1s=Pr(H&lmQC8&B)9MiAp2bg{PO*PhS4TpI+Nrl`+nKX#J?;_LRQP zmhXMd?WOz4Szp`IDyd%3`fw0i>&?!Fm_VXS$PO_=j)KYhy8gIA# zq%F_4;-hAD88JtZ+!HvzQ%kAl5Wz!0*CJqUhHM}x2@2k2t&W6LlXVswMDp6_KQW9-H}+Ppo>Sgz|g zExEtUI3%0Xsoq$R8eyXy__BD*aV04pP`o7y%+YhS;t4T|#Wkhu01-WB4j?H-pgSg~ MM*E500-z)H2O2~t^#A|> diff --git a/src/evals/data/full-pdfs/meta-2022-10k.pdf b/src/evals/data/full-pdfs/meta-2022-10k.pdf deleted file mode 100644 index 15efdeacc212ebc507f441fdc3de2d26c18d57a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 132 zcmWN?OA^8$3;@tQr|1PNP0A<0r%b diff --git a/src/evals/data/full-pdfs/mobile-home-manual.pdf b/src/evals/data/full-pdfs/mobile-home-manual.pdf deleted file mode 100644 index 493cd73e2f9a8ceb55ca2d34d18ac43962e1fcf5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 130 zcmWN`K@!3s3;@78uiyg~LIAP9p^ykODjh?6@b&hzhdt>leSCDAbC=baXP>th%W~O{ zZ7JhzWT#?IP@`8ZExQm`elTRT6~KDS8zKQ#Of|dAz@_*YDfp`s1#tI334v{lAy6#@ MMM?jWb{-t6Kk5%Bb^rhX diff --git a/src/evals/data/full-pdfs/mock-1-page-lease.pdf b/src/evals/data/full-pdfs/mock-1-page-lease.pdf deleted file mode 100644 index 4baf697612293b5efd6b72b6cbe020aeb08e84ed..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 130 zcmWN?%MrpL5CG6SRnUL|c3Hr5v;2e^m5h)atX|*cUF9?Tc+0ldF?XdNechgQZvWdE zw=`aA9wn*Eh|#m0je*?Gn#p)Xq!_c!nt*@-Avu?zLIh6?C3=13;@tQr{DsWPZERPMgtUP+Ts*+(bLz}n|GyeukEAD7)M`?dDiiG Date: Wed, 24 Sep 2025 16:02:46 +0100 Subject: [PATCH 5/8] remove more pdf --- .../meta-2022-10k-bullets-across-pages.pdf | Bin 130 -> 0 bytes .../meta-2022-10k-long-bullets.pdf | Bin 130 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/evals/data/specific-examples/meta-2022-10k-bullets-across-pages.pdf delete mode 100644 src/evals/data/specific-examples/meta-2022-10k-long-bullets.pdf diff --git a/src/evals/data/specific-examples/meta-2022-10k-bullets-across-pages.pdf b/src/evals/data/specific-examples/meta-2022-10k-bullets-across-pages.pdf deleted file mode 100644 index 77936a1c0745d4e3b5ef0cd26f40f9f5920f74a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 130 zcmWN?OA^8$3;@tQr{Dq>LMSx74WA&)sB}#2!qe;9yo=v5=1ceUJY+ZKKF-^t$@0H{ z@>1s0$ic;2pysGrdU9*n{hDF3wL;0Z)yz3Epv|GhWQoZY=Su*BfC(@VB2g`DnXw_b NRF#Y`>&;V)>IeE-C&2&! diff --git a/src/evals/data/specific-examples/meta-2022-10k-long-bullets.pdf b/src/evals/data/specific-examples/meta-2022-10k-long-bullets.pdf deleted file mode 100644 index bad907572618acf13adfc3c90136640f8d08bdab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 130 zcmWN?K@!3s3;@7;U%>|~2^0wZ4S`gcQRxWw;OliSd&zsW{!(?$bL?8*+q^xFvHq_g zUUPryaZ1(~F1-~sYBJ962swC?5RruiHwG&O$Qv|)GNc$lXmcDOGEx$B-g30290|lz MSw{Pcau&!fKhF^-0{{R3 From c62f5dd770dbdb1bc62929557b265b371d2c5f67 Mon Sep 17 00:00:00 2001 From: Espoir Murhabazi Date: Wed, 24 Sep 2025 16:04:48 +0100 Subject: [PATCH 6/8] remove more pdf --- src/evals/data/tables/H3_Scorecard_Mock.pdf | Bin 130 -> 0 bytes .../data/tables/OH_Condo_TerrBaseRates_Mock.pdf | Bin 130 -> 0 bytes .../data/tables/OH_Home_Profit-Loss_thru_2015.pdf | Bin 130 -> 0 bytes ...F_HO_Actuarial_Justification_5.20.17_DRAFT.pdf | Bin 131 -> 0 bytes src/evals/data/tables/loss-trend-severity.pdf | Bin 131 -> 0 bytes src/evals/data/tables/meta-2022-10k-page-53.pdf | Bin 131 -> 0 bytes src/evals/data/tables/meta-2022-10k-page-69.pdf | Bin 130 -> 0 bytes .../naic-numerical-list-of-companies-page-94.pdf | Bin 130 -> 0 bytes .../data/tables/underwriting-loss-and-profit.pdf | Bin 131 -> 0 bytes 9 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/evals/data/tables/H3_Scorecard_Mock.pdf delete mode 100644 src/evals/data/tables/OH_Condo_TerrBaseRates_Mock.pdf delete mode 100644 src/evals/data/tables/OH_Home_Profit-Loss_thru_2015.pdf delete mode 100644 src/evals/data/tables/OH_SAF_HO_Actuarial_Justification_5.20.17_DRAFT.pdf delete mode 100644 src/evals/data/tables/loss-trend-severity.pdf delete mode 100644 src/evals/data/tables/meta-2022-10k-page-53.pdf delete mode 100644 src/evals/data/tables/meta-2022-10k-page-69.pdf delete mode 100644 src/evals/data/tables/naic-numerical-list-of-companies-page-94.pdf delete mode 100644 src/evals/data/tables/underwriting-loss-and-profit.pdf diff --git a/src/evals/data/tables/H3_Scorecard_Mock.pdf b/src/evals/data/tables/H3_Scorecard_Mock.pdf deleted file mode 100644 index 22a1d91d933b71d1b6147baa6c20ec79aa4b9aee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 130 zcmWN?OA^8$3;@tQr{DsXCj3fo(}W<*sB{Fo@bvmN?~?au{iW-i=h%(8w|RS%vHY(e zTDU*WIEBpxs<*61J!45CFiODrmss|I`f}hhfGx8Xr>N>aA#_z3@w8et2K&pk0XPSdUku?Y5s~ zgZUP8Ac#w`IVz`~wex$n3ANTfL})S?3&yzQH9!s$T(;;i2bH`m#;7W7Dj2JZ#oVPe NpBRlFawlU7><`J?CguPD diff --git a/src/evals/data/tables/OH_Home_Profit-Loss_thru_2015.pdf b/src/evals/data/tables/OH_Home_Profit-Loss_thru_2015.pdf deleted file mode 100644 index afbfd5c7ba5fc932fe950eada4046736d79304b2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 130 zcmWN?%MpVh5CG6SRnS1>yDr)dEK6V}2~I!{sXo5TyZAd=|HwM$F?OY%Z9ZOQEcf+H z3-z}e2a~#t=q<}pqlI~4jFyJ^A4?c0$!DUR&nvDu+&bS$k{vJJTp?HE~N=6;o Mi_v~8Er4CcAJ|VPb^rhX diff --git a/src/evals/data/tables/OH_SAF_HO_Actuarial_Justification_5.20.17_DRAFT.pdf b/src/evals/data/tables/OH_SAF_HO_Actuarial_Justification_5.20.17_DRAFT.pdf deleted file mode 100644 index cd62c23065bd849eac9957e7d6e27db87875af7b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 131 zcmWN?OA^8$3;@tQr{Dq>LQR0)hF^pkm5yn<@bvmN?`j_z^R4@F?6Mj27{~3&vi$F7 zUdntK*;_Fes5z>Zo*dFfYoLI!W-b7sVu;+3eL>D>IT1MvHj*#4fvtg7NFlmPF;|W$ NIVI!Uw6}LeQa=RpCx!q3 diff --git a/src/evals/data/tables/loss-trend-severity.pdf b/src/evals/data/tables/loss-trend-severity.pdf deleted file mode 100644 index 609e48f1a5cf5cc0e0e06515b1e4d4dd9469edda..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 131 zcmWN{xe>!45CFiODrmssy#v$@uVKbE8Xr>N>aA##z3P|7{P4ckLAwyou^z8R+igG7 zmgig0QM0%do1<{*Q3LMEHfPZL6fmKarWmwX!RlaRD=8|d;Ltd*cQewX3O)oCgY(${ NI!5DHxwfE{WPihOC9?nk diff --git a/src/evals/data/tables/meta-2022-10k-page-53.pdf b/src/evals/data/tables/meta-2022-10k-page-53.pdf deleted file mode 100644 index a81422c2957a910cda857d9101272ecc00960c00..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 131 zcmWN?K@!3s3;@7;U%>|~1PI0c29hAmsC0z(;OliSd&y_C{#JF)W9(W#+Ppo>SpU~E zuhd_9976hnr8iciCW~P=-Xz&9XHU-3y=;!56hk5sFiQ%^k!*nyT}}{Da%K)31yO>t NVHxc!3c!KK!5CFhCuiyg)hG9#7Gb|%isiXvR@b%i4zUq7S@se$=a~?|F`?@`NZvWdS zZFxM^JZn}Lh|!Cjjg0e0HYT${igpLkuI`97a^6eQ&PC$jsaD52hG+qiGZmkJLIA+T N2x9hcmC6H0{M20{>KR62rPczWyVzxju}N9!+L=iJ9;%)QOaqm1Qj z{iKEa(~Mo%9H4s3den%HHtU2!^5g(X7;o%F0#mlxTFV>~h+Jclf)Q6rPy!-)IK6uG MY}IIA(eQuj2kcZQH~;_u diff --git a/src/evals/data/tables/underwriting-loss-and-profit.pdf b/src/evals/data/tables/underwriting-loss-and-profit.pdf deleted file mode 100644 index 16f9db11879543182865ab91a1bb902cb5a37fd0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 131 zcmWN?K@x)?3;@8puiyif00zb1KmvuCwm1!X=ywCw%|_ From 5225383ad5ca3afb9782a0fcf8dd59adc2db5d60 Mon Sep 17 00:00:00 2001 From: Espoir Murhabazi Date: Wed, 24 Sep 2025 16:08:17 +0100 Subject: [PATCH 7/8] remove all pdf --- src/tests/sample_data/europe.jpg | Bin 16457 -> 0 bytes src/tests/sample_data/pdf-with-image.pdf | Bin 130 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/tests/sample_data/europe.jpg delete mode 100644 src/tests/sample_data/pdf-with-image.pdf diff --git a/src/tests/sample_data/europe.jpg b/src/tests/sample_data/europe.jpg deleted file mode 100644 index ea9ef34198915bcb73a504c9caf80be9b4ae8891..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16457 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 Vk}5nH6ltbDrGHQ7htBQ7{{cL}E@S`z diff --git a/src/tests/sample_data/pdf-with-image.pdf b/src/tests/sample_data/pdf-with-image.pdf deleted file mode 100644 index da89750aeef95c5fa702acac2a6c2852440611db..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 130 zcmWN|K@!3s3;@78uiyg~LIY@jLjnjhDjh?6@b&hzr#;J8`uONJ=PsKu&pvOjD$8X% zXyNfTvKKZdsL`{QmYfe82MiEtC1frxC*l-cjfvo%&;nFU5wk-F**=I0R)p-mE!Xhb NvXcHQI=Hxk`U40HC-?vW From 9219f6e8f3d169569c9ccc7cc115a2965da65bc1 Mon Sep 17 00:00:00 2001 From: Espoir Murhabazi Date: Wed, 24 Sep 2025 16:12:30 +0100 Subject: [PATCH 8/8] add back the pdf --- src/evals/data/full-pdfs/Response_Letter.pdf | Bin 0 -> 131 bytes .../full-pdfs/attention-is-all-you-need.pdf | Bin 0 -> 132 bytes .../data/full-pdfs/insurance-product-guide.pdf | Bin 0 -> 131 bytes src/evals/data/full-pdfs/meta-2022-10k.pdf | Bin 0 -> 132 bytes src/evals/data/full-pdfs/mobile-home-manual.pdf | Bin 0 -> 130 bytes src/evals/data/full-pdfs/mock-1-page-lease.pdf | Bin 0 -> 130 bytes .../full-pdfs/summary-of-rate-indication.pdf | Bin 0 -> 131 bytes .../meta-2022-10k-bullets-across-pages.pdf | Bin 0 -> 130 bytes .../meta-2022-10k-long-bullets.pdf | Bin 0 -> 130 bytes src/evals/data/tables/H3_Scorecard_Mock.pdf | Bin 0 -> 130 bytes .../data/tables/OH_Condo_TerrBaseRates_Mock.pdf | Bin 0 -> 130 bytes .../tables/OH_Home_Profit-Loss_thru_2015.pdf | Bin 0 -> 130 bytes ...HO_Actuarial_Justification_5.20.17_DRAFT.pdf | Bin 0 -> 131 bytes src/evals/data/tables/loss-trend-severity.pdf | Bin 0 -> 131 bytes src/evals/data/tables/meta-2022-10k-page-53.pdf | Bin 0 -> 131 bytes src/evals/data/tables/meta-2022-10k-page-69.pdf | Bin 0 -> 130 bytes ...naic-numerical-list-of-companies-page-94.pdf | Bin 0 -> 130 bytes .../tables/underwriting-loss-and-profit.pdf | Bin 0 -> 131 bytes src/tests/sample_data/europe.jpg | Bin 0 -> 16457 bytes src/tests/sample_data/pdf-with-image.pdf | Bin 0 -> 130 bytes src/tests/tables/pymupdf/test_parse.py | 6 ++++-- 21 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 src/evals/data/full-pdfs/Response_Letter.pdf create mode 100644 src/evals/data/full-pdfs/attention-is-all-you-need.pdf create mode 100644 src/evals/data/full-pdfs/insurance-product-guide.pdf create mode 100644 src/evals/data/full-pdfs/meta-2022-10k.pdf create mode 100644 src/evals/data/full-pdfs/mobile-home-manual.pdf create mode 100644 src/evals/data/full-pdfs/mock-1-page-lease.pdf create mode 100644 src/evals/data/full-pdfs/summary-of-rate-indication.pdf create mode 100644 src/evals/data/specific-examples/meta-2022-10k-bullets-across-pages.pdf create mode 100644 src/evals/data/specific-examples/meta-2022-10k-long-bullets.pdf create mode 100644 src/evals/data/tables/H3_Scorecard_Mock.pdf create mode 100644 src/evals/data/tables/OH_Condo_TerrBaseRates_Mock.pdf create mode 100644 src/evals/data/tables/OH_Home_Profit-Loss_thru_2015.pdf create mode 100644 src/evals/data/tables/OH_SAF_HO_Actuarial_Justification_5.20.17_DRAFT.pdf create mode 100644 src/evals/data/tables/loss-trend-severity.pdf create mode 100644 src/evals/data/tables/meta-2022-10k-page-53.pdf create mode 100644 src/evals/data/tables/meta-2022-10k-page-69.pdf create mode 100644 src/evals/data/tables/naic-numerical-list-of-companies-page-94.pdf create mode 100644 src/evals/data/tables/underwriting-loss-and-profit.pdf create mode 100644 src/tests/sample_data/europe.jpg create mode 100644 src/tests/sample_data/pdf-with-image.pdf diff --git a/src/evals/data/full-pdfs/Response_Letter.pdf b/src/evals/data/full-pdfs/Response_Letter.pdf new file mode 100644 index 0000000000000000000000000000000000000000..04c0462ac5e3b99ae4bd53aceb368f1b8d28d475 GIT binary patch literal 131 zcmWN{K@P$o5J1s=Pr(H&lmQC8&B)9MiAp2bg{PO*PhS4TpI+Nrl`+nKX#J?;_LRQP zmhXMd?WOz4Szp`IDyd%3`fw0i>&?!Fm_VXS$PO_=j)KYhy8gIA# zq%F_4;-hAD88JtZ+!HvzQ%kAl5Wz!0*CJqUhHM}x2@2k2t&W6LlXVswMDp6_KQW9-H}+Ppo>Sgz|g zExEtUI3%0Xsoq$R8eyXy__BD*aV04pP`o7y%+YhS;t4T|#Wkhu01-WB4j?H-pgSg~ MM*E500-z)H2O2~t^#A|> literal 0 HcmV?d00001 diff --git a/src/evals/data/full-pdfs/meta-2022-10k.pdf b/src/evals/data/full-pdfs/meta-2022-10k.pdf new file mode 100644 index 0000000000000000000000000000000000000000..15efdeacc212ebc507f441fdc3de2d26c18d57a6 GIT binary patch literal 132 zcmWN?OA^8$3;@tQr|1PNP0A<0r%b literal 0 HcmV?d00001 diff --git a/src/evals/data/full-pdfs/mobile-home-manual.pdf b/src/evals/data/full-pdfs/mobile-home-manual.pdf new file mode 100644 index 0000000000000000000000000000000000000000..493cd73e2f9a8ceb55ca2d34d18ac43962e1fcf5 GIT binary patch literal 130 zcmWN`K@!3s3;@78uiyg~LIAP9p^ykODjh?6@b&hzhdt>leSCDAbC=baXP>th%W~O{ zZ7JhzWT#?IP@`8ZExQm`elTRT6~KDS8zKQ#Of|dAz@_*YDfp`s1#tI334v{lAy6#@ MMM?jWb{-t6Kk5%Bb^rhX literal 0 HcmV?d00001 diff --git a/src/evals/data/full-pdfs/mock-1-page-lease.pdf b/src/evals/data/full-pdfs/mock-1-page-lease.pdf new file mode 100644 index 0000000000000000000000000000000000000000..4baf697612293b5efd6b72b6cbe020aeb08e84ed GIT binary patch literal 130 zcmWN?%MrpL5CG6SRnUL|c3Hr5v;2e^m5h)atX|*cUF9?Tc+0ldF?XdNechgQZvWdE zw=`aA9wn*Eh|#m0je*?Gn#p)Xq!_c!nt*@-Avu?zLIh6?C3=13;@tQr{DsWPZERPMgtUP+Ts*+(bLz}n|GyeukEAD7)M`?dDiiGLMSx74WA&)sB}#2!qe;9yo=v5=1ceUJY+ZKKF-^t$@0H{ z@>1s0$ic;2pysGrdU9*n{hDF3wL;0Z)yz3Epv|GhWQoZY=Su*BfC(@VB2g`DnXw_b NRF#Y`>&;V)>IeE-C&2&! literal 0 HcmV?d00001 diff --git a/src/evals/data/specific-examples/meta-2022-10k-long-bullets.pdf b/src/evals/data/specific-examples/meta-2022-10k-long-bullets.pdf new file mode 100644 index 0000000000000000000000000000000000000000..bad907572618acf13adfc3c90136640f8d08bdab GIT binary patch literal 130 zcmWN?K@!3s3;@7;U%>|~2^0wZ4S`gcQRxWw;OliSd&zsW{!(?$bL?8*+q^xFvHq_g zUUPryaZ1(~F1-~sYBJ962swC?5RruiHwG&O$Qv|)GNc$lXmcDOGEx$B-g30290|lz MSw{Pcau&!fKhF^-0{{R3 literal 0 HcmV?d00001 diff --git a/src/evals/data/tables/H3_Scorecard_Mock.pdf b/src/evals/data/tables/H3_Scorecard_Mock.pdf new file mode 100644 index 0000000000000000000000000000000000000000..22a1d91d933b71d1b6147baa6c20ec79aa4b9aee GIT binary patch literal 130 zcmWN?OA^8$3;@tQr{DsXCj3fo(}W<*sB{Fo@bvmN?~?au{iW-i=h%(8w|RS%vHY(e zTDU*WIEBpxs<*61J!45CFiODrmss|I`f}hhfGx8Xr>N>aA#_z3@w8et2K&pk0XPSdUku?Y5s~ zgZUP8Ac#w`IVz`~wex$n3ANTfL})S?3&yzQH9!s$T(;;i2bH`m#;7W7Dj2JZ#oVPe NpBRlFawlU7><`J?CguPD literal 0 HcmV?d00001 diff --git a/src/evals/data/tables/OH_Home_Profit-Loss_thru_2015.pdf b/src/evals/data/tables/OH_Home_Profit-Loss_thru_2015.pdf new file mode 100644 index 0000000000000000000000000000000000000000..afbfd5c7ba5fc932fe950eada4046736d79304b2 GIT binary patch literal 130 zcmWN?%MpVh5CG6SRnS1>yDr)dEK6V}2~I!{sXo5TyZAd=|HwM$F?OY%Z9ZOQEcf+H z3-z}e2a~#t=q<}pqlI~4jFyJ^A4?c0$!DUR&nvDu+&bS$k{vJJTp?HE~N=6;o Mi_v~8Er4CcAJ|VPb^rhX literal 0 HcmV?d00001 diff --git a/src/evals/data/tables/OH_SAF_HO_Actuarial_Justification_5.20.17_DRAFT.pdf b/src/evals/data/tables/OH_SAF_HO_Actuarial_Justification_5.20.17_DRAFT.pdf new file mode 100644 index 0000000000000000000000000000000000000000..cd62c23065bd849eac9957e7d6e27db87875af7b GIT binary patch literal 131 zcmWN?OA^8$3;@tQr{Dq>LQR0)hF^pkm5yn<@bvmN?`j_z^R4@F?6Mj27{~3&vi$F7 zUdntK*;_Fes5z>Zo*dFfYoLI!W-b7sVu;+3eL>D>IT1MvHj*#4fvtg7NFlmPF;|W$ NIVI!Uw6}LeQa=RpCx!q3 literal 0 HcmV?d00001 diff --git a/src/evals/data/tables/loss-trend-severity.pdf b/src/evals/data/tables/loss-trend-severity.pdf new file mode 100644 index 0000000000000000000000000000000000000000..609e48f1a5cf5cc0e0e06515b1e4d4dd9469edda GIT binary patch literal 131 zcmWN{xe>!45CFiODrmssy#v$@uVKbE8Xr>N>aA##z3P|7{P4ckLAwyou^z8R+igG7 zmgig0QM0%do1<{*Q3LMEHfPZL6fmKarWmwX!RlaRD=8|d;Ltd*cQewX3O)oCgY(${ NI!5DHxwfE{WPihOC9?nk literal 0 HcmV?d00001 diff --git a/src/evals/data/tables/meta-2022-10k-page-53.pdf b/src/evals/data/tables/meta-2022-10k-page-53.pdf new file mode 100644 index 0000000000000000000000000000000000000000..a81422c2957a910cda857d9101272ecc00960c00 GIT binary patch literal 131 zcmWN?K@!3s3;@7;U%>|~1PI0c29hAmsC0z(;OliSd&y_C{#JF)W9(W#+Ppo>SpU~E zuhd_9976hnr8iciCW~P=-Xz&9XHU-3y=;!56hk5sFiQ%^k!*nyT}}{Da%K)31yO>t NVHxc!3c!KK!5CFhCuiyg)hG9#7Gb|%isiXvR@b%i4zUq7S@se$=a~?|F`?@`NZvWdS zZFxM^JZn}Lh|!Cjjg0e0HYT${igpLkuI`97a^6eQ&PC$jsaD52hG+qiGZmkJLIA+T N2x9hcmC6H0{M20{>KR62rPczWyVzxju}N9!+L=iJ9;%)QOaqm1Qj z{iKEa(~Mo%9H4s3den%HHtU2!^5g(X7;o%F0#mlxTFV>~h+Jclf)Q6rPy!-)IK6uG MY}IIA(eQuj2kcZQH~;_u literal 0 HcmV?d00001 diff --git a/src/evals/data/tables/underwriting-loss-and-profit.pdf b/src/evals/data/tables/underwriting-loss-and-profit.pdf new file mode 100644 index 0000000000000000000000000000000000000000..16f9db11879543182865ab91a1bb902cb5a37fd0 GIT binary patch literal 131 zcmWN?K@x)?3;@8puiyif00zb1KmvuCwm1!X=ywCw%|_ literal 0 HcmV?d00001 diff --git a/src/tests/sample_data/europe.jpg b/src/tests/sample_data/europe.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ea9ef34198915bcb73a504c9caf80be9b4ae8891 GIT binary patch literal 16457 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 Vk}5nH6ltbDrGHQ7htBQ7{{cL}E@S`z literal 0 HcmV?d00001 diff --git a/src/tests/sample_data/pdf-with-image.pdf b/src/tests/sample_data/pdf-with-image.pdf new file mode 100644 index 0000000000000000000000000000000000000000..da89750aeef95c5fa702acac2a6c2852440611db GIT binary patch literal 130 zcmWN|K@!3s3;@78uiyg~LIY@jLjnjhDjh?6@b&hzr#;J8`uONJ=PsKu&pvOjD$8X% zXyNfTvKKZdsL`{QmYfe82MiEtC1frxC*l-cjfvo%&;nFU5wk-F**=I0R)p-mE!Xhb NvXcHQI=Hxk`U40HC-?vW literal 0 HcmV?d00001 diff --git a/src/tests/tables/pymupdf/test_parse.py b/src/tests/tables/pymupdf/test_parse.py index d0f99a0..9d90502 100644 --- a/src/tests/tables/pymupdf/test_parse.py +++ b/src/tests/tables/pymupdf/test_parse.py @@ -11,7 +11,8 @@ def test_parse_output_to_markdown(): "| 2022 | 100,000 | 50,000 |\n" "| 2021 | 90,000 | 45,000 |\n" ) - assert output_to_markdown(headers, rows) == expected_output, "Standard case failed" + assert output_to_markdown( + headers, rows) == expected_output, "Standard case failed" # Case with missing values headers = ["Year", "Revenue", "Expenses"] @@ -48,7 +49,8 @@ def test_output_to_html(): "202190,00045,000\n" "" ) - assert output_to_html(headers, rows) == expected_output, "Standard case failed" + assert output_to_html( + headers, rows) == expected_output, "Standard case failed" # Case with missing values headers = ["Year", "Revenue", "Expenses"]