φ(ai) PHI AI
DocumentationDocs
Repository

Model documentation

Every model this platform runs, documented four ways: what it does in plain words, what it is actually computing, how data moves through it, and how it is built. The numbers on this page are read from the running system at page load — a documented metric that disagrees with production is worse than no metric at all. Each capability slot is addressable: the AI core banner on every feature screen links straight to its section here.

Slot, not vendor. The platform reasons about capability slots — a slot is a job, and a registry entry is one implementation of it. Swapping the model behind a slot must not invalidate the description of what that slot does, which is why this page is organised by slot and names the currently activated model inside each one.

The registry at a glance

Every model the Control panel knows about, and the slot it serves. Rows are live from the registry.

Capability slotActivated modelKind StatusDocumented
Ambient listener
ambient
Ambient listener — faster-whisper custom enabled read →
PHI AI assistant (retrieval)
assistant
Claude Sonnet 5
3 registered for this slot
foundation enabled read →
Denial risk
claims
Denial risk model predictive enabled read →
Coding integrity
coding
Coding integrity model classifier enabled read →
Imaging read assistant
imaging
Imaging read assistant vision enabled read →
Terminology mapping
ingest
Terminology mapper mapper enabled read →
Ingest & mapping QA
ingestqa
Ingest QA reviewer llm.analytic enabled read →
Patient instructions
instructions
Patient instructions writer llm.generative enabled read →
No-show risk
noshow
No-show risk model predictive enabled read →
Prior-auth evidence assembly
priorauth
Prior auth evidence assembler retrieval enabled read →
Release-of-information validation
roi
ROI requirements validator classifier enabled read →
Scheduling optimization
scheduling
Scheduling optimizer optimization enabled read →
Sensitivity classification
segmentation
Sensitivity classifier classifier enabled read →
Inbox triage
triage
Inbox triage ranker deterministic enabled read →

Ambient listener

ambient speech recognition running: Ambient listener — faster-whisper v1.2

What it does

This listens to a visit and turns the conversation into text, which another model then drafts into a note. Before a single second is captured it checks whether recording this visit is lawful — which depends on the state, whether it is in person or telehealth, and who has consented. If the answer is no, nothing is recorded at all. Terms the model is unsure of are flagged for the clinician rather than quietly guessed, and nothing reaches the chart until a clinician signs it.

Live metrics

Read from the running system at page load.

How it works — technical

Consent gate precedes capture. A jurisdiction × modality rule set decides admissibility. There is no default state: an unresolved jurisdiction refuses, because choosing one would be a security-relevant guess.

capture ⇔ allowed( state, modality, attested )
state ∉ RULES ⇒ refuse   (no default jurisdiction)

Transducer decoding. Self-hosted CTC/attention speech recognition over log-mel features; audio never leaves the deployment.

X = log-mel(x, n=80)  →  encoder → decoder → tokens
ŷ = argmaxyt P(yt | y<t, X)

Uncertainty is surfaced, not smoothed. Low-confidence tokens — drug names especially — are flagged for the signing clinician rather than silently normalised to the likeliest word.

Data flow

Model architecture

↑ back to the registry

PHI AI assistant (retrieval)

assistant retrieval + LLM running: Claude Sonnet 5 v1

What it does

You ask a question about a patient in ordinary language and get an answer where every claim is footnoted to the actual record it came from. It cannot see anything your role could not open yourself, and if the record has nothing to say on your question it tells you that instead of inventing something. The language model never touches the database — it only ever receives excerpts that the platform already decided you were allowed to read.

Live metrics

Read from the running system at page load.

How it works — technical

Hybrid retrieval, grant-bounded. Candidate chunks are scored by a lexical term-frequency component and a dense-similarity component, then filtered by the asker’s own grants before ranking — never after, so a forbidden chunk can never influence the ordering.

score(q,d) = λ·BM25(q,d) + (1−λ)·cos(eq, ed)  ·  δ(d)
BM25(q,d) = ∑t∈q IDF(t) · f(t,d)(k1+1) / ( f(t,d) + k1(1−b+b·|d|/avgdl) )
δ(d) = exp( −Δt(d) / τ )   (recency weighting)
grants: d retained ⇔ role(user) ⊇ required(d)

The attribution hard gate. Every sentence in the answer must resolve to at least one retrieved chunk. Sentences that do not are removed, not softened — and if the retrieval set is empty the model abstains rather than answering from parametric memory.

answer emitted ⇔ ∀ claims c ∈ A, ∃ d ∈ R : supports(d, c)

Chunking preserves negation and status. Chunks are serialised with their clinical status and negation intact, because “no history of MI” and “history of MI” must never collapse to the same retrieval unit.

Data flow

