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 uncertainty in 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%. See validation/model-card.md in 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.

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support