5. Batch DICIE predictions written back as extracted fields
# Run salvage predictions and persist extracted fields into SQL (role=extracted)salvage_export = EXPORTS /"train_pipeline_salvage_docie.jsonl"store.export_jsonl( salvage_export, format="docie", application="salvage_claims", split="test")pred_out = DEMO /"salvage_test_predictions.jsonl"run_file( salvage_export, pred_out, application="salvage_claims", cfg=cfg, run_ocr=False,)n_updated =0for pred in load_jsonl(pred_out): rid = pred["record_id"] fields = pred.get("fields") or {} flat = {}for k, v in fields.items():ifisinstance(v, list): flat[k] = v[0] if v elseNoneelse: flat[k] = vifnot flat:continue conf =Noneifisinstance(pred.get("extraction"), dict): conf = pred["extraction"].get("confidence") store.set_fields( rid, {k: Noneif v isNoneelsestr(v) for k, v in flat.items()}, role="extracted", confidence=conf, ) n_updated +=1print(f"wrote extracted fields for {n_updated} test documents")cmp_sql ="""SELECT g.document_id, g.field_name, g.field_value AS ground_truth, e.field_value AS extractedFROM document_fields gLEFT JOIN document_fields e ON e.document_id = g.document_id AND e.field_name = g.field_name AND e.field_role = 'extracted'WHERE g.field_role = 'ground_truth' AND g.document_id IN ( SELECT document_id FROM documents WHERE split='test' AND application='salvage_claims' )ORDER BY g.document_id, g.field_nameLIMIT 40"""with sqlite3.connect(DB_PATH) as conn:cmp= pd.read_sql_query(cmp_sql, conn)cmp
wrote extracted fields for 8 test documents
document_id
field_name
ground_truth
extracted
0
sal-bundle00-log
claim_id
CLM-2022-536774
CLM-2022-536774
1
sal-bundle00-log
make
BMW
BMW
2
sal-bundle00-log
model
330i
330i
3
sal-bundle00-log
vin
WBA8E9G50JNU12345
WBA8E9G50JNU12345
4
sal-bundle00-log
year
2018
2018
5
sal-bundle01-log
claim_id
CLM-2023-165142
CLM-2023-165142
6
sal-bundle01-log
make
Toyota
Toyota
7
sal-bundle01-log
model
Corolla
Corolla
8
sal-bundle01-log
vin
2T1BURHE0JC123456
2T1BURHE0JC123456
9
sal-bundle01-log
year
2017
2017
10
sal-log-001
claim_id
CLM-2024-100200
CLM-2024-100200
11
sal-log-001
make
Honda
Honda
12
sal-log-001
model
Accord
Accord
13
sal-log-001
vin
1HGCM82633A004352
1HGCM82633A004352
14
sal-log-001
year
2018
2018
15
sal-log-100
claim_id
CLM-2022-232378
CLM-2022-232378
16
sal-log-100
make
Honda
Honda
17
sal-log-100
model
Accord
Accord
18
sal-log-100
vin
1HGCM82633A004352
1HGCM82633A004352
19
sal-log-100
year
2018
2018
20
sal-other-003
claim_id
CLM-2024-100202
CLM-2024-100202
21
sal-other-003
make
NaN
NaN
22
sal-other-003
model
NaN
NaN
23
sal-other-003
vin
NaN
NaN
24
sal-other-003
year
NaN
NaN
25
sal-other-100
claim_id
CLM-2025-711484
CLM-2025-711484
26
sal-other-100
make
Tesla
Tesla
27
sal-other-100
model
Model 3
Model 3
28
sal-other-100
vin
5YJSA1E26HF000111
5YJSA1E26HF000111
29
sal-other-100
year
2019
2019
30
sal-sales-002
claim_id
CLM-2024-100201
CLM-2024-100201
31
sal-sales-002
make
Ford
Ford
32
sal-sales-002
model
Focus
Focus
33
sal-sales-002
vin
1FADP3F20EL123456
1FADP3F20EL123456
34
sal-sales-002
year
2015
2015
35
sal-sales-100
claim_id
CLM-2024-338536
CLM-2024-338536
36
sal-sales-100
make
Jeep
Jeep
37
sal-sales-100
model
Grand Cherokee
Grand Cherokee
38
sal-sales-100
vin
1C4RJFBG5EC123456
1C4RJFBG5EC123456
39
sal-sales-100
year
2014
2014
6. Optional DistilBERT smoke train (transformers)
# Optional deep classifier smoke — skipped automatically if deps/data are insufficient.RUN_TRANSFORMERS_SMOKE =False# set True on machines with transformers + datasets installedtransformers_metrics = {}if RUN_TRANSFORMERS_SMOKE:try:from src.classification.evalimport evaluate as eval_clffrom src.classification.train_classifier import train as train_clffor app in ("medical_bills", "salvage_claims"): prepared = PREPARED / app /"classification" out_dir = MODELS /f"{app}_distilbert_smoke" model_dir = train_clf( prepared_dir=prepared, cfg=cfg, output_dir=out_dir, smoke=True, wandb_settings=None, ) metrics = eval_clf(model_dir=model_dir, prepared_dir=prepared, cfg=cfg) transformers_metrics[app] = { k: metrics[k]for k in metricsif k in ("accuracy", "macro_f1", "weighted_f1", "n") }print(app, transformers_metrics[app])exceptExceptionas exc:print("Transformers smoke skipped/failed:", exc)else:print("RUN_TRANSFORMERS_SMOKE=False — using TF-IDF RF metrics only")write_json(DEMO /"transformers_smoke_metrics.json", transformers_metrics)
RUN_TRANSFORMERS_SMOKE=False — using TF-IDF RF metrics only
7. Pipeline scorecard
scorecard = []for app, m in train_metrics.items(): scorecard.append( {"application": app,"model": "tfidf_rf","test_accuracy": m.get("test_accuracy"),"test_macro_f1": m.get("test_macro_f1"),"n_train": m["n_train"],"n_test": m["n_test"],"docie_clf_accuracy": docie_metrics[app]["classification_accuracy"],"docie_ext_micro_f1": docie_metrics[app]["extraction_micro_f1"], } )score_df = pd.DataFrame(scorecard)display(score_df)write_json( DEMO /"pipeline_scorecard.json", {"rf": { app: {k: v for k, v in m.items() if k !="val_report"and k !="test_report"}for app, m in train_metrics.items() },"docie": docie_metrics,"db_path": str(DB_PATH),"prepared": str(PREPARED), },)print("artifacts under", DEMO)for p insorted(DEMO.rglob("*")):if p.is_file():print(" ", p.relative_to(DEMO))