{"slug": "unlimited-ocr-2-rejoins-tables-split-across-pdf-pages", "title": "Unlimited-OCR-2 rejoins tables split across PDF pages", "summary": "Baidu's open-source Unlimited-OCR-2 document parsing model reads multiple PDF pages in a single request, returning tables that span page breaks as one table instead of two, according to a hands-on test by Khuyen Tran, Senior DevRel at OpenTeams. In Baidu's tests at 100 pages, each word was 7 times faster to write than with a read-every-page approach, and the model runs on NVIDIA GPUs via Baidu's Transformers code or on Apple Silicon Macs through the mlx-vlm conversion (pip install mlx-vlm==0.7.11). Tran tested it on the Federal Reserve's 214-page 2024 Annual Report, where Table 5.3 starts on page 71 and continues on page 72, and contrasted it with DeepSeek-OCR-2, which reads one page per request and returns the split table as two tables requiring manual cleanup.", "body_md": "# Parse Long PDFs Without Breaking Tables Using Unlimited-OCR-2\n\nUnlimited-OCR-2 reads many PDF pages in one request, so tables split across pages come back as one table. See how it compares to page-by-page OCR.\n\n[Khuyen TranSenior DevRel at OpenTeams](https://openteams.com/engineering-blog/author/khuyen-tran/)\n\nIf you run OCR on a long PDF report, a table that spans two pages may come back as two separate tables instead of one. This happens because most OCR models read one page at a time, so they can't tell that a table on one page continues onto the next.\n\nUnlimited-OCR-2 solves this by reading many pages in one request, so a table split across pages comes back as one table.\n\nIt scores well on [long-document benchmarks](https://huggingface.co/baidu/Unlimited-OCR-2/blob/main/Unlimited-OCR-2.pdf), but benchmarks don't always reflect real-world documents. So I tested it on a long PDF report to see how good it is in practice.\n\n💻 **Get the Code**: The scripts for every example are on [GitHub](https://github.com/khuyentran1401/codecut-blog/tree/main/unlimited-ocr-2-vs-deepseek-ocr-2).\n\n[Unlimited-OCR-2](https://huggingface.co/baidu/Unlimited-OCR-2) is an open-source document parsing model from Baidu. It is built on DeepSeek-OCR and has the same size as [DeepSeek-OCR-2](https://huggingface.co/deepseek-ai/DeepSeek-OCR-2). The main difference between them is how they read a document.\n\nDeepSeek-OCR-2 reads one page per request, while Unlimited-OCR-2 reads many pages in one request:\n\nThe obvious way to let a model see across a page break is to have it look at every page while it writes. But then the model would reread every page before writing each word, which gets very slow for long documents.\n\nUnlimited-OCR-2 avoids this slowdown by:\n\nBecause the number of bands it reads in full stays small no matter how long the document is, each word gets only a little slower to write as you add pages. In Baidu's tests at 100 pages, each word was 7 times faster to write than with the read-every-page approach.\n\nTo see how well this works, I ran DeepSeek-OCR-2 and Unlimited-OCR-2 on several tables that span multiple pages. Both models are built on DeepSeek-OCR and have the same size, so differences in their outputs come mostly from whether they read across page breaks.\n\nUnlimited-OCR-2 runs on an NVIDIA GPU through Baidu's Transformers code, or on an Apple Silicon Mac through the MLX conversion in [mlx-vlm](https://github.com/Blaizzy/mlx-vlm). This article uses the Mac path, but the outputs are the same format on both.\n\nOn a Mac:\n\n```\npip install mlx-vlm==0.7.11\n```\n\nOn an NVIDIA GPU, follow the [model card's Transformers setup](https://huggingface.co/baidu/Unlimited-OCR-2#transformers).\n\nThe first test is the simplest: give the model the two pages around one split table, and see whether it can recognize them as one table.\n\nThe tests use the [Federal Reserve's 2024 Annual Report](https://www.federalreserve.gov/publications/files/2024-annual-report.pdf), a 214-page report with many tables that cross a page break. Its Table 5.3 starts on page 71 and continues on page 72, with its header repeated.\n\nA page-by-page model like DeepSeek-OCR-2 parses each page separately, so these two pages come back as two tables. The first one ends at the bottom of page 71:\n\n| Item | 2024 | 2023 | \n|---|---|---|\n| ... |  |  | \n| For currency costs | 1,242 | 1,047 | \n| For Consumer Financial Protection Bureau costs | 663 | 721 | \n\nThe second one starts with the page title and the header as ordinary rows:\n\n| Table 5.3—continued |  |  | \n|---|---|---|\n| Item | 2024 | 2023 | \n| Reserve Bank net (loss) from operations | -77,606 | -114,386 | \n| Consolidated variable interest entities: Income, net | 22 | 1,124 | \n| ... |  |  | \n\nBefore you can use the table, you have to delete the extra title and header rows from the second table, then join the two tables yourself.\n\nNow let's try Unlimited-OCR-2. Pass both page images to `mlx_vlm.generate` in one call, with the prompt `Multi page parsing.`:\n\n```\nmlx_vlm.generate --model mlx-community/Unlimited-OCR-2-8bit \\\n  --image p071.png p072.png \\\n  --prompt \"Multi page parsing.\" --max-tokens 8000\n```\n\nThis prints one `<PAGE>` section per image, each containing a list of blocks. The model uses the label `append_table` to indicate that the table on page 72 is a continuation of the table on page 71.\n\n```\n<PAGE>                                                        <- page 71\n<BLOCK>table[144, 460, 855, 817]<FORK><table>...\n<PAGE>                                                        <- page 72\n<BLOCK>append_table[145, 137, 855, 535]<FORK><table>...       <- continues the table above\n```\n\nThe raw output is hard to read, so I use Baidu's [Markdown converter](https://github.com/baidu/Unlimited-OCR/tree/main/utils). It uses the `append_table` label to join the two halves into one table. Here are the rows around the page break:\n\nThe two halves are merged into one table, with no repeated header between them.\n\nLet's make the test harder by running the model on a table that spans four pages (Table G.10).\n\nDeepSeek-OCR-2 returns four separate tables, one per page.\n\nUnlimited-OCR-2 returns one table for all four pages, with only one repeated header row left between 1986 and 1987:\n\nThe result isn't perfect, but deleting one row is far less work than cleaning and joining four separate tables.\n\nPage breaks cut paragraphs in half too. Let's see whether the model can rejoin them.\n\nFor this test, I switched to a different report. This paragraph in the Federal Reserve's [June 2025 Monetary Policy Report](https://www.federalreserve.gov/monetarypolicy/files/20250620_mprfullreport.pdf) stops at \"highly accommodative\" on page 54 and continues on page 55:\n\nDeepSeek-OCR-2 leaves the sentence split, with the box title from page 55 in the middle:\n\n```\n...called for highly accommodative                                <- end of page 54\n\nBox 4—continued                                                   <- box title repeated on page 55\n\nmonetary policy in response to the pandemic-driven recession...   <- start of page 55\n```\n\nUnlimited-OCR-2 returns one paragraph but loses the space at the page break:\n\n```\n...called for highly accommodativemonetary policy in response to the pandemic-driven recession...\n                                  ^ space lost at the page break\n```\n\nI also tested two other paragraph breaks, and Unlimited-OCR-2 left both sentences split, just like DeepSeek-OCR-2. So paragraph merging seems less reliable than table merging.\n\nSo far, I gave the model only the few pages around one break. In practice, you would send a whole section of a report and let the model find the breaks.\n\nLet's test how well the model can find breaks in longer requests by sending 10- and 30-page chunks of the Annual Report in one request each:\n\n```\nmlx_vlm.generate --model mlx-community/Unlimited-OCR-2-8bit \\\n  --image pages/p185.png pages/p186.png ... pages/p214.png \\\n  --prompt \"Multi page parsing.\" --max-tokens 150000\n```\n\n| Pages per request | Table breaks recognized | \n|---|---|\n| 2 to 4 | 7 of 7 | \n| 10 | 11 of 12 | \n| 30 | 20 of 22 | \n\nUnlimited-OCR-2 recognized most breaks even in 30-page requests.\n\nOn a MacBook Pro with an M5 Pro chip, a 30-page request took 3 to 5.5 minutes and peaked at about 17 GB of memory, so you can parse a long report on a laptop without a GPU server.\n\nFrom my tests, Unlimited-OCR-2 is a great tool for parsing long PDFs. It can read across page breaks and join tables that span multiple pages.\n\nIt also runs on a laptop. With mlx-vlm, a 30-page request fits in about 17 GB of memory, so private documents never leave the machine.\n\nBut how does it perform on single pages? On OmniDocBench v1.6, a single-page benchmark, it scores about 3 points below the best single-page models but above DeepSeek-OCR-2:\n\n| Model | Overall score | \n|---|---|\n| TeleOCR (best) | 96.91 | \n| OvisOCR2 | 96.47 | \n| **Unlimited-OCR-2** | **94.02** | \n| DeepSeek-OCR-2 | 90.25 | \n\nA 3-point gap is small, so if you're not sure whether your documents have page breaks, Unlimited-OCR-2 is a good default.\n\n`Multi page parsing.` prompt.\nBenchmarks, deep dives, and lessons from OpenTeams engineers. Leave your email, or follow the feed.", "url": "https://wpnews.pro/news/unlimited-ocr-2-rejoins-tables-split-across-pdf-pages", "canonical_source": "https://openteams.com/engineering-blog/unlimited-ocr-2-long-pdf-tables/", "published_at": "2026-11-06 01:21:53+00:00", "updated_at": "2026-11-06 01:50:05.268210+00:00", "lang": "en", "topics": ["artificial-intelligence", "ai-research", "ai-tools", "large-language-models", "computer-vision"], "entities": ["Baidu", "Unlimited-OCR-2", "DeepSeek-OCR-2", "DeepSeek-OCR", "Khuyen Tran", "OpenTeams", "mlx-vlm", "Federal Reserve"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/unlimited-ocr-2-rejoins-tables-split-across-pdf-pages", "markdown": "https://wpnews.pro/news/unlimited-ocr-2-rejoins-tables-split-across-pdf-pages.md", "text": "https://wpnews.pro/news/unlimited-ocr-2-rejoins-tables-split-across-pdf-pages.txt", "jsonld": "https://wpnews.pro/news/unlimited-ocr-2-rejoins-tables-split-across-pdf-pages.jsonld"}}