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

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.

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.

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.

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