-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpipeline.py
More file actions
executable file
·115 lines (96 loc) · 3.85 KB
/
Copy pathpipeline.py
File metadata and controls
executable file
·115 lines (96 loc) · 3.85 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
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
#!/usr/bin/env python3
"""
pipeline.py — Run the full extraction pipeline (or parts of it).
python pipeline.py # full pipeline for new seeds only
python pipeline.py --all # full pipeline for everything
python pipeline.py --from extract # start from extraction step
python pipeline.py --id moral_elevation # single mechanism
python pipeline.py --fix-only # just fix flagged + rebuild
"""
import argparse
import subprocess
import sys
from pathlib import Path
ROOT = Path(__file__).parent
PYTHON = str(ROOT / ".venv" / "bin" / "python")
def run(cmd: list[str], label: str, check: bool = True) -> bool:
"""Run a command, print its output live, return success."""
print(f"\n{'─' * 60}")
print(f" {label}")
print(f"{'─' * 60}\n")
result = subprocess.run(cmd, cwd=ROOT)
if result.returncode != 0:
print(f"\n✗ FAILED: {label} (exit {result.returncode})")
if check:
sys.exit(result.returncode)
return False
return True
def main():
parser = argparse.ArgumentParser(description="Run the drivermap extraction pipeline")
parser.add_argument("--id", help="Process a single mechanism")
parser.add_argument("--domain", help="Process one domain only")
parser.add_argument("--all", action="store_true", help="Process all mechanisms (not just new)")
parser.add_argument(
"--from",
dest="start_from",
choices=["fetch", "extract", "verify", "fix", "narrative", "load"],
default="fetch",
help="Start from this step (default: fetch)",
)
parser.add_argument(
"--fix-only", action="store_true", help="Just fix flagged records + rebuild"
)
parser.add_argument(
"--no-narrative", action="store_true", help="Skip narrative_outputs patching"
)
parser.add_argument(
"--fix-rounds", type=int, default=2, help="Max fix→verify rounds (default 2)"
)
args = parser.parse_args()
skip = [] if args.all else ["--skip-existing"]
target = []
if args.id:
target = ["--id", args.id]
elif args.domain:
target = ["--domain", args.domain]
steps = ["fetch", "extract", "verify", "fix", "narrative", "load"]
start_idx = steps.index(args.start_from) if not args.fix_only else steps.index("fix")
# ── Fetch
if start_idx <= 0:
run([PYTHON, "fetch.py"] + skip + target, "Fetching corpus")
# ── Extract
if start_idx <= 1:
run([PYTHON, "extract.py", "--guided"] + skip + target, "Guided extraction")
# ── Verify → Fix loop
if start_idx <= 3:
for round_n in range(1, args.fix_rounds + 1):
run(
[PYTHON, "extract.py", "--verify"] + target,
f"Verification (round {round_n})",
)
# Try fixing flagged records
ok = run(
[PYTHON, "extract.py", "--fix"] + target,
f"Fixing flagged records (round {round_n})",
check=False,
)
if not ok:
print(" (no records to fix or fix failed — moving on)")
break
# ── Narrative outputs
if start_idx <= 4 and not args.no_narrative:
narr_args = [PYTHON, "patch_narrative_outputs.py", "--skip-existing"]
if args.id:
narr_args = [PYTHON, "patch_narrative_outputs.py", "--id", args.id]
run(narr_args, "Patching narrative outputs")
# ── Load + build
if start_idx <= 5:
run([PYTHON, "db_load.py", "--rebuild"], "Rebuilding database")
run([PYTHON, "build_explorer.py"], "Building explorer")
# ── Tests
run([ROOT / ".venv" / "bin" / "pytest", "tests/", "-q"], "Running tests", check=False)
print(f"\n{'═' * 60}")
print(" Pipeline complete")
print(f"{'═' * 60}\n")
if __name__ == "__main__":
main()