ZigoTrace Pharma β Diversion Anomaly Model
A locked, validated logistic model that scores grey-market diversion on a pharmaceutical serialization graph β engine: zigo-pharma.
Intended use β read this first
- Advisory only. This model outputs a suspicion score that is fused as one reliability-capped evidence source into a larger Dempster-Shafer authenticity confidence, alongside deterministic rule-based gaps. It never gates a dispense/release decision by itself β the deterministic layer (recall, expiry, cold-chain, cloned-serial, aggregation, mass-balance) is the authoritative safety path, always.
- Scope: diversion only. Trained to catch route/ring diversion β units that are individually unremarkable but statistically anomalous in their custody path or their aggregation-case neighbourhood. It is not trained to catch expired, recalled, or cold-chain-excursion stock; those are deterministic gaps, on purpose (rules validate cleanly; this model is the layer for what rules cannot express).
- Abstains under uncertainty. Low model certainty collapses its contribution toward
"unknown" rather than guessing β see
uncertaintyin the output. - Not (yet) validated on real data. Trained and evaluated on the synthetic dataset
zigotrace/pharma-serialized-events. See Limitations.
How to use
Input is an already-extracted 8-feature vector β this model does not accept or
parse a raw event graph. Feature extraction is intentionally single-sourced in the TS
engine (packages/intelligence/src/features.ts) to avoid two implementations of graph
traversal silently drifting apart; see docs/huggingface-model-plan.md Β§0.
from huggingface_hub import hf_hub_download
import json, sys
sys.path.insert(0, ".") # scorer.py ships alongside model.json in this repo
from scorer import load_model, score_features
model = load_model(hf_hub_download("zigotrace/pharma-authenticity-model", "model.json"))
features = [0.83, 1, 1, 1, 1, 1, 4, 0.0] # route_rarity, num_receives, num_dispenses,
# distinct_receive_locations, aggregation_consistent,
# attestation_ok, hop_count, case_dispense_anomaly
out = score_features(model, features)
print(out) # AnomalyOutput(score=..., uncertainty=..., explanation="...")
Or via an Inference Endpoint running handler.py:
POST / {"inputs": {"features": [0.83, 1, 1, 1, 1, 1, 4, 0.0]}}
Training
- Algorithm: logistic regression, full-batch gradient descent, fixed
initialization and iteration count β deterministic (same events produce an
identical artifact β required for GxP change control; see
packages/intelligence/src/train.ts). - Labels: weak supervision β labeling functions over model-observable signals (rare custody route, duplicate dispense, weak attestation, case-sibling funnelling), not ground truth. Realistic for a domain where confirmed-counterfeit labels are scarce.
- Data:
zigotrace/pharma-serialized-events(synthetic, seed 7, 420 train / 180 test rows).
Evaluation (this artifact, test.jsonl, standalone at a raw 0.5 threshold)
| Metric | Value |
|---|---|
| Diversion detection (route + ring) | 7/7 β 100% |
| Brier score | 0.021 |
| False-positive rate (standalone, 0.5 threshold) | 2.3% (4/173) |
Reproduce: python hf/local_dry_run.py (after node hf/generate_fixtures.mjs).
The false-positive rate above is a property of this model scored in isolation. In the shipped engine it is capped by a reliability weight inside the Dempster-Shafer fusion and can only ever add suspicion, never override a deterministic "authentic" verdict β so it does not translate into a real false-quarantine rate. The shipped engine's actual false-quarantine rate (with this model fused in, evaluated by
intel-validate) is 0%. Seevalidation/model-card.mdin the source repo for the fused-system numbers.
Model internals (inspectable β this is why logistic-first)
featureNames: route_rarity, num_receives, num_dispenses, distinct_receive_locations,
aggregation_consistent, attestation_ok, hop_count, case_dispense_anomaly
weights: [1.596, 0.026, 0.567, 0.026, 2.117, -0.567, 0.2, 1.095]
bias: -2.329
Weights act on standardized features ((x - mean) / std, per-feature mean/std
shipped in model.json). case_dispense_anomaly (the relational feature) and
route_rarity carry meaningful weight, consistent with the model's diversion-specific
training signal.
Limitations
- Synthetic training/eval data only β real-world generalization is unverified pending a lighthouse distributor dataset (planned, gated dataset repo).
- Linear model β cannot capture more complex relational patterns (e.g. multi-hop
laundering rings); a GNN track exists (
ml/in the source repo) for that, not yet outperforming this baseline on available data. aggregation_consistent's weight sign should not be over-interpreted causally β it has low variance in the synthetic generator (aggregation mismatches are a separate, rare injected pattern), so its fitted coefficient is not strongly constrained by this dataset.
Governance
- Change control: training is deterministic; any retrain is a new artifact with a new sha256, which is the locked version id (anchored on Hedera in the deployed engine). No silent model updates.
- Human authority: a pharmacist/QP/auditor retains override, with recorded provenance, regardless of this model's output.
- Full GxP validation pack:
validation/in the source repo.
License
MIT (this model + code). The synthetic dataset it's trained on is MIT-licensed generated data β see the dataset card for details.