AI_adjudication / docs /architecture.md
stellar413's picture
Initial commit: Plum OPD Claim Adjudication Engine with Hybrid Decision Pipeline
f047704
|
Raw
History Blame Contribute Delete
8.27 kB
# Plum OPD Claim Adjudication Tool
An intelligent, multimodal claim adjudication system for OPD (Outpatient Department) insurance claims. It combines a deterministic policy rules engine with Google Gemini 2.5 Flash to automate document extraction, eligibility checks, and final claim decisions β€” surfacing only genuinely ambiguous cases to human reviewers.
---
## Table of Contents
- [System Architecture](#system-architecture)
- [Database Schema (ER Diagram)](#database-schema-er-diagram)
- [Claim Decision Flow](#claim-decision-flow)
- [Tech Stack](#tech-stack)
---
## System Architecture
The system is composed of three tiers: a Streamlit web portal for claimants, a FastAPI backend hosting the adjudication logic, and two external services β€” the Gemini 2.5 Flash API for multimodal AI and a relational database for persistence.
```mermaid
graph TD
User(["User / Claimant"]) <-->|"Browser / UI"| Streamlit["Streamlit Portal"]
Streamlit <-->|"HTTP / JSON"| FastAPI["FastAPI Backend Application"]
subgraph Backend ["FastAPI Backend"]
Router["API Router"] <--> Repository["Repository CRUD Layer"]
Router <--> PolicyService["Policy & Rules Engine"]
Router <--> GeminiService["Gemini Integration Services"]
PolicyService -->|"Check Rules"| ConfCalc["Confidence & Flags Calculator"]
end
GeminiService <-->|"Multimodal API / SDK"| GeminiAPI["Google Gemini 2.5 Flash API"]
Repository <-->|"SQLAlchemy ORM"| DB[("SQLite / PostgreSQL Database")]
classDef main fill:#1E3A8A,color:#fff,stroke:#10B981,stroke-width:2px;
classDef external fill:#111827,color:#fff,stroke:#F59E0B,stroke-width:2px;
classDef secondary fill:#F3F4F6,color:#1E293B,stroke:#9CA3AF,stroke-width:1px;
class Streamlit,FastAPI,PolicyService,GeminiService main;
class GeminiAPI,DB external;
class Router,Repository,ConfCalc secondary;
```
### Component Summary
| Component | Role |
|---|---|
| **Streamlit Portal** | Browser-based UI for claim submission and status tracking |
| **FastAPI Backend** | REST API gateway; orchestrates all backend services |
| **API Router** | Routes incoming requests to the appropriate service layer |
| **Repository (CRUD)** | SQLAlchemy-based data access layer for all DB operations |
| **Policy & Rules Engine** | Deterministic eligibility checks (waiting period, annual limit, member status) |
| **Confidence & Flags Calculator** | Computes composite confidence score; raises fraud/ambiguity flags |
| **Gemini Integration Services** | Handles OCR extraction and AI-based adjudication via Gemini SDK |
| **Gemini 2.5 Flash API** | Google's multimodal LLM β€” processes bills, prescriptions, lab reports |
| **Database** | Stores members, claims, documents, results, and audit logs |
---
## Database Schema (ER Diagram)
Five entities capture the full lifecycle of a claim β€” from member identity through document ingestion, adjudication result, and audit trail.
```mermaid
erDiagram
MEMBERS {
string id PK "e.g., EMP001"
string name
string policy_number
date join_date
float annual_limit_remaining
string status "ACTIVE / INACTIVE"
}
CLAIMS {
string id PK "e.g., CLM_XXXXX"
string member_id FK
string patient_name
float claim_amount
string status "PENDING / APPROVED / REJECTED / PARTIAL / MANUAL_REVIEW"
string hospital_name
boolean cashless_request
date treatment_date
timestamp submitted_at
timestamp updated_at
}
CLAIM_DOCUMENTS {
int id PK
string claim_id FK
string document_type "PRESCRIPTION / BILL / LAB_REPORT / OTHER"
string file_path
string file_name
int file_size
json extracted_data
text raw_llm_response
}
ADJUDICATION_RESULTS {
int id PK
string claim_id FK "Unique"
string decision "APPROVED / REJECTED / PARTIAL / MANUAL_REVIEW"
float approved_amount
float confidence_score
json reasons "List of strings"
json flags "List of strings"
text notes
text next_steps
json policy_engine_log
timestamp created_at
}
AUDIT_LOGS {
int id PK
string claim_id FK
string action "e.g., CLAIM_SUBMITTED, OCR_EXTRACTED"
timestamp timestamp
text details
}
MEMBERS ||--o{ CLAIMS : "submits"
CLAIMS ||--o{ CLAIM_DOCUMENTS : "contains"
CLAIMS ||--|| ADJUDICATION_RESULTS : "produces"
CLAIMS ||--o{ AUDIT_LOGS : "records"
```
### Relationships
| Relationship | Cardinality | Description |
|---|---|---|
| `MEMBERS` β†’ `CLAIMS` | One-to-many | A member can submit multiple claims |
| `CLAIMS` β†’ `CLAIM_DOCUMENTS` | One-to-many | A claim can have multiple supporting documents |
| `CLAIMS` β†’ `ADJUDICATION_RESULTS` | One-to-one | Each claim produces exactly one adjudication result |
| `CLAIMS` β†’ `AUDIT_LOGS` | One-to-many | Every state change on a claim is logged |
---
## Claim Decision Flow
The adjudication engine processes each submitted claim through three sequential stages: deterministic eligibility checks, AI-powered medical necessity review, and a confidence threshold gate before final status assignment.
```mermaid
graph TD
Start(["Claim Submitted"]) --> Upload["Save Documents & Metadata"]
Upload --> OCR["Gemini Multimodal OCR & Extraction"]
OCR --> DeterministicChecks{"Run Deterministic Checks"}
DeterministicChecks -->|"Failed: Member Inactive / Waiting Period / Per-claim Exceeded"| Reject["Set Status: REJECTED"]
DeterministicChecks -->|"Passed: Basic Eligibility Met"| AICheck{"Run Gemini AI Adjudication"}
AICheck -->|"Exclusions Found / Lack of Medical Necessity"| AIReject["Set Status: REJECTED or PARTIAL"]
AICheck -->|"Valid & Medically Necessary"| CalcLimits["Calculate Limits & Copays / Discounts"]
CalcLimits --> ConfidenceCheck{"Evaluate Composite Confidence"}
ConfidenceCheck -->|"Confidence < 70% or Fraud Flags"| Review["Set Status: MANUAL_REVIEW"]
ConfidenceCheck -->|"Confidence >= 70% & No Flags"| Approve["Set Status: APPROVED or PARTIAL"]
Approve --> UpdateLimit["Deduct Approved Amount from YTD Limit"]
UpdateLimit --> Log["Record Adjudication & Update Status"]
Reject --> Log
AIReject --> Log
Review --> Log
Log --> End(["Processing Complete"])
classDef process fill:#DBEAFE,color:#1E40AF,stroke:#3B82F6;
classDef decision fill:#FEF3C7,color:#92400E,stroke:#F59E0B;
classDef terminal fill:#FEE2E2,color:#991B1B,stroke:#EF4444;
classDef start fill:#D1FAE5,color:#065F46,stroke:#10B981;
class Start,End start;
class DeterministicChecks,AICheck,ConfidenceCheck decision;
class Upload,OCR,CalcLimits,UpdateLimit,Log process;
class Reject,AIReject,Review,Approve terminal;
```
### Decision Stages
**Stage 1 β€” Deterministic Checks**
Hard policy rules evaluated before any AI call. A failure here results in an immediate rejection.
| Check | Fail Condition |
|---|---|
| Member status | Member is `INACTIVE` |
| Waiting period | Treatment date is within the policy's waiting window |
| Per-claim limit | Claimed amount exceeds the maximum allowable per single claim |
**Stage 2 β€” Gemini AI Adjudication**
Gemini 2.5 Flash reviews the extracted document data against policy exclusions and assesses medical necessity.
| Outcome | Description |
|---|---|
| `REJECTED` | Claim falls under a policy exclusion |
| `PARTIAL` | Partial medical necessity β€” only a portion of the claim is valid |
| Passes | Claim is valid and medically necessary β†’ proceeds to limit calculation |
**Stage 3 β€” Confidence Gate**
A composite confidence score is computed from OCR quality, AI certainty, and policy match strength.
| Score | Fraud Flags | Final Status |
|---|---|---|
| β‰₯ 70% | None | `APPROVED` or `PARTIAL` |
| < 70% | Any | `MANUAL_REVIEW` |
---
## Tech Stack
| Layer | Technology |
|---|---|
| Frontend | Streamlit |
| Backend API | FastAPI (Python) |
| ORM | SQLAlchemy |
| Database | SQLite (dev) / PostgreSQL (prod) |
| AI / OCR | Google Gemini 2.5 Flash (multimodal) |
| Document types | Prescriptions, hospital bills, lab reports |