Model architecture

↑ back to the registry

Denial risk

claims predictive running: Denial risk model v1.0

What it does

Before a claim is sent to the insurer, this model estimates how likely that insurer is to refuse it — and says why, in counts you can check. It learns nothing from outside your walls: the only evidence it uses is your own history of what that payer has already paid and denied, for that kind of service. A high score is not a verdict; it is a prompt to look at the claim before it goes out, when fixing it is still cheap.

Live metrics

Read from the running system at page load — separation and calibration are computed on claims whose outcome is already known.

How it works — technical

Additive log-odds. Each factor moves the odds, and the movement is stored so it can be shown. Starting from the corpus base rate p₀, every applicable factor contributes a shift Δₕ and the score is the recombined probability.

logit(p) = ln( p / (1 − p) )
ℓ = logit(p0) + ∑i Δℓi
Δℓi = logit(pi) − logit(p0)
p̂ = σ(ℓ) = 1 / (1 + e−ℓ)  →  score = round(99 · p̂)

Why this shape. Because every Δₕ is an independent, printable quantity, the screen can list "this payer denies 31% of these, +0.42 logits" beside the number. A gradient-boosted model would likely score marginally better and could not do that, and an unexplainable denial score is one nobody in a billing office will act on.

Laplace flooring. Rates are floored at 0.02 before the log so a payer with two historical claims cannot produce an infinite shift.

Data flow

Model architecture

↑ back to the registry

Coding integrity

coding classifier running: Coding integrity model v1.0

What it does

This reads in both directions at once. It finds care that clearly happened in the notes but never made it onto the bill, and it finds things that were billed with no note to support them. A tool that only looks for missed revenue is upcoding with better branding; looking both ways is what makes it an integrity check. It drafts a question for a human coder — it never edits a code or a note.

Live metrics

Read from the running system at page load.

How it works — technical

Two-sided evidence comparison. Let D be the set of clinical assertions extracted from documentation in the claim window, and C the set of coded concepts on the claim.

under-coded = { d ∈ D : ¬∃ c ∈ C, maps(d, c) }
under-documented = { c ∈ C : ¬∃ d ∈ D, supports(d, c) }
window: |date(d) − date(c)| ≤ 45 days

Both directions are reported, always. The screen shows both sets side by side and the counts are never filtered to the profitable one. Reporting only the first set would change the tool’s purpose.

Output is a query, not an edit. Findings become drafted coder queries in the signature queue. The model has no write path to a code or a note.

Data flow

Model architecture

↑ back to the registry

Imaging read assistant

imaging vision running: Imaging read assistant v1.0

What it does

This looks at the actual pixels of a scan and writes what it sees — the technique used, the findings, and measurements taken from the image’s own scale. It is a second reader, not the reader: the draft goes to the signature queue for a radiologist. In this demo the images are synthetic and some contain deliberately planted findings, so you can check whether the model actually found what is there.

Live metrics

Read from the running system at page load.

How it works — technical

Vision-language inference over rendered frames. A frame is selected, encoded into visual tokens, and read jointly with a structured prompt carrying modality, body part and acquisition scale.

tokens = Φv(frame)  ∈  ℝn×d
report = LM( tokens ⊕ prompt(modality, part, mm/px) )
sizemm = sizepx × (mm/px)   (scale is given, never inferred)

Measurement honesty. The acquisition scale is supplied to the model rather than estimated from the image, so a reported millimetre figure is arithmetic on a known constant and not a guess about pixel size.

Evaluation in the demo. Findings are planted deterministically at generation time and never disclosed to the model, so a read that reports one is genuine detection rather than prompt leakage.

Data flow

Model architecture

↑ back to the registry

Terminology mapping

ingest mapper running: Terminology mapper v3.0

What it does

Different systems call the same thing by different names and codes. This maps incoming source terms onto standard vocabularies so that a question about "diabetes" finds every patient who has it, however their record spelled it. When it cannot find a confident target it leaves the term unmapped and says so, because a wrong mapping is far more dangerous than a missing one.

Live metrics

Read from the running system at page load.

How it works — technical

Licensed vocabulary lookup with an abstention band. Exact code matches first, then normalised lexical matching against the licensed vocabulary. Below threshold the term is left unmapped and counted.

map(t) = argmaxc∈V sim(norm(t), norm(c))   if   sim ≥ θ
sim(a,b) = |trigrams(a) ∩ trigrams(b)| / |trigrams(a) ∪ trigrams(b)|
sim < θ ⇒ unmapped, surfaced in QA

Licences are enforced, not assumed. SNOMED, CPT and UMLS require the deploying organisation’s own licences. The loader fails loudly on missing credentials rather than silently degrading coverage.

