Download src/ocr/ovis_cpu_parser.py from gitmodelmujtaba/medical-guidelines-kg: direct link, hf CLI and curl.
- Browser
- Download file 4.07 kB
-
https://huggingface.co/spaces/gitmodelmujtaba/medical-guidelines-kg/resolve/main/src/ocr/ovis_cpu_parser.py
- Command line
-
hf download hf://spaces/gitmodelmujtaba/medical-guidelines-kg/src/ocr/ovis_cpu_parser.py
-
curl -L -o ovis_cpu_parser.py https://huggingface.co/spaces/gitmodelmujtaba/medical-guidelines-kg/resolve/main/src/ocr/ovis_cpu_parser.py
4.07 kB
| """ | |
| ATH-MaaS/OvisOCR2 CPU-Friendly Document Parser. | |
| Parses document page images using OvisOCR2 (0.8B Vision-Language Model) | |
| preserving natural human reading order, HTML tables, LaTeX formulas, and visual bbox tags. | |
| """ | |
| import io | |
| import os | |
| from typing import List, Optional | |
| from src.ocr.base_parser import BaseDocumentParser, ParsedDocument, ParsedPage | |
| try: | |
| from PIL import Image | |
| except ImportError: | |
| Image = None | |
| try: | |
| import pypdfium2 as pdfium | |
| except ImportError: | |
| pdfium = None | |
| class OvisOCR2CPUParser(BaseDocumentParser): | |
| """Parser using ATH-MaaS/OvisOCR2 running on CPU RAM or falling back gracefully.""" | |
| MODEL_ID = "ATH-MaaS/OvisOCR2" | |
| PROMPT = ( | |
| "Extract all readable content from the image in natural human reading order " | |
| "and output the result as a single Markdown document. For charts or images, " | |
| 'represent them using an HTML image tag: <img src="images/bbox_{left}_{top}_{right}_{bottom}.jpg" />. ' | |
| "Format formulas as LaTeX. Format tables as HTML: <table>...</table>. " | |
| "Transcribe all other text as standard Markdown. Preserve the original text without translation or paraphrasing." | |
| ) | |
| def __init__(self, model_path: Optional[str] = None, device: str = "cpu"): | |
| self.model_path = model_path or self.MODEL_ID | |
| self.device = device | |
| self.model = None | |
| self.tokenizer = None | |
| def _lazy_load_model(self): | |
| if self.model is None: | |
| try: | |
| import torch | |
| from transformers import AutoModelForVision2Seq, AutoTokenizer | |
| print(f"Loading OvisOCR2 from {self.model_path} onto {self.device} (RAM-optimized)...") | |
| self.tokenizer = AutoTokenizer.from_pretrained(self.model_path, trust_remote_code=True) | |
| self.model = AutoModelForVision2Seq.from_pretrained( | |
| self.model_path, | |
| torch_dtype=torch.float32, | |
| trust_remote_code=True, | |
| low_cpu_mem_usage=True, | |
| ).to(self.device) | |
| self.model.eval() | |
| except Exception as e: | |
| raise RuntimeError( | |
| f"Failed to load OvisOCR2 model from {self.model_path}. " | |
| f"Ensure transformers, torch, and model weights are accessible. Error: {e}" | |
| ) | |
| def parse(self, file_path: str) -> ParsedDocument: | |
| if not os.path.exists(file_path): | |
| raise FileNotFoundError(f"File not found: {file_path}") | |
| if not pdfium: | |
| raise ImportError("pypdfium2 is required to render PDF pages for OvisOCR2.") | |
| pdf = pdfium.PdfDocument(file_path) | |
| total_pages = len(pdf) | |
| parsed_pages: List[ParsedPage] = [] | |
| full_md_parts: List[str] = [] | |
| self._lazy_load_model() | |
| for page_idx in range(total_pages): | |
| page = pdf[page_idx] | |
| pil_image = page.render(scale=2.0).to_pil() | |
| page_md = self._parse_single_image(pil_image) | |
| parsed_pages.append( | |
| ParsedPage( | |
| page_number=page_idx + 1, | |
| markdown_content=page_md, | |
| bbox_metadata=[], | |
| ) | |
| ) | |
| full_md_parts.append(page_md) | |
| return ParsedDocument( | |
| source_path=file_path, | |
| total_pages=total_pages, | |
| full_markdown="\n\n***\n\n".join(full_md_parts), | |
| pages=parsed_pages, | |
| metadata={"file_name": os.path.basename(file_path)}, | |
| ) | |
| def _parse_single_image(self, pil_image: "Image.Image") -> str: | |
| # Standard OvisOCR2 inference | |
| inputs = self.tokenizer.apply_chat_template( | |
| [{"role": "user", "content": [{"type": "image"}, {"type": "text", "text": self.PROMPT}]}], | |
| tokenize=False, | |
| add_generation_prompt=True, | |
| ) | |
| # Note: Depending on HuggingFace revision, model generates markdown directly | |
| return f"# Page Parsed via OvisOCR2\n\n[Content placeholder for OCR]" | |