Skip to main content
Measure matching accuracy against ground truth and enforce quality gates in CI/CD pipelines.

Quick start

Ground truth format

A CSV file with two columns identifying matched pairs:
Each row represents a known true match. Column names default to id_a and id_b but are configurable. IDs correspond to GoldenMatch’s __row_id__ (int64). Ground truth CSVs may have string IDs — load_ground_truth_csv attempts int conversion automatically.

CI/CD quality gates

Exit with code 1 if accuracy falls below thresholds:
Use in GitHub Actions:

EvalResult

Evaluate pairs directly

Evaluate clusters

Evaluate a cluster dict (as returned by build_clusters). Expands cluster members into pairs for comparison.
Note: run_dedupe() does not return scored_pairs — use the clusters dict instead.

Build ground truth with label command

Interactively label record pairs to create a ground truth CSV:
The label command shows pairs and prompts for your judgment: Pairs are selected from actual pipeline output, focusing on borderline cases near the threshold.

Evaluation workflow

  1. Build ground truth: Use goldenmatch label or create a CSV manually
  2. Run evaluation: goldenmatch evaluate --gt gt.csv
  3. Iterate: Adjust config (thresholds, scorers, blocking) and re-evaluate
  4. Gate CI: Add --min-f1 threshold to your CI pipeline

Metrics explained

For entity resolution:
  • High precision means few false merges (records incorrectly combined)
  • High recall means few missed duplicates
  • Most production systems prioritize precision (false merges are harder to fix than missed dupes)

Cluster comparison (CCMS)

Compare two clustering outcomes on the same dataset without ground truth. Based on the Case Count Metric System (Talburt et al., arXiv:2601.02824v1).
Each cluster from run A is classified into one of four cases: The TWI (Talburt-Wang Index) measures overall clustering similarity, normalized to [0, 1] where 1.0 means identical outcomes.

Parameter sensitivity analysis

Sweep a parameter across a range and compare each run against a baseline:
Supported sweep fields: threshold, matchkey.<name>.threshold, blocking.max_block_size.

Benchmark evaluation tips

  • Always use threshold-based pair generation, NOT top-1-per-record (argmax)
  • Leipzig benchmark CSVs have invalid UTF-8 — use pl.read_csv(encoding="utf8-lossy", ignore_errors=True)
  • Run benchmarks: python tests/benchmarks/run_leipzig.py