| name | blind-ml-demo |
| description | Build or extend Blind Insight encrypted-ML demo notebooks in blind-ml. Use when adding a notebook, a model trained on aggregate queries, demo_helpers/healthcare helpers, BI client usage, or debugging parity between encrypted and sklearn baselines. |
blind-ml demo contributor
Architecture (short)
- Training:
BlindInsightClient.query(..., count_only=True) and aggregate filters — no record-level decryption during training.
- Plaintext baseline: Local SQLite under
demo_data/plaintext/ (from scripts/generate_*.py).
- Config:
get_fraud_demo_config() in blind_ml/demo_helpers.py, get_bc_demo_config() in blind_ml/healthcare.py.
- Auth:
BI_EMAIL, BI_PASSWORD, BI_ORG in .env only.
Checklist for a new demo
- Schema — add
schemas/<name>.json; document field types and min/max (integers often need maximum = actual_max + 2 in schema).
- Generator —
scripts/generate_<domain>_data.py writes matching SQLite + demo_data/upload_batches/*.json.
- Helpers — training/query/HTML tables in
blind_ml/demo_helpers.py or blind_ml/healthcare.py; keep notebooks thin.
- Notebook — setup cell:
load_env(), config dict, BlindInsightClient(proxy_url=...), warm_up().
- Register symbols — add imports to
scripts/smoke_test.py notebook symbol lists.
- Docs — README row + short section; link upload batches in demo-datasets.
Algorithms that fit today
See APPROACH.md. Prefer reusing existing patterns:
| Pattern | Example in repo |
|---|
| NB from counts | run_bi_training, build_bc_model |
| DT from marginals + local cross-tabs | run_encrypted_dt_fraud, run_encrypted_dt |
| LR from X'X / X'y + IRLS | build_fraud_linear_model, train_evaluate_bc_lr_models |
Common pitfalls
- Query syntax:
field:count(50~100) not count(50, 100). Aggregates are filters in the BI API — see ./blind record list --filter "field:avg(0~100)".
- Warm-up: call
client.warm_up(org, dataset, schema) before heavy query loops.
- Scale: fraud batches are 50K records each; BC batches 20K — upload as many as needed; SQLite generator can build full scale locally.
- Parity: encrypted vs sklearn F1 gaps often mean schema bounds, indexing not finished (wait ~30s after upload), or plaintext/BI data mismatch — regenerate with the same script for both.
- Silent zero is fatal (E022): if BI base rates are 0 or any feature's conditional counts are all 0, training will silently produce a uniform-conditional model that looks trained but isn't. Always call
get_bi_base_rates first and raise loudly on 0. run_bi_training does this automatically — don't bypass it.
- Case sensitivity on the encrypted index (E023): BI's encrypted index does case-sensitive exact-match on the hashed token. If your data is uploaded as
"DE" (uppercase), a query for "de" returns 0 — silently. discover_feature_values must preserve the case BI uses; don't reflexively .str.lower() values. NB/DT survive casing bugs (averaging absorbs zeros); LR diverges catastrophically (beta[0] → -3M, all predictions collapse).
- Marginals mismatch is the fastest BI/local divergence diagnostic (E025): when a model behaves differently on BI vs local counts, dump the (feature, value) → count pairs from both sides and print the top mismatches by absolute diff. Casing, partial uploads, and stale schemas jump out in 30 seconds.
Debugging a query-layer bug
Run the CLI against the live proxy first (E021). Source-only diagnosis of the encrypted query layer (proxy ↔ server wire format, aggregate response, filter parsing) consistently produces confidently-wrong stories. The CLI is the canonical reference for both wire format and expected behavior:
./blind record list --organization <org> --dataset <dataset> --schema <schema> \
--filter "risk_level:count(50~100),fraud_type:mule_account"
Compare what the CLI returns to what the Python client returns. If they disagree, the bug is in the Python client. If they agree (e.g., both 0), the bug is environmental — wrong dataset, casing, upload failure, schema mismatch.
Files to touch
| Change | Files |
|---|
| New fraud-style demo | schemas/, scripts/generate_*.py, blind_ml/demo_helpers.py, *.ipynb, smoke_test.py, README |
| New healthcare-style demo | same + blind_ml/healthcare.py |
| Client behavior | blind_ml/client.py (proxy-only) |
Do not add alternate BI backends or new dependencies without maintainer approval.