File size: 4,531 Bytes
5840d20 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | """Rangkum semua run jadi angka siap pakai untuk justifikasi resource.
py -m src.knowledge_parsing.report
py -m src.knowledge_parsing.report --scale 6800
`--scale` mengekstrapolasi ke jumlah halaman tertentu (mis. skala BUMA
±6.700-6.800 halaman) memakai detik/halaman yang TERUKUR — dokumen yang
diambil dari cache tidak ikut dihitung, karena akan membuat angkanya
terlihat jauh lebih cepat dari kenyataan.
"""
from __future__ import annotations
import argparse
import json
from pathlib import Path
from .config import PipelineConfig
# Di bawah ini, ongkos tetap pemuatan model mendominasi sehingga detik/halaman
# jauh lebih besar dari kenyataan pada dokumen besar. Terukur di mesin ini:
# 1 hal -> 54,0 dtk/hal, 5 hal -> 33,2, 20 hal -> 19,0.
MIN_HALAMAN_SAHIH = 20
def _jam(detik: float) -> str:
if detik < 90:
return f"{detik:.0f} dtk"
if detik < 5400:
return f"{detik/60:.1f} mnt"
return f"{detik/3600:.1f} jam"
def kumpulkan(runs_dir: Path) -> list[dict]:
hasil = []
for m in sorted(runs_dir.glob("*/manifest.json")):
try:
hasil.append(json.loads(m.read_text(encoding="utf-8")))
except (OSError, json.JSONDecodeError) as e:
# Manifest rusak/separuh tertulis (run yang mati di tengah). Dilewati,
# tapi disebutkan — laporan yang diam-diam kehilangan satu run akan
# memberi angka detik/halaman yang salah tanpa ada tandanya.
print(f" ! lewati manifest tidak terbaca: {m} ({type(e).__name__})")
return hasil
def cetak(runs: list[dict], scale: int | None) -> None:
if not runs:
print("Belum ada run. Jalankan: py -m src.knowledge_parsing.run --input dokumen/")
return
print(f"{'run':<17} {'backend':<9} {'ver':<8} {'dok':>4} {'hal':>5} "
f"{'dtk/hal':>8} {'peringatan':>11}")
print("-" * 68)
for r in runs:
s = r.get("ringkasan", {})
cfg = r.get("config", {})
# backend yang tercatat di output MinerU lebih dipercaya daripada config
tercatat = {d.get("backend_tercatat") for d in r.get("dokumen", [])} - {None}
backend = "/".join(sorted(tercatat)) if tercatat else cfg.get("backend", "?")
dph = s.get("detik_per_halaman")
print(f"{r.get('run_id',''):<17} {backend:<9} "
f"{str(r.get('mineru_version') or '?')[:7]:<8} "
f"{s.get('dokumen_ok',0):>4} {s.get('total_halaman',0):>5} "
f"{(f'{dph:.2f}' if dph else '-'):>8} {s.get('total_peringatan',0):>11}")
terukur = [r for r in runs if (r.get("ringkasan") or {}).get("detik_per_halaman")]
if not terukur:
print("\n(belum ada run yang benar-benar diparse — semua dari cache)")
return
print("\n--- ekstrapolasi ---")
target = scale or 6800
meragukan = False
for r in terukur:
s = r["ringkasan"]
dph = s["detik_per_halaman"]
hal = s.get("halaman_terukur", 0)
cfg = r.get("config", {})
tanda = ""
if hal < MIN_HALAMAN_SAHIH:
tanda = f" ⚠ hanya {hal} hal."
meragukan = True
print(f" {cfg.get('backend','?'):<9} {dph:>6.2f} dtk/hal → "
f"{target} halaman = {_jam(dph * target)}{tanda}")
if meragukan:
print(
f"\n ⚠ Run dengan < {MIN_HALAMAN_SAHIH} halaman TIDAK layak diekstrapolasi.\n"
" Pemuatan model adalah ongkos tetap, jadi dokumen kecil terlihat jauh\n"
" lebih lambat per halaman. Terukur sebelumnya di mesin ini:\n"
" 1 hal -> 54,0 dtk/hal | 5 hal -> 33,2 | 20 hal -> 19,0\n"
" Pakai dokumen >= 20 halaman sebelum angkanya dibawa ke luar."
)
if len(terukur) >= 2:
cepat = min(terukur, key=lambda r: r["ringkasan"]["detik_per_halaman"])
lambat = max(terukur, key=lambda r: r["ringkasan"]["detik_per_halaman"])
a = lambat["ringkasan"]["detik_per_halaman"]
b = cepat["ringkasan"]["detik_per_halaman"]
if b:
print(f"\n selisih tercepat vs terlambat: {a/b:.1f}×")
def main() -> None:
p = argparse.ArgumentParser(description="Ringkasan angka dari semua run")
p.add_argument("--runs-dir", type=Path, default=None)
p.add_argument("--scale", type=int, default=None,
help="ekstrapolasi ke berapa halaman (mis. 6800)")
a = p.parse_args()
cfg = PipelineConfig()
cetak(kumpulkan(a.runs_dir or cfg.runs_dir), a.scale)
if __name__ == "__main__":
main()
|