Data flow

Model architecture

↑ back to the registry

Ingest & mapping QA

ingestqa rules + LLM reviewer running: Ingest QA reviewer v1.0

What it does

After records land, this sweeps the entire store looking for things that cannot be true — a condition that started before the patient was born, a visit that ended before it began, a lab result with no units. The rules find the problems; a model then reads the findings and argues about what is probably broken upstream and what to fix first. The rules are the authority — the model never marks anything as wrong on its own.

Live metrics

Read from the running system at page load.

How it works — technical

Deterministic integrity predicates. Each check is a closed-form predicate over the store, counted exactly. There is no sampling and no scoring.

violations(r) = | { x ∈ store : ¬r(x) } |
r1: onset ≥ birth  ·  r2: onset ≤ today  ·  r3: abatement ≥ onset
r4: end ≥ start  ·  r5: valuenum ⇒ unit ≠ ∅

A zero is a finding. Reporting zero for a rule is information: it says the mapping held across the whole corpus for that invariant. The screen shows every rule, not only the failing ones.

The model reasons, it does not score. The reviewer receives counts and sample rows and argues root causes and fix order. It cannot change a count or quarantine a row.

Data flow

Model architecture

↑ back to the registry

Patient instructions

instructions generative + checker running: Patient instructions writer v1.0

What it does

This writes the sheet a patient takes home, in plain language drawn only from their chart. Then a second model reads the first one’s work and checks every clinical statement against the record. If it finds even one instruction that the chart does not support, the whole draft is refused — it cannot reach the signature queue at all. An invented instruction reaching a patient is the worst thing this feature could do, so the check is a gate and not a report.

Live metrics

Read from the running system at page load.

How it works — technical

Generate, then verify against the source. Two passes with different jobs. The writer is constrained to the chart facts; the checker treats the writer as untrusted.

draft = LMwriter( facts(p) )   constrained to restatement
V = { (a, verdict) : a ∈ assertions(draft) }
pass ⇔ ∀ a ∈ assertions(draft), ∃ f ∈ facts(p) : supports(f, a)
release ⇔ pass   (a single NOT-IN-RECORD blocks the whole draft)

Fail closed on a malformed check. If the checker does not return a parsable verdict line, the result is treated as failure, not as absence of failure. An unreadable safety check is a failed one.

Reading level. The writer targets a 6th–8th grade reading level; the checker ignores style entirely and judges only whether each clinical claim is supported.

Data flow

Model architecture

↑ back to the registry

No-show risk

noshow predictive running: No-show risk model v2.1

What it does

For each upcoming appointment this estimates how likely the patient is not to arrive, so a clinic can spend its limited outreach on the people most likely to need it. Every point of the score is printed next to it — how long since they were last seen, how thin their visit history is, their age band, their coverage. Nothing is hidden, because a risk score nobody can inspect is a rumour.

Live metrics

Read from the running system at page load.

How it works — technical

Transparent additive scoring. A deliberately simple model. Each feature contributes a fixed integer weight; the total is clipped to a usable range.

s = clip( b + ∑i wi · 1[featurei present] , 5, 95 )
b = 10 (base)  ·  w ∈ { +30, +20, +15, +12, +10, +8, −10 }

Why integers, not a fit. The clinic acts on rank order, not calibrated probability — who to call first with the twelve calls you have time for. Integer weights survive being read aloud in a huddle, and every one of them is defensible to the person being called.

Known limitation. Payer is a feature (Medicaid, +10). That correlates with access barriers rather than intent, and it is exactly the kind of term the fairness screen exists to keep honest. It is documented here rather than buried.

Data flow

Model architecture

↑ back to the registry

Prior-auth evidence assembly

priorauth retrieval running: Prior auth evidence assembler v1.0

What it does

Insurers publish criteria for approving expensive care. This reads those criteria one line at a time and goes looking in the chart for the evidence each one needs — marking what is met, what is not, and what a human has to judge. It assembles the appeal packet with citations. It does not decide whether the patient qualifies, and it never sends anything.

Live metrics

Read from the running system at page load.

How it works — technical

Criterion-wise evidence retrieval. Each policy criterion becomes its own retrieval query against the patient’s record, evaluated independently so a single strong match cannot carry a weak one.

∀ k ∈ criteria(policy): Ek = topN( retrieve(k, chart(p)) )
verdictk = met  if  ∃ e ∈ Ek : entails(e, k)
packet = ⋃k { (k, verdictk, cite(Ek)) }

Injection-guarded policy text. Payer policy text is third-party content pasted into the system. It is handled as data and fenced from the instruction channel — a policy document cannot tell the model what to do.

