Files · Azure AI Document Pipeline for SMB Medical Claim Processing
87 (1 binary, 562.1 kB total)attempt 2
README.md·7355 B·markdown
markdown
# Azure AI Document Pipeline for SMB Medical Claim Processing
> Ingest EOBs and insurance claims from PDFs, repair malformed LLM outputs, and route low-confidence extractions for human review—all with cost-aware caching.
Small medical practices and billing companies manually extract data from Explanation of Benefits (EOB) documents and insurance claims, leading to errors, delays, and high administrative costs. This pipeline automates the process using Azure Document Intelligence for OCR, Azure OpenAI for structured extraction, and the `@reaatech/*` package family for JSON repair, confidence routing, cost tracking, budget enforcement, and smart caching.
---
## Architecture
```
PDF Upload
│
▼
Azure Document Intelligence ─── OCR & layout extraction
│
▼
LLM Extraction (Azure OpenAI) ─── raw JSON from extracted text
│
▼
structured-repair-core ─── repairs malformed LLM JSON output
│
▼
confidence-router-core ─── evaluates extraction confidence
│ │
│ ├── high confidence ───→ response returned immediately
│ │
│ └── low confidence ───→ Postgres review queue → human review → response
│
▼
Response (ExtractedClaim JSON)
```
Caching (`llm-cache` + Redis adapter) avoids redundant LLM calls for duplicate documents. Cost tracking (`llm-cost-telemetry`) records per-request token usage and dollar cost. Budget enforcement (`agent-budget-engine`) short-circuits the pipeline when a daily spend limit is exceeded.
---
## REAA Packages
| Package | Role |
|---|---|
| `@reaatech/structured-repair-core` | Repairs malformed JSON returned by the LLM (unclosed braces, missing quotes, stray tokens, etc.) |
| `@reaatech/confidence-router-core` | Routes low-confidence extractions to a human review queue instead of returning them directly |
| `@reaatech/agent-budget-spend-tracker` | Spend tracking data layer for budget engine |
| `@reaatech/agent-budget-types` | Core types and Zod schemas for budget engine |
| `@reaatech/llm-cache` | Exact-match and semantic cache for LLM responses to avoid redundant API calls |
| `@reaatech/llm-cache-adapters-redis` | Redis-backed storage adapter for the LLM cache |
| `@reaatech/llm-cost-telemetry` | Captures per-request token counts and computes USD cost for each LLM invocation |
| `@reaatech/agent-budget-engine` | Enforces a daily budget cap; rejects requests when the spend limit is reached |
---
## Third-Party Dependencies
| Package | Role |
|---|---|
| `@azure/ai-form-recognizer` | Azure Document Intelligence SDK — OCR and layout analysis of uploaded PDFs/forms |
| `@azure/openai` | Azure OpenAI SDK — sends extracted document text to GPT-4o for structured claim extraction |
| `sharp` | Image preprocessing (resize, JPEG compression) before OCR for optimal accuracy |
| `postgres` | PostgreSQL client — stores the human-review queue |
| `ioredis` | Redis client — powers the LLM response cache adapter |
| `zod` | Runtime schema validation for extracted claims (input parsing, type guards) |
| `p-retry` | Retry wrapper around Azure OpenAI calls (3 retries on network failures) |
| `p-limit` | Concurrency limiter for the pipeline (max 3 concurrent document processes) |
| `jsonrepair` | Fast first-pass JSON syntax fix before handing to structured-repair-core |
| `langfuse` | LLM observability and tracing (optional, configured via Langfuse env vars) |
| `next` | Next.js 16 App Router — API route handlers and (optional) minimal UI |
| `uuid` | Unique ID generation for claims, review entries, and cost spans |
---
## Environment Variables
| Variable | Required | Description |
|---|---|---|
| `NODE_ENV` | No | Environment mode (`development`, `production`, `test`; defaults to `development`) |
| `AZURE_DOCUMENT_INTELLIGENCE_ENDPOINT` | Yes | Azure Document Intelligence service endpoint URL |
| `AZURE_DOCUMENT_INTELLIGENCE_KEY` | Yes | API key for Azure Document Intelligence |
| `AZURE_OPENAI_ENDPOINT` | Yes | Azure OpenAI service endpoint URL |
| `AZURE_OPENAI_KEY` | Yes | API key for Azure OpenAI |
| `AZURE_OPENAI_DEPLOYMENT` | Yes | The deployed model name on Azure OpenAI (e.g. `gpt-4o`) |
| `REDIS_URL` | Yes | Redis connection string (e.g. `redis://localhost:6379`) for LLM cache |
| `POSTGRES_URL` | Yes | PostgreSQL connection string (e.g. `postgres://user:pass@localhost:5432/claims`) for review queue |
| `LANGFUSE_PUBLIC_KEY` | No | Langfuse public key for LLM observability |
| `LANGFUSE_SECRET_KEY` | No | Langfuse secret key |
| `LANGFUSE_HOST` | No | Langfuse host URL (defaults to `https://cloud.langfuse.com`) |
| `CONFIDENCE_ROUTE_THRESHOLD` | No | Confidence score at or above which an extraction is auto-approved (default `0.8`) |
| `CONFIDENCE_FALLBACK_THRESHOLD` | No | Confidence score below which an extraction is rejected outright (default `0.3`) |
| `ENABLE_HUMAN_REVIEW` | No | Whether to enable the human-review queue for medium-confidence claims (default `true`) |
| `BUDGET_DAILY_LIMIT` | No | Maximum daily spend in USD before the pipeline rejects requests (default `10.0`) |
---
## Getting Started
```bash
# Install dependencies
pnpm install
# Copy and configure environment variables
cp .env.example .env
# Edit .env with your Azure, Redis, and Postgres credentials
# Start the development server
pnpm dev
# Run the test suite (vitest with coverage)
pnpm test
# Lint the codebase
pnpm lint
# Type-check
pnpm typecheck
```
---
## API Routes
### POST `/api/claims/upload`
Upload a PDF (or image) document for processing.
- **Content-Type**: `multipart/form-data`
- **Body field**: `file` — the document blob
- **Success (200)**: `{ success: true, claim: ExtractedClaim, confidence: number, status: "approved" }`
- **Needs Review (202)**: `{ success: false, error: string, needsReview: true, claim: PartialClaim }`
- **Bad Request (400)**: `{ error: "no file provided" }` or `{ error: "empty file" }`
- **Payload Too Large (413)**: `{ error: "file too large" }` (limit: 10 MB)
- **Unprocessable (422)**: `{ success: false, error: string }`
### GET `/api/claims/review`
Return all pending review-queue entries.
- **Success (200)**: `{ items: ReviewQueueEntry[] }`
- **Empty**: `{ items: [] }`
### PATCH `/api/claims/review/:id`
Resolve a review-queue entry (approve or reject).
- **Body**: `{ approved: boolean }`
- **Success (200)**: `{ status: "resolved" }`
### GET `/api/health`
Health-check endpoint that verifies Redis and Postgres connectivity.
- **Success (200)**: `{ status: "ok", redis: "connected", postgres: "connected" }`
- **Degraded (200)**: reports which services are unreachable
---
## Project Layout
```
app/ Next.js App Router — API routes (claims/upload, claims/review, health)
src/
services/ Pipeline, document-intelligence, llm, claim-repair,
confidence-router, llm-cache-service, cost-telemetry,
budget-service, image-preprocessor, review-queue
lib/ Utilities (id generation, errors, concurrency, JSON repair)
types/ Zod schemas and TypeScript types (ClaimSchema, ExtractedClaim, etc.)
tests/ Vitest test suite (mirrors src/ layout)
packages/ API references for every dependency
```
---
## License
MIT — see [LICENSE](./LICENSE).