hcc-meat-coder / docs /ARCHITECTURE.md
chraos's picture
Claude Opus 4.7 (1M context)
Initial scaffold: HCC-MEAT Coder v0.1.0
c6cfe5f
|
Raw History Blame Contribute Delete
5.17 kB

Architecture

Data contract (single source of truth)

app/pipeline/types.py is the authority. Every component consumes and emits instances of these pydantic models. If you need to add a field, add it here first and the components will fail loudly until they handle it.

Key shapes:

  • Note β€” free-text input + optional section list.
  • Span β€” typed offset ranges (Condition/Medication/Lab/...) with negation + temporality.
  • ICD10Link β€” (Condition span, ICD-10 code, linker confidence).
  • HCCCandidate β€” HCC id, RAF weight, hierarchy state, ICD-10 links, confidence (raw + calibrated), MEAT evidence, risk.
  • MEATEvidence β€” category (M/E/A/T), quoted text + offsets, NLI entailment, verified flag.
  • RiskAssessment β€” level (low/medium/high), score, transparent reason list, named component scores.
  • CodingResult β€” the whole thing, serializable.

Component map

# Component Inputs Outputs Real or stub
A Section Segmenter (a_segmenter.py) Note Note with sections Rule-based (real, narrow)
B Clinical NER (b_ner.py) Note list[Span] Dictionary baseline (stub)
C Negation + Temporality (c_negation.py) Note + spans Spans with flags; is_attributable() filter Rule-based (real)
D ICD-10 Linker (d_linker.py) Spans list[ICD10Link] Exact + alias match (stub)
E HCC Crosswalk (e_crosswalk.py) Links HCC candidates + trumping Real (DuckDB + CSV)
F MEAT Extractor (f_meat.py) Note + candidate list[MEATEvidence] Rule-based (stub)
G Calibrator (g_calibrator.py) HCC + raw conf Calibrated conf Identity (stub)
H Over-coding Risk (h_risk.py) Candidate RiskAssessment Real (transparent heuristic)
I Verifier (i_verifier.py) Note + candidate Candidate with verified/dropped evidence Real (substring) + NLI hook

Orchestration order

A segmenter
  β†’ B NER
    β†’ C negation/temporality β†’ filter non-attributable spans
      β†’ D linker (conditions only)
        β†’ E crosswalk + trumping
          β†˜
            F MEAT extractor (per candidate)
              β†’ I verifier (per candidate)
          ↙
          G calibrator (per candidate)
            β†’ H risk (per candidate)
              β†’ rank: non-trumped first, then calibrated_conf Γ— RAF_weight

Notes:

  • I (verifier) sits between F and G β€” a candidate with zero verified MEAT evidence is still kept (with an empty evidence list), because risk heuristic H needs to see that emptiness and flag the candidate accordingly. Dropping the candidate silently would undercount the suspect list a coder needs to see.
  • G (calibrator) runs late because it doesn't affect rank tie-breakers inside E, but it does affect the final ranking H reads.

Why hierarchy trumping is handled inside component E

Trumping requires the full candidate set; it's not a per-span decision. Running it inside the crosswalk (HCCCrosswalk.apply_trumping) keeps the orchestrator code short and the crosswalk tests self-contained.

Why MEAT evidence belongs on HCCCandidate (not on Span)

One MEAT evidence row justifies one HCC. The same sentence can justify Assess for HCC-18 and Monitor for HCC-85. Binding MEATEvidence to HCC rather than to span avoids a many-to-many association table.

API shape

Endpoints in app/api/server.py:

  • POST /api/code β€” {text, note_id} β†’ CodingResult. Single source of truth for the frontend.
  • GET /api/gallery β€” returns precomputed GalleryItem[] for the preloaded demo cases. Computed once at app startup so clicking a gallery entry is instant.
  • GET /api/healthz β€” {status: "ok", version}. Used by the Docker healthcheck.
  • GET /api/reference/hcc β€” HCC label table for UI tooltips linking to CMS.

Frontend

ui/src/App.tsx is a controller holding noteText, result, selectedHCC, and the gallery. Three presentational components:

  • NotePanel β€” textarea + highlight preview (MEAT quotes underlined by category).
  • HCCList β€” ranked HCC suggestions; trumped ones dimmed.
  • DrillIn β€” selected HCC's MEAT-by-category, risk reasons, ICD-10 support.

State flows strictly one-way. The only network call besides gallery is codeNote() from ui/src/lib/api.ts.

Deployment target

Single Docker image (Dockerfile) for an HF Docker Space:

  • Stage 1 (node:20-alpine): build the React UI.
  • Stage 2 (python:3.11-slim): install minimal Python deps, copy app/, eval_harness/, data/reference/, and the built UI at ui/dist/.
  • Uvicorn serves FastAPI on :7860 and the UI via StaticFiles mount.
  • HF Spaces auto-builds the Dockerfile; the Python CI runs on GitHub Actions without building the image.