markitdown-ocr + markitdown-sample-plugin

外掛生態的兩個代表:真 OCR 外掛 + 開發範本
檔案:packages/markitdown-ocr/src/ · packages/markitdown-sample-plugin/src/

大方向

markitdown-ocrLLM Vision 對 PDF/DOCX/PPTX/XLSX 內嵌圖片做 OCR, 並以 priority -1.0 註冊在內建之前「攔截」;markitdown-sample-plugin 是官方最小範本,教你三步寫外掛。


1. markitdown-ocr:外掛入口

register_converters(markitdown, **kwargs) _plugin.py建 LLMVisionOCRService 並以 priority -1.0 註冊 4 個 OCR converter。

從 kwargs 取出 llm_client / llm_model / llm_prompt 建 service; 沒有 llm_client 就回傳空 service(OCR 會靜默略過)。四個 converter (PdfConverterWithOCR 等)用 register_converter(priority=-1.0) 註冊——-1.0 < 內建的 0.0,所以先被試到,等同覆寫內建。

2. LLMVisionOCRService(OCR 服務層)

OCRResult / LLMVisionOCRService.__init__ / extract_text _ocr_service.py把圖片 base64 → OpenAI 相容 vision 呼叫 → 回傳文字。

OCRResultdataclass(text + confidence 等); extract_text 組圖像 content 送 LLM,回傳抽取文字。整個外掛 「不新增 ML 函式庫」的承諾就建立在這裡——全部靠既有的 OpenAI 相容 client。

3. 各格式 OCR 增強 converter

PdfConverterWithOCR _pdf_converter_with_ocr.py抽取頁面內嵌圖片逐張 OCR,就地插回文字流。
  • _extract_images_from_page(page) — 依 pdfplumber page XObjects/位置抽圖。
  • _extract_page_images — 依頁索引抽圖。
  • _ocr_full_pages — 掃描版 PDF 偵測(無文字層)時整頁渲染 300 DPI 送 LLM。
  • convert — 正常文字 + 內嵌圖片的 OCR 文字依垂直閱讀順序交錯

輸出以 *[Image OCR]...<text>[End OCR]* 包住,並用 PyMuPDF 重試 malformed PDF。

DocxConverterWithOCR _docx_converter_with_ocr.py在 DOCX→HTML→Markdown 管線前注入 OCR 佔位。

_extract_and_ocr_imagesdoc.part.rels 抽圖並 OCR; _inject_placeholders 把結果換成佔位 token 塞進 HTML,等 mammoth/markdownify 跑完再還原成 *[Image OCR]... 區塊——避免 markdown 轉換器把 OCR 標記轉義掉。

PptxConverterWithOCR / XlsxConverterWithOCR OCR 增強PPTX 依形狀順序 OCR(描述優先、OCR 兜底);XLSX 依錨點座標列圖片。

PPTX 支援 picture shape、placeholder 內圖片、群組內圖片,且「先問 LLM 描述、無描述才 OCR」; XLSX 用 _extract_and_ocr_sheet_images + _column_number_to_letter 把圖片的錨點座標換成 Excel 欄位名,輸出 ### Images in this sheet: 段落。

4. markitdown-sample-plugin(開發範本)

__plugin_interface_version__ / register_converters / RtfConverter _plugin.pyRTF converter 的最小完整範例。

三步就是全部:

  • RtfConverter(DocumentConverter) — 實作 accepts(判斷 RTF)+ convert(轉 Markdown)。
  • __plugin_interface_version__ = 1 — 宣告外掛介面版本(目前只支援 1)。
  • register_converters(markitdown, **kwargs)markitdown.register_converter(RtfConverter())

最後在 pyproject.toml 宣告 entry-point:[project.entry-points."markitdown.plugin"] sample_plugin = "markitdown_sample_plugin"。裝好後 markitdown --list-plugins 就看得到。