Spaces:
Sleeping
Sleeping
|
Download docs/ARCHITECTURE.md from charlesyapai/hcc-meat-coder: direct link, hf CLI and curl.
- Browser
- Download file 5.17 kB
-
https://huggingface.co/spaces/charlesyapai/hcc-meat-coder/resolve/main/docs/ARCHITECTURE.md
- Command line
-
hf download hf://spaces/charlesyapai/hcc-meat-coder/docs/ARCHITECTURE.md
-
curl -L -o ARCHITECTURE.md https://huggingface.co/spaces/charlesyapai/hcc-meat-coder/resolve/main/docs/ARCHITECTURE.md
5.17 kB
| # Architecture | |
| ## Data contract (single source of truth) | |
| [`app/pipeline/types.py`](../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](../app/pipeline/components/a_segmenter.py)) | Note | Note with sections | Rule-based (real, narrow) | | |
| | B | Clinical NER ([b_ner.py](../app/pipeline/components/b_ner.py)) | Note | `list[Span]` | Dictionary baseline (stub) | | |
| | C | Negation + Temporality ([c_negation.py](../app/pipeline/components/c_negation.py)) | Note + spans | Spans with flags; `is_attributable()` filter | Rule-based (real) | | |
| | D | ICD-10 Linker ([d_linker.py](../app/pipeline/components/d_linker.py)) | Spans | `list[ICD10Link]` | Exact + alias match (stub) | | |
| | E | HCC Crosswalk ([e_crosswalk.py](../app/pipeline/components/e_crosswalk.py)) | Links | HCC candidates + trumping | **Real** (DuckDB + CSV) | | |
| | F | MEAT Extractor ([f_meat.py](../app/pipeline/components/f_meat.py)) | Note + candidate | `list[MEATEvidence]` | Rule-based (stub) | | |
| | G | Calibrator ([g_calibrator.py](../app/pipeline/components/g_calibrator.py)) | HCC + raw conf | Calibrated conf | Identity (stub) | | |
| | H | Over-coding Risk ([h_risk.py](../app/pipeline/components/h_risk.py)) | Candidate | `RiskAssessment` | **Real** (transparent heuristic) | | |
| | I | Verifier ([i_verifier.py](../app/pipeline/components/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. | |