The problem
Family-based immigration filings (marriage-based adjustment of status, K-1, standalone I-130) require assembling many documents into precisely filled USCIS forms.
Manual form-filling is slow and error-prone, and naive LLM auto-fill risks inventing field values that must be legally defensible.
The approach
Made a typed 'case record' the single source of truth; every form and draft is a derived view over it, so auto-fill stays auditable.
Constrained the LLM to two narrow jobs — document classification and field extraction with citation back to the source page — never free-form value invention.
Modeled USCIS forms as JSON field maps so adding a new form is a content task rather than an engineering change.
What I built
- A FastAPI backend structured around the case flow: intake, document ingest and classification, form auto-fill, and packet assembly
- Routers and services for intake, documents, forms, and packet generation, with Pydantic schemas defining the structured case record
- Form metadata and field maps (form-field id to dotted case-record path) for I-130 and related forms
- PDF packet assembly via pypdf that fills AcroForm fields and stitches exhibits with bookmarks and tabs
- A regression eval set run on every change to guard classification and extraction quality
- A static intake demo UI exercising the end-to-end skeleton flow
- Python
- FastAPI
- Uvicorn
- Pydantic v2
- pypdf
- HTML/JavaScript
Result
A V0 platform whose spine is the typed case record: LLM steps are constrained to classification and cited extraction, OCR and model calls sit behind swappable interfaces, and a regression eval guards quality on every change.