No approval semantics. The output is an evidence packet with citations. Medical necessity remains a clinical judgement, and the appeal is a draft in the signature queue.

Data flow

Model architecture

↑ back to the registry

Release-of-information validation

roi classifier running: ROI requirements validator v1.0

What it does

When someone requests a copy of a patient’s records, the law that governs the release depends on who is asking, why, and where they are. This checks the request against every requirement of the applicable jurisdiction and names any that are unmet. It can stop a release; it can never approve one. The decision stays with the records professional, and both outcomes are recorded.

Live metrics

Read from the running system at page load.

How it works — technical

Rule evaluation over a jurisdiction table. Requirements are data, not code. Each carries an authority citation and a hardness flag.

blocked ⇔ ∃ r ∈ R(j) : hard(r) ∧ ¬met(r, request)
verdict(r) ∈ { met, unmet, needs review }
unconfigured jurisdiction ⇒ blocked   (fail closed)

Asymmetric authority. The validator has the power to refuse and no power to permit. A release that passes every check still requires a human to press fulfil, and that press is what is audited as the disclosure.

Part 2 redisclosure. Substance-use-disorder records carry a separate consent requirement for the specific disclosure; absent it, fulfilment records a refusal rather than releasing.

Data flow

Model architecture

↑ back to the registry

Scheduling optimization

scheduling optimization running: Scheduling optimizer v1.2

What it does

Using the clinic’s real demand pattern and the current no-show risk, this suggests how much to overbook each hour of the day. It prices the trade-off; it does not book anyone. No patient is named on this screen — it works entirely in counts.

Live metrics

Read from the running system at page load.

How it works — technical

Expected-loss overbooking. Overbooking guidance is the expected number of empty slots at that hour, scaled by how busy the hour actually is.

load(h) = volume(h) / maxh′ volume(h′)
overbook(h) = round( p̄no-show · capacity · load(h) )
no-show = mean no-show risk over the current worklist

A price, not a decision. Overbooking trades patient wait time against idle clinician time. The platform quantifies the trade; it holds no write path into any scheduling system.

Data flow

Model architecture

↑ back to the registry

Sensitivity classification

segmentation classifier running: Sensitivity classifier v1.4

What it does

Some records are protected more tightly than the rest of a chart — addiction treatment, mental health, HIV, reproductive and genetic care. This reads every incoming condition, medication and document and decides which of those categories it belongs to, at the moment it arrives. When it is not sure, it does not guess: the record stays withheld and a person decides. Getting this wrong in the permissive direction is the worst mistake this platform could make, so it is built to fail closed.

Live metrics

Read from the running system at page load — queue depth is the live count of withheld, unresolved classifications.

How it works — technical

Evidence-term matching with a confidence floor. A lexicon of category-bearing terms is matched against coded values and extracted prose. Confidence rises with the number of independent supporting terms.

conf(c) = 1 − ∏e∈E(c) (1 − τe)
assign c* = argmaxc conf(c)  if  conf(c*) ≥ θhigh
queue for human review  if  θlow ≤ conf(c*) < θhigh

The asymmetry is deliberate. A false negative discloses a protected record; a false positive withholds an ordinary one. These costs are nowhere near equal, so the uncertain band resolves to withheld-and-queued rather than to the more likely label.

Human decisions are the training signal. Every reclassification is audited as segmentation.reclassified and becomes labelled data — the queue is the loop, not a backlog.

Data flow

Model architecture

↑ back to the registry

Inbox triage

triage deterministic ranking running: Inbox triage ranker v1.0

What it does

A clinician’s inbox fills with abnormal results, new documents and unsigned drafts. This puts them in order of urgency and shows why each one sits where it does. Crucially it only reorders — nothing is ever removed. A triage tool that hides an item is a safety incident waiting to happen, so the whole queue is always present, worst first.

Live metrics

Read from the running system at page load.

How it works — technical

Recency-decayed severity ranking. A transparent score per item, with the reason string carried alongside it.

s(i) = max( smin , s0 − α · agedays(i) )
abnormal result: s0 = 90, α = 2/day, smin = 5
ordering: sort by s(i) descending  ·  |queue| preserved

Reordering is not filtering. The invariant is that the output set equals the input set. Items leave the inbox by being acted on, never by scoring low.

Data flow

Model architecture

↑ back to the registry

How these numbers are produced

Metrics come from the same functions the model monitoring screen uses, computed against the live Data Store on each page load rather than cached into the documentation. Drift is population stability on the payer mix; separation is the gap between mean scores on outcomes already known. Where a slot has no meaningful aggregate — a refusal gate, for instance — this page says so instead of inventing one.

Every figure here is computed over synthetic data. The methods are real; the population is not, and no metric on this page should be read as evidence of clinical performance.