stellar413/AI_adjudication
0
1# Plum OPD Claim Adjudication Tool2 3An 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.4 5---6 7## Table of Contents8 9- [System Architecture](#system-architecture)10- [Database Schema (ER Diagram)](#database-schema-er-diagram)11- [Claim Decision Flow](#claim-decision-flow)12- [Tech Stack](#tech-stack)13 14---15 16## System Architecture17 18The 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.19 20```mermaid21graph TD22 User(["User / Claimant"]) <-->|"Browser / UI"| Streamlit["Streamlit Portal"]23 Streamlit <-->|"HTTP / JSON"| FastAPI["FastAPI Backend Application"]24 25 subgraph Backend ["FastAPI Backend"]26 Router["API Router"] <--> Repository["Repository CRUD Layer"]27 Router <--> PolicyService["Policy & Rules Engine"]28 Router <--> GeminiService["Gemini Integration Services"]29 30 PolicyService -->|"Check Rules"| ConfCalc["Confidence & Flags Calculator"]31 end32 33 GeminiService <-->|"Multimodal API / SDK"| GeminiAPI["Google Gemini 2.5 Flash API"]34 Repository <-->|"SQLAlchemy ORM"| DB[("SQLite / PostgreSQL Database")]35 36 classDef main fill:#1E3A8A,color:#fff,stroke:#10B981,stroke-width:2px;37 classDef external fill:#111827,color:#fff,stroke:#F59E0B,stroke-width:2px;38 classDef secondary fill:#F3F4F6,color:#1E293B,stroke:#9CA3AF,stroke-width:1px;39 40 class Streamlit,FastAPI,PolicyService,GeminiService main;41 class GeminiAPI,DB external;42 class Router,Repository,ConfCalc secondary;43```44 45### Component Summary46 47| Component | Role |48|---|---|49| **Streamlit Portal** | Browser-based UI for claim submission and status tracking |50| **FastAPI Backend** | REST API gateway; orchestrates all backend services |51| **API Router** | Routes incoming requests to the appropriate service layer |52| **Repository (CRUD)** | SQLAlchemy-based data access layer for all DB operations |53| **Policy & Rules Engine** | Deterministic eligibility checks (waiting period, annual limit, member status) |54| **Confidence & Flags Calculator** | Computes composite confidence score; raises fraud/ambiguity flags |55| **Gemini Integration Services** | Handles OCR extraction and AI-based adjudication via Gemini SDK |56| **Gemini 2.5 Flash API** | Google's multimodal LLM — processes bills, prescriptions, lab reports |57| **Database** | Stores members, claims, documents, results, and audit logs |58 59---60 61## Database Schema (ER Diagram)62 63Five entities capture the full lifecycle of a claim — from member identity through document ingestion, adjudication result, and audit trail.64 65```mermaid66erDiagram67 MEMBERS {68 string id PK "e.g., EMP001"69 string name70 string policy_number71 date join_date72 float annual_limit_remaining73 string status "ACTIVE / INACTIVE"74 }75 76 CLAIMS {77 string id PK "e.g., CLM_XXXXX"78 string member_id FK79 string patient_name80 float claim_amount81 string status "PENDING / APPROVED / REJECTED / PARTIAL / MANUAL_REVIEW"82 string hospital_name83 boolean cashless_request84 date treatment_date85 timestamp submitted_at86 timestamp updated_at87 }88 89 CLAIM_DOCUMENTS {90 int id PK91 string claim_id FK92 string document_type "PRESCRIPTION / BILL / LAB_REPORT / OTHER"93 string file_path94 string file_name95 int file_size96 json extracted_data97 text raw_llm_response98 }99 100 ADJUDICATION_RESULTS {101 int id PK102 string claim_id FK "Unique"103 string decision "APPROVED / REJECTED / PARTIAL / MANUAL_REVIEW"104 float approved_amount105 float confidence_score106 json reasons "List of strings"107 json flags "List of strings"108 text notes109 text next_steps110 json policy_engine_log111 timestamp created_at112 }113 114 AUDIT_LOGS {115 int id PK116 string claim_id FK117 string action "e.g., CLAIM_SUBMITTED, OCR_EXTRACTED"118 timestamp timestamp119 text details120 }121 122 MEMBERS ||--o{ CLAIMS : "submits"123 CLAIMS ||--o{ CLAIM_DOCUMENTS : "contains"124 CLAIMS ||--|| ADJUDICATION_RESULTS : "produces"125 CLAIMS ||--o{ AUDIT_LOGS : "records"126```127 128### Relationships129 130| Relationship | Cardinality | Description |131|---|---|---|132| `MEMBERS` → `CLAIMS` | One-to-many | A member can submit multiple claims |133| `CLAIMS` → `CLAIM_DOCUMENTS` | One-to-many | A claim can have multiple supporting documents |134| `CLAIMS` → `ADJUDICATION_RESULTS` | One-to-one | Each claim produces exactly one adjudication result |135| `CLAIMS` → `AUDIT_LOGS` | One-to-many | Every state change on a claim is logged |136 137---138 139## Claim Decision Flow140 141The 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.142 143```mermaid144graph TD145 Start(["Claim Submitted"]) --> Upload["Save Documents & Metadata"]146 Upload --> OCR["Gemini Multimodal OCR & Extraction"]147 OCR --> DeterministicChecks{"Run Deterministic Checks"}148 149 DeterministicChecks -->|"Failed: Member Inactive / Waiting Period / Per-claim Exceeded"| Reject["Set Status: REJECTED"]150 DeterministicChecks -->|"Passed: Basic Eligibility Met"| AICheck{"Run Gemini AI Adjudication"}151 152 AICheck -->|"Exclusions Found / Lack of Medical Necessity"| AIReject["Set Status: REJECTED or PARTIAL"]153 AICheck -->|"Valid & Medically Necessary"| CalcLimits["Calculate Limits & Copays / Discounts"]154 155 CalcLimits --> ConfidenceCheck{"Evaluate Composite Confidence"}156 157 ConfidenceCheck -->|"Confidence < 70% or Fraud Flags"| Review["Set Status: MANUAL_REVIEW"]158 ConfidenceCheck -->|"Confidence >= 70% & No Flags"| Approve["Set Status: APPROVED or PARTIAL"]159 160 Approve --> UpdateLimit["Deduct Approved Amount from YTD Limit"]161 UpdateLimit --> Log["Record Adjudication & Update Status"]162 163 Reject --> Log164 AIReject --> Log165 Review --> Log166 167 Log --> End(["Processing Complete"])168 169 classDef process fill:#DBEAFE,color:#1E40AF,stroke:#3B82F6;170 classDef decision fill:#FEF3C7,color:#92400E,stroke:#F59E0B;171 classDef terminal fill:#FEE2E2,color:#991B1B,stroke:#EF4444;172 classDef start fill:#D1FAE5,color:#065F46,stroke:#10B981;173 174 class Start,End start;175 class DeterministicChecks,AICheck,ConfidenceCheck decision;176 class Upload,OCR,CalcLimits,UpdateLimit,Log process;177 class Reject,AIReject,Review,Approve terminal;178```179 180### Decision Stages181 182**Stage 1 — Deterministic Checks**183Hard policy rules evaluated before any AI call. A failure here results in an immediate rejection.184 185| Check | Fail Condition |186|---|---|187| Member status | Member is `INACTIVE` |188| Waiting period | Treatment date is within the policy's waiting window |189| Per-claim limit | Claimed amount exceeds the maximum allowable per single claim |190 191**Stage 2 — Gemini AI Adjudication**192Gemini 2.5 Flash reviews the extracted document data against policy exclusions and assesses medical necessity.193 194| Outcome | Description |195|---|---|196| `REJECTED` | Claim falls under a policy exclusion |197| `PARTIAL` | Partial medical necessity — only a portion of the claim is valid |198| Passes | Claim is valid and medically necessary → proceeds to limit calculation |199 200**Stage 3 — Confidence Gate**201A composite confidence score is computed from OCR quality, AI certainty, and policy match strength.202 203| Score | Fraud Flags | Final Status |204|---|---|---|205| ≥ 70% | None | `APPROVED` or `PARTIAL` |206| < 70% | Any | `MANUAL_REVIEW` |207 208---209 210## Tech Stack211 212| Layer | Technology |213|---|---|214| Frontend | Streamlit |215| Backend API | FastAPI (Python) |216| ORM | SQLAlchemy |217| Database | SQLite (dev) / PostgreSQL (prod) |218| AI / OCR | Google Gemini 2.5 Flash (multimodal) |219| Document types | Prescriptions, hospital bills, lab reports |220 