mirror of
https://github.com/lllin000/PaperForge.git
synced 2026-07-22 06:50:53 +00:00
refactor(ocr): split legacy and vnext figure entrypoints
This commit is contained in:
parent
3feabf1569
commit
f95925b226
3 changed files with 103 additions and 0 deletions
|
|
@ -2978,6 +2978,29 @@ def _infer_missing_main_figure_numbers(
|
|||
|
||||
|
||||
def build_figure_inventory(structured_blocks: list[dict], page_width: float = 1200, page_pdf_lines_by_page: dict[int, list[dict]] | None = None) -> dict[str, Any]:
|
||||
return build_figure_inventory_legacy(structured_blocks, page_width, page_pdf_lines_by_page)
|
||||
|
||||
|
||||
def build_figure_inventory_vnext(structured_blocks: list[dict], page_width: float = 1200, page_pdf_lines_by_page: dict[int, list[dict]] | None = None) -> dict[str, Any]:
|
||||
return {
|
||||
"pipeline_mode": "vnext",
|
||||
"matched_figures": [],
|
||||
"ambiguous_figures": [],
|
||||
"unmatched_legends": [],
|
||||
"unmatched_assets": [],
|
||||
"unresolved_clusters": [],
|
||||
"held_figures": [],
|
||||
"rejected_legends": [],
|
||||
"page_ledger": {},
|
||||
"residual_ledger": {},
|
||||
"local_pairing_hypotheses": [],
|
||||
"completeness": {
|
||||
"total_numbered_legends": 0,
|
||||
"accounted_for": 0,
|
||||
"details": [],
|
||||
},
|
||||
}
|
||||
def build_figure_inventory_legacy(structured_blocks: list[dict], page_width: float = 1200, page_pdf_lines_by_page: dict[int, list[dict]] | None = None) -> dict[str, Any]:
|
||||
legends: list[dict] = []
|
||||
held_figures: list[dict] = []
|
||||
rejected_legends: list[dict] = []
|
||||
|
|
|
|||
45
scripts/dev/compare_figure_inventory_legacy_vs_vnext.py
Normal file
45
scripts/dev/compare_figure_inventory_legacy_vs_vnext.py
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
from paperforge.worker.ocr_figures import (
|
||||
build_figure_inventory_legacy,
|
||||
build_figure_inventory_vnext,
|
||||
)
|
||||
|
||||
|
||||
def _figure_asset_ids(fig: dict[str, object]) -> list[str]:
|
||||
ids = {str(x) for x in fig.get("asset_block_ids", [])}
|
||||
ids.update(str(asset.get("block_id", "")) for asset in fig.get("matched_assets", []))
|
||||
return sorted(x for x in ids if x)
|
||||
|
||||
|
||||
def compare_inventories(legacy: dict[str, object], vnext: dict[str, object]) -> dict[str, object]:
|
||||
return {
|
||||
"legacy_matched_count": len(legacy.get("matched_figures", [])),
|
||||
"vnext_matched_count": len(vnext.get("matched_figures", [])),
|
||||
"legacy_unresolved_count": len(legacy.get("unresolved_clusters", [])),
|
||||
"vnext_unresolved_count": len(vnext.get("unresolved_clusters", [])),
|
||||
"legacy_unmatched_legend_count": len(legacy.get("unmatched_legends", [])),
|
||||
"vnext_unmatched_legend_count": len(vnext.get("unmatched_legends", [])),
|
||||
"legacy_consumed_block_ids": sorted(
|
||||
{bid for fig in legacy.get("matched_figures", []) for bid in _figure_asset_ids(fig)}
|
||||
),
|
||||
"vnext_consumed_block_ids": sorted(
|
||||
{bid for fig in vnext.get("matched_figures", []) for bid in _figure_asset_ids(fig)}
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
def main(blocks_path: str) -> int:
|
||||
blocks = [json.loads(line) for line in Path(blocks_path).read_text(encoding="utf-8").splitlines() if line.strip()]
|
||||
legacy = build_figure_inventory_legacy(blocks)
|
||||
vnext = build_figure_inventory_vnext(blocks)
|
||||
print(json.dumps(compare_inventories(legacy, vnext), ensure_ascii=False, indent=2))
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
raise SystemExit(main(sys.argv[1]))
|
||||
|
|
@ -6424,3 +6424,38 @@ def test_recover_internal_figure_number_inside_overlap_gate():
|
|||
# Line that covers >15% of asset -> edge_band_score = 0
|
||||
large_line = [100, 100, 500, 600] # covers large area
|
||||
assert _asset_edge_band_score(large_line, asset) == 0.0
|
||||
|
||||
|
||||
# --- Task 1: Legacy/vnext mechanical split ---
|
||||
|
||||
|
||||
def test_build_figure_inventory_wrapper_stays_legacy_path(monkeypatch):
|
||||
from paperforge.worker import ocr_figures
|
||||
|
||||
called = {"legacy": 0, "vnext": 0}
|
||||
|
||||
def fake_legacy(*args, **kwargs):
|
||||
called["legacy"] += 1
|
||||
return {"source": "legacy"}
|
||||
|
||||
def fake_vnext(*args, **kwargs):
|
||||
called["vnext"] += 1
|
||||
return {"source": "vnext"}
|
||||
|
||||
monkeypatch.setattr(ocr_figures, "build_figure_inventory_legacy", fake_legacy)
|
||||
monkeypatch.setattr(ocr_figures, "build_figure_inventory_vnext", fake_vnext)
|
||||
|
||||
result = ocr_figures.build_figure_inventory([], 1200)
|
||||
|
||||
assert result == {"source": "legacy"}
|
||||
assert called == {"legacy": 1, "vnext": 0}
|
||||
|
||||
|
||||
def test_vnext_entrypoint_is_callable_without_cutover():
|
||||
from paperforge.worker.ocr_figures import build_figure_inventory_vnext
|
||||
|
||||
result = build_figure_inventory_vnext([], 1200)
|
||||
|
||||
assert isinstance(result, dict)
|
||||
assert result.get("pipeline_mode") == "vnext"
|
||||
assert result.get("matched_figures") == []
|
||||
|
|
|
|||
Loading…
Reference in a new issue