mirror of
https://github.com/lllin000/PaperForge.git
synced 2026-07-22 06:50:53 +00:00
feat: persist OCR reader figure artifacts and health metrics
This commit is contained in:
parent
7ec1f66da7
commit
c86700b6f2
4 changed files with 65 additions and 0 deletions
|
|
@ -1846,6 +1846,14 @@ def postprocess_ocr_result(vault: Path, key: str, all_results: list[dict]) -> tu
|
|||
figure_inventory,
|
||||
)
|
||||
|
||||
# --- Phase 2a: reader figure synthesis ---
|
||||
from paperforge.worker.ocr_figure_reader import synthesize_reader_figures
|
||||
|
||||
reader_payload = synthesize_reader_figures(figure_inventory, structured_blocks=structured)
|
||||
reader_figures_dir = ocr_root / "structure"
|
||||
reader_figures_dir.mkdir(parents=True, exist_ok=True)
|
||||
write_json(reader_figures_dir / "reader_figures.json", reader_payload)
|
||||
|
||||
# --- Phase 2: table inventory ---
|
||||
table_inventory = build_table_inventory(structured)
|
||||
write_table_inventory(
|
||||
|
|
@ -1903,6 +1911,7 @@ def postprocess_ocr_result(vault: Path, key: str, all_results: list[dict]) -> tu
|
|||
figure_inventory=figure_inventory,
|
||||
table_inventory=table_inventory,
|
||||
doc_structure=doc_structure,
|
||||
reader_payload=reader_payload,
|
||||
)
|
||||
write_ocr_health(ocr_root / "health", health_report)
|
||||
meta["ocr_health_overall"] = health_report["overall"]
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ def build_ocr_health(
|
|||
figure_inventory: dict,
|
||||
table_inventory: dict,
|
||||
doc_structure: Any = None,
|
||||
reader_payload: dict | None = None,
|
||||
) -> dict[str, Any]:
|
||||
section_heading_count = sum(1 for b in structured_blocks if b.get("role") == "section_heading")
|
||||
abstract_found = any(
|
||||
|
|
@ -224,6 +225,14 @@ def build_ocr_health(
|
|||
else 1.0
|
||||
),
|
||||
}
|
||||
|
||||
if reader_payload is not None:
|
||||
rc = reader_payload.get("reader_coverage", {})
|
||||
report["figure_reader_coverage_total"] = rc.get("total", 0)
|
||||
report["figure_reader_coverage_accounted"] = rc.get("accounted", 0)
|
||||
report["figure_reader_coverage_gap_count"] = rc.get("gap_count", 0)
|
||||
report["figure_reader_coverage_ratio"] = rc.get("ratio", 1.0)
|
||||
|
||||
report.update(decision_summary)
|
||||
|
||||
degraded_reasons = []
|
||||
|
|
@ -278,6 +287,8 @@ def build_ocr_health(
|
|||
degraded_reasons.append(
|
||||
f"figure legend completeness gap ({formal_legend_gaps} numbered legends unaccounted for)"
|
||||
)
|
||||
if reader_payload is not None and reader_payload.get("reader_coverage", {}).get("gap_count", 0) > 0:
|
||||
degraded_reasons.append("reader_figure_coverage_gap")
|
||||
|
||||
return report
|
||||
|
||||
|
|
|
|||
|
|
@ -130,6 +130,14 @@ def run_derived_rebuild_for_keys(vault: Path, keys: list[str]) -> dict:
|
|||
figure_inventory = build_figure_inventory(structured)
|
||||
write_figure_inventory(artifacts.blocks_structured.parent / "figure_inventory.json", figure_inventory)
|
||||
|
||||
# Rebuild reader figures
|
||||
from paperforge.worker.ocr_figure_reader import synthesize_reader_figures
|
||||
|
||||
reader_payload = synthesize_reader_figures(figure_inventory, structured_blocks=structured)
|
||||
reader_figures_dir = paper_root / "structure"
|
||||
reader_figures_dir.mkdir(parents=True, exist_ok=True)
|
||||
write_json(reader_figures_dir / "reader_figures.json", reader_payload)
|
||||
|
||||
# Rebuild table inventory
|
||||
from paperforge.worker.ocr_tables import build_table_inventory, write_table_inventory
|
||||
|
||||
|
|
@ -189,6 +197,7 @@ def run_derived_rebuild_for_keys(vault: Path, keys: list[str]) -> dict:
|
|||
figure_inventory=figure_inventory,
|
||||
table_inventory=table_inventory,
|
||||
doc_structure=doc_structure,
|
||||
reader_payload=reader_payload,
|
||||
)
|
||||
write_ocr_health(paper_root / "health", health_report)
|
||||
|
||||
|
|
|
|||
|
|
@ -202,3 +202,39 @@ def test_legend_only_consumes_caption_when_rendered() -> None:
|
|||
|
||||
assert result["consumed_caption_block_ids"] == [21]
|
||||
assert result["reader_figures"][0]["reader_status"] == "LEGEND_ONLY"
|
||||
|
||||
|
||||
def test_reader_payload_coverage_accounted_matches_reader_figures() -> None:
|
||||
from paperforge.worker.ocr_figure_reader import synthesize_reader_figures
|
||||
|
||||
strict_inventory = {
|
||||
"matched_figures": [
|
||||
{
|
||||
"figure_number": 1,
|
||||
"legend_block_id": 5,
|
||||
"text": "Fig. 1 Overview of the system...",
|
||||
"matched_assets": [{"block_id": 10, "bbox": [1, 2, 3, 4]}],
|
||||
"match_score": 0.91,
|
||||
"marker_type": "figure_number",
|
||||
}
|
||||
],
|
||||
"held_figures": [],
|
||||
"ambiguous_figures": [],
|
||||
"unmatched_legends": [
|
||||
{
|
||||
"figure_number": 2,
|
||||
"legend_block_id": 21,
|
||||
"text": "FIGURE 2 | Treadmill exercise protocols...",
|
||||
"marker_type": "figure_number",
|
||||
}
|
||||
],
|
||||
"unresolved_clusters": [],
|
||||
}
|
||||
|
||||
result = synthesize_reader_figures(strict_inventory, structured_blocks=[])
|
||||
|
||||
assert result["reader_coverage"]["total"] == 2
|
||||
assert result["reader_coverage"]["accounted"] == 2
|
||||
assert result["reader_coverage"]["gap_count"] == 0
|
||||
assert result["reader_coverage"]["ratio"] == 1.0
|
||||
assert set(result["consumed_caption_block_ids"]) == {5, 21}
|
||||
|
|
|
|||
Loading…
Reference in a new issue