-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrun.py
More file actions
89 lines (74 loc) · 3.42 KB
/
Copy pathrun.py
File metadata and controls
89 lines (74 loc) · 3.42 KB
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
#!/usr/bin/env python3
"""CLI for the resume extraction POC.
python run.py path/to/resume.pdf # run all steps (auto-OCR if scanned) -> HTML
python run.py path/to/resume.pdf --open # ...and open the HTML in your browser
python run.py path/to/resume.pdf --step 1 # text extraction + page render (no LLM)
python run.py --doc-id <id> --step ocr # transcribe a scanned PDF's pages
python run.py --doc-id <id> --step 2 # replay LLM extraction from step1/ocr
python run.py --doc-id <id> --step 3 # replay verification (no LLM)
python run.py --doc-id <id> --step html # re-render the HTML (no LLM)
Artifacts land in artifacts/<doc_id>/ (resume.html is the human-readable output).
AI call trail in artifacts/ai_calls.jsonl.
"""
from __future__ import annotations
import argparse
import json
import subprocess
from dotenv import load_dotenv
from resume_poc import pipeline
load_dotenv()
def main() -> None:
ap = argparse.ArgumentParser()
ap.add_argument("pdf", nargs="?", help="path to resume PDF")
ap.add_argument("--doc-id", help="replay a step from saved artifacts")
ap.add_argument("--step", choices=["1", "2", "3", "ocr", "html"], help="run a single step")
ap.add_argument("--no-vision", action="store_true",
help="text-only arm (skip page images) for A/B vs the vision path")
ap.add_argument("--open", dest="open_", action="store_true",
help="open the rendered HTML in the default browser")
args = ap.parse_args()
use_vision = not args.no_vision
def show(title: str, obj: dict) -> None:
print(f"\n=== {title} ===")
print(json.dumps(obj, ensure_ascii=False, indent=2))
def doc_id() -> str:
return args.doc_id or pipeline.doc_id_for(args.pdf)
def deliver(path: str) -> None:
print(f"\nHTML -> {path}")
if args.open_:
subprocess.run(["open", path], check=False)
if args.step == "1":
s1 = pipeline.step1(args.pdf)
show("step1: text", s1)
if s1.get("source") == "needs_ocr":
print(f"\n[scanned] no text layer -> run: --doc-id "
f"{pipeline.doc_id_for(args.pdf)} --step ocr")
elif args.step == "ocr":
show("ocr: transcription", pipeline.step_ocr(doc_id()))
elif args.step == "2":
show("step2: fields", pipeline.step2(doc_id(), use_vision=use_vision))
elif args.step == "3":
show("step3: verify", pipeline.step3(doc_id()))
elif args.step == "html":
deliver(pipeline.step_html(doc_id()))
else:
out = pipeline.run_all(args.pdf, use_vision=use_vision)
print(f"\ndoc_id: {out['doc_id']}")
if "ocr" in out:
o = out["ocr"]
print(f"[scanned] OCR via {o['provider']}: {o['n_pages']} page(s), "
f"${o['cost_usd']:.5f}")
show("step2: fields", out["step2"])
show("step3: verify", out["step3"])
rep = out["step3"]
s2 = out["step2"]
print(f"\nsource: {s2['source']} mode: {s2['mode']} ({s2['n_images']} page image(s))")
print(f"confidence: {rep['confidence']} "
f"({rep['verified']}/{rep['total_checks']} grounded)")
if rep["unverified"]:
print("UNVERIFIED (possible hallucination / 张冠李戴):")
for c in rep["unverified"]:
print(f" - [{c['kind']}] {c['label']}")
deliver(out["html"])
if __name__ == "__main__":
main()