mirror of
https://github.com/lllin000/PaperForge.git
synced 2026-07-22 06:50:53 +00:00
feat: close OCR object gate for reader outputs
When figure_caption_candidate blocks lack explicit marker_type or caption_text in the strict inventory, _normalize_bucket now falls back to the structured block's text and infers figure_number/marker_type from the text content. This ensures candidate captions propagate through the reader-figure pipeline to the renderer and health summary.
This commit is contained in:
parent
669c3bfe07
commit
8dfc0a0425
2 changed files with 39 additions and 3 deletions
|
|
@ -1,7 +1,16 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import contextlib
|
||||
import re
|
||||
from dataclasses import dataclass
|
||||
|
||||
_FIGURE_NUM_PATTERN = re.compile(
|
||||
r"(?:Figure|Fig\.?|Supplementary\s+Figure|Supplementary\s+Fig\.?|"
|
||||
r"Extended\s+Data\s+Figure|Extended\s+Data\s+Fig\.?)\s+"
|
||||
r"(?:S)?(\d+(?:\.\d+)?)",
|
||||
flags=re.IGNORECASE,
|
||||
)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ReaderCoverage:
|
||||
|
|
@ -100,7 +109,7 @@ def _normalize_bucket(
|
|||
legend_block_id = _legend_block_id(source_item)
|
||||
source_page = source_item.get("page")
|
||||
block = (page_block_index or {}).get((source_page, legend_block_id), block_index.get(legend_block_id, {}))
|
||||
source_text = str(source_item.get("text", source_item.get("caption_text", "")) or "")
|
||||
source_text = str(source_item.get("text", source_item.get("caption_text", block.get("text", ""))) or "")
|
||||
legend_data = (page_legends_index or {}).get((source_page, legend_block_id), (legends_index or {}).get(legend_block_id, {}))
|
||||
source_marker = (
|
||||
source_item.get("marker_signature")
|
||||
|
|
@ -109,9 +118,19 @@ def _normalize_bucket(
|
|||
or {}
|
||||
)
|
||||
|
||||
_inferred_figure_number: int | None = None
|
||||
_inferred_marker_type: str | None = None
|
||||
_text_for_inference = source_text or block.get("text", "")
|
||||
if not source_item.get("marker_type") and not source_marker.get("type") and _text_for_inference:
|
||||
_m = _FIGURE_NUM_PATTERN.search(_text_for_inference)
|
||||
if _m:
|
||||
_inferred_marker_type = "figure_number"
|
||||
with contextlib.suppress(ValueError):
|
||||
_inferred_figure_number = int(float(_m.group(1)))
|
||||
|
||||
normalized.append(
|
||||
{
|
||||
"figure_number": source_item.get("figure_number") or source_marker.get("number"),
|
||||
"figure_number": source_item.get("figure_number") or source_marker.get("number") or _inferred_figure_number,
|
||||
"legend_block_id": legend_block_id,
|
||||
"caption_text": source_text,
|
||||
"asset_block_ids": _asset_ids_from_item(source_item),
|
||||
|
|
@ -120,7 +139,7 @@ def _normalize_bucket(
|
|||
if bucket_name in candidate_buckets
|
||||
else []
|
||||
),
|
||||
"marker_type": source_item.get("marker_type") or source_marker.get("type"),
|
||||
"marker_type": source_item.get("marker_type") or source_marker.get("type") or _inferred_marker_type,
|
||||
"inline_mention": bool(source_item.get("inline_mention", False)),
|
||||
"panel_label": bool(source_item.get("panel_label", False)),
|
||||
"body_prose_likelihood": float(source_item.get("body_prose_likelihood", 0.0)),
|
||||
|
|
|
|||
|
|
@ -277,6 +277,23 @@ def test_reader_payload_coverage_accounted_matches_reader_figures() -> None:
|
|||
assert set(result["consumed_caption_block_ids"]) == {5, 21}
|
||||
|
||||
|
||||
def test_reader_figures_emit_from_matched_or_unresolved_object_inputs() -> None:
|
||||
from paperforge.worker.ocr_figure_reader import synthesize_reader_figures
|
||||
|
||||
payload = synthesize_reader_figures(
|
||||
{
|
||||
"matched_figures": [{"figure_id": "figure_001", "page": 2, "legend_block_id": 21, "asset_block_ids": [90], "strict_status": "matched"}],
|
||||
"held_figures": [],
|
||||
"ambiguous_figures": [],
|
||||
"unmatched_legends": [],
|
||||
"unresolved_clusters": [],
|
||||
},
|
||||
structured_blocks=[{"block_id": 21, "page": 2, "role": "figure_caption_candidate", "text": "Fig. 1 Caption"}],
|
||||
)
|
||||
|
||||
assert len(payload["reader_figures"]) >= 1
|
||||
|
||||
|
||||
def test_reader_normalization_keeps_same_block_id_legends_separate_by_page() -> None:
|
||||
from paperforge.worker.ocr_figure_reader import synthesize_reader_figures
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue