document_agent / docs /ARCHITECTURE.md
Jai-rathore29's picture
Deploy: DocAgent backend (deterministic date-anomaly fix)
f65e025
|
Raw
History Blame Contribute Delete
4.9 kB
# Architecture β€” Document Processing AI Agent
**Decision record from research (see `RESEARCH.md`). Stack chosen: custom composed stack.**
## High-level
```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ FRONTEND (Next.js + React + TypeScript + Tailwind) β”‚
β”‚ 40% Chat β”‚ 60% Workspace β”‚
β”‚ ──────── β”‚ ── Tabs: Viewer Β· Fields Β· Classify Β· Summary Β· β”‚
β”‚ streaming β”‚ Export ── β”‚
β”‚ agent β”‚ Document viewer w/ bounding-box highlights β”‚
β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚ REST + SSE (streaming)
β”Œβ”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ BACKEND (FastAPI, async) β”‚
β”‚ β”‚
β”‚ api/ routes: documents, chat(SSE), extract, β”‚
β”‚ classify, summary, export, health β”‚
β”‚ agent/ orchestrator (tool-calling loop) + prompts β”‚
β”‚ llm/ provider abstraction: Gemini(default)⇄OpenAI β”‚
β”‚ services/ ingestion(Docling) Β· extraction Β· classificationβ”‚
β”‚ Β· summary Β· qa(RAG) Β· anomaly Β· export Β· β”‚
β”‚ vectorstore Β· storage β”‚
β”‚ schemas/ Pydantic models (incl. invoice/contract) β”‚
β”‚ core/ config Β· logging Β· deps β”‚
β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚ β”‚
β”Œβ”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Docling β”‚ β”‚ Storage β”‚
β”‚ (local β”‚ β”‚ β€’ files (disk/S3) β”‚
β”‚ extract) β”‚ β”‚ β€’ SQLite/Postgres β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β€’ vectors (chroma/β”‚
β”‚ pgvector) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```
## The 7 core functions β†’ implementation
| Function | How | Tool exposed to agent |
|---|---|---|
| 1. Upload & ingest | `POST /documents` β†’ Docling parse β†’ DoclingDocument JSON + page images | `ingest_document` |
| 2. Parse & extract structured data | Docling structure + LLM structured-output against Pydantic schema (fields, tables, KV, entities) + confidence | `extract_fields` |
| 3. Classify | LLM zero-shot classification β†’ type + confidence | `classify_document` |
| 4. Summarize | Map-reduce summarization over chunks | `summarize_document` |
| 5. Conversational Q&A | Agentic RAG: retrieve chunks β†’ answer **with citations** (page + bbox) | `query_document` |
| 6. Flag anomalies | Rule + LLM checks: missing required fields, inconsistencies, low-confidence | `flag_anomalies` |
| 7. Export | Serialize extracted data β†’ JSON / CSV / Excel | `export_data` |
## Agent design
Single **orchestrator agent** with the tools above (tool-calling loop), agentic-RAG retrieval, structured outputs (Pydantic), human-in-the-loop on low-confidence fields. Pattern mirrors LlamaIndex ADW: *parse β†’ maintain state β†’ retrieve β†’ reason β†’ surface for validation*.
## LLM strategy
- **Default (free):** Gemini Flash (1M context, native vision for scans).
- **Fallback (switchable):** GPT-4o-mini.
- `llm/base.py` defines a `LLMProvider` interface; runtime switch via config/env or per-request header. Cheap model for classify, stronger for reasoning.
## Tech choices (pragmatic defaults for a runnable, impressive build)
- **Backend:** FastAPI, Pydantic v2, Docling, `google-generativeai`, `openai`, ChromaDB (embedded vector store β€” no external service), SQLite (dev) with a path to Postgres/pgvector.
- **Frontend:** Next.js (App Router) + React + TypeScript + Tailwind + a PDF/image viewer with overlay layer for bounding boxes; SSE for streaming chat.
- **Local-first:** runs with only a free Gemini API key. No paid services required.
## Separation of concerns
Routes are thin β†’ call services. Agent orchestrates services as tools. LLM access only via `llm/`. Storage only via `services/storage` + `services/vectorstore`. Schemas shared. This is the Dify-grade discipline we borrowed.