Spaces:
Sleeping
Sleeping
| """General document field extraction — catch-all parser for unknown types.""" | |
| from __future__ import annotations | |
| import re | |
| from ml_utils.ocr import OcrResult, get_full_text, get_average_confidence | |
| EMAIL_RE = re.compile(r"[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}") | |
| PHONE_RE = re.compile(r"(?:\+91[\s\-]?)?[6-9]\d{9}") | |
| DATE_RE = re.compile( | |
| r"\d{1,2}[/\-]\d{1,2}[/\-]\d{2,4}|" | |
| r"\d{1,2}\s+(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)[a-z]*\s+\d{4}", | |
| re.I, | |
| ) | |
| KV_RE = re.compile(r"([A-Za-z\s]{2,30})\s*[:\-]\s*(.+)") | |
| def parse_general_fields(ocr_results: list[OcrResult]) -> dict: | |
| """Extract whatever we can from an unknown document type.""" | |
| full_text = get_full_text(ocr_results) | |
| fields: dict = {} | |
| # Emails | |
| emails = EMAIL_RE.findall(full_text) | |
| if emails: | |
| fields["emails"] = emails | |
| # Phones | |
| phones = PHONE_RE.findall(full_text) | |
| if phones: | |
| fields["phones"] = phones | |
| # Dates | |
| dates = DATE_RE.findall(full_text) | |
| if dates: | |
| fields["dates"] = dates | |
| # Key-value pairs | |
| kv_pairs: dict = {} | |
| for line in full_text.split("\n"): | |
| m = KV_RE.match(line.strip()) | |
| if m: | |
| key = m.group(1).strip().lower().replace(" ", "_") | |
| value = m.group(2).strip() | |
| if len(key) >= 2 and len(value) >= 1: | |
| kv_pairs[key] = value | |
| if kv_pairs: | |
| fields["detected_fields"] = kv_pairs | |
| fields["full_text_preview"] = full_text[:500] if full_text else "" | |
| return fields | |
| def validate_general(fields: dict, ocr_results: list[OcrResult]) -> tuple[float, list[str]]: | |
| """Minimal validation for unknown documents.""" | |
| flags: list[str] = ["UNKNOWN_DOC_TYPE"] | |
| checks_total = 2 | |
| checks_passed = 0 | |
| if fields.get("detected_fields"): | |
| checks_passed += 1 | |
| if fields.get("full_text_preview") and len(fields["full_text_preview"]) > 20: | |
| checks_passed += 1 | |
| if ocr_results: | |
| avg_conf = get_average_confidence(ocr_results) | |
| if avg_conf < 0.4: | |
| flags.append("LOW_OCR_CONFIDENCE") | |
| validation_ratio = checks_passed / max(checks_total, 1) | |
| return validation_ratio * 20.0, flags | |