# imamh0ssain/paralegal architecture

> Architecture diagram of the GitHub repository imamh0ssain/paralegal, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-27). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/imamh0ssain/paralegal
- Repository: https://github.com/imamh0ssain/paralegal

## Overview

1. Paralegal is a document-grounded memo pipeline, not a generic web app. The core flow is: ingest legal/regulatory documents, normalize them into evidence blocks, index those blocks for hybrid retrieval, generate a cited memo from retrieved evidence, then validate citations and evaluate retrieval quality.

2. `app.py` is the Streamlit presentation layer. It sits on top of the same backend modules as the CLI and is used for document preparation, memo generation, evidence inspection, feedback capture, and evaluation. The UI is a consumer of pipeline artifacts rather than the system of record.

3. `paralegal/cli.py` is the orchestration boundary. The CLI exposes stage-by-stage commands such as ingest, index, draft, evaluate, download-real, and make-samples, plus the end-to-end `all` workflow. This makes the repository deployable in both fully local and API-assisted modes.

4. `paralegal/ingestion.py` is the first major processing subsystem. It handles PDFs, text, markdown, and image files, performs native PDF text extraction before OCR, optionally invokes OCR/layout parsing, and emits normalized evidence records with stable source IDs like `DOC2:p6:b1`. It also extracts structured fields such as parties, dates, addresses, amounts, signatures, deadlines, and unclear spans.

5. The ingestion output becomes the durable intermediate data layer under `data/processed/`. The README shows two main artifacts: `processed_documents.jsonl` for page/block-level evidence and `document_summaries.json` for document-level summaries. These artifacts are the handoff between extraction and retrieval/generation.

6. `paralegal/retrieval.py` is the search subsystem. It combines SQLite FTS5 keyword search, vector embeddings, reciprocal-rank fusion, and optional reranking. The resulting index is stored separately under `evidence_index/`, which is the retrieval boundary used by drafting and evaluation.

7. `paralegal/generation.py` consumes retrieved evidence plus learned operator feedback patterns to produce a memo draft with citations. The system is explicitly grounded: memo claims should map back to evidence blocks, and unsupported claims are rejected through citation validation rather than being silently emitted.

8. `paralegal/feedback.py` implements the operator-edit learning loop. It captures before/after edits, stores reusable patterns, and feeds those patterns back into future drafting. This is a distinct subsystem from generation; it models user preference and style changes, not retrieval facts.

9. `paralegal/evaluation.py` measures the system end-to-end. It reports retrieval metrics such as term recall@5, source recall@5, and MRR, plus extraction counts, warnings, citation validity, unsupported factual lines, and edit-learning persistence. Evaluation outputs are written to `sample_outputs/` as both Markdown and JSON reports.

10. `paralegal/providers.py` and `paralegal/local_device.py` define the execution backends. Providers can route OCR, embeddings, reranking, and drafting to optional external APIs like OpenAI and Mistral, or to local components such as Docling, Sentence Transformers, BGE reranker, and Ollama. `local_device.py` controls CPU/CUDA selection so the local stack can run safely on mixed hardware.

11. `paralegal/models.py`, `io_utils.py`, `text_utils.py`, and `real_data.py` are supporting layers. They define shared data structures, file I/O helpers, text normalization, and public-document acquisition, keeping the major pipeline stages decoupled from parsing and filesystem details.

12. The repository has two operating modes with the same architecture: privacy-preserving local mode and optional API-assisted mode. In local mode, documents, embeddings, reranking, and drafting stay on the machine; in API mode, selected steps can leave the machine when configured. The architecture is therefore a modular RAG pipeline with clear boundaries between ingestion, indexing, retrieval, generation, feedback, and evaluation.

13. `tests/` verifies core behavior and local device selection, which is important because the pipeline’s correctness depends on consistent extraction, indexing, and backend routing. The sample artifacts under `sample_outputs/` act as reference outputs for the full workflow and are useful when drawing the “inputs → processed evidence → index → memo/report” diagram.

Main entry points: [`paralegal/retrieval.py`](https://github.com/imamh0ssain/paralegal/blob/master/paralegal/retrieval.py) (Retrieval), [`paralegal/generation.py`](https://github.com/imamh0ssain/paralegal/blob/master/paralegal/generation.py) (Memo Drafting), [`paralegal/cli.py`](https://github.com/imamh0ssain/paralegal/blob/master/paralegal/cli.py) (CLI), [`paralegal/ingestion.py`](https://github.com/imamh0ssain/paralegal/blob/master/paralegal/ingestion.py) (Ingestion)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_group_interface["Interfaces"]
  node_app_py["Streamlit UI<br/>presentation layer<br/>[app.py]"]
  node_cli_py["CLI<br/>orchestrator<br/>[cli.py]"]
end

subgraph group_group_pipeline["Pipeline"]
  node_ingestion["Ingestion<br/>extract/normalize<br/>[ingestion.py]"]
  node_retrieval["Retrieval<br/>hybrid search<br/>[retrieval.py]"]
  node_generation["Memo Drafting<br/>grounded generation<br/>[generation.py]"]
  node_feedback["Feedback Loop<br/>edit learning<br/>[feedback.py]"]
  node_evaluation["Evaluation<br/>metrics/reporting<br/>[evaluation.py]"]
end

subgraph group_group_data["Data Artifacts"]
  node_processed_docs["Processed Docs<br/>evidence corpus<br/>[evidence_map.json]"]
  node_evidence_index[("Evidence Index<br/>search index")]
  node_sample_reports["Sample Outputs<br/>reports<br/>[generated_memo.md]"]
end

subgraph group_group_support["Support"]
  node_models["Models<br/>shared schemas<br/>[models.py]"]
  node_io_utils["I/O Utils<br/>file helpers<br/>[io_utils.py]"]
  node_text_utils["Text Utils<br/>normalization<br/>[text_utils.py]"]
  node_real_data["Real Data<br/>acquisition<br/>[real_data.py]"]
  node_providers["Providers<br/>backend routing<br/>[providers.py]"]
  node_local_device["Local Device<br/>hardware selection<br/>[local_device.py]"]
end

node_app_py -->|"uses workflow"| node_cli_py
node_cli_py -->|"ingest"| node_ingestion
node_cli_py -->|"index/search"| node_retrieval
node_cli_py -->|"draft"| node_generation
node_cli_py -->|"evaluate"| node_evaluation
node_ingestion -->|"write evidence"| node_processed_docs
node_processed_docs -->|"seed index"| node_retrieval
node_retrieval -->|"store search"| node_evidence_index
node_retrieval -->|"retrieve evidence"| node_generation
node_feedback -->|"pattern bias"| node_generation
node_generation -->|"emit memo"| node_sample_reports
node_evaluation -->|"emit reports"| node_sample_reports
node_evaluation -->|"measure"| node_retrieval
node_evaluation -->|"validate citations"| node_generation
node_providers -->|"ocr/extract"| node_ingestion
node_providers -->|"embeddings/rerank"| node_retrieval
node_providers -->|"LLM draft"| node_generation
node_local_device -->|"device control"| node_providers
node_models -->|"schemas"| node_ingestion
node_models -->|"schemas"| node_retrieval
node_models -->|"schemas"| node_generation
node_io_utils -->|"file ops"| node_ingestion
node_text_utils -->|"normalize text"| node_ingestion
node_real_data -->|"download-real"| node_cli_py

click node_app_py "https://github.com/imamh0ssain/paralegal/blob/master/app.py"
click node_cli_py "https://github.com/imamh0ssain/paralegal/blob/master/paralegal/cli.py"
click node_ingestion "https://github.com/imamh0ssain/paralegal/blob/master/paralegal/ingestion.py"
click node_retrieval "https://github.com/imamh0ssain/paralegal/blob/master/paralegal/retrieval.py"
click node_generation "https://github.com/imamh0ssain/paralegal/blob/master/paralegal/generation.py"
click node_feedback "https://github.com/imamh0ssain/paralegal/blob/master/paralegal/feedback.py"
click node_evaluation "https://github.com/imamh0ssain/paralegal/blob/master/paralegal/evaluation.py"
click node_processed_docs "https://github.com/imamh0ssain/paralegal/blob/master/sample_outputs/evidence_map.json"
click node_sample_reports "https://github.com/imamh0ssain/paralegal/blob/master/sample_outputs/generated_memo.md"
click node_models "https://github.com/imamh0ssain/paralegal/blob/master/paralegal/models.py"
click node_io_utils "https://github.com/imamh0ssain/paralegal/blob/master/paralegal/io_utils.py"
click node_text_utils "https://github.com/imamh0ssain/paralegal/blob/master/paralegal/text_utils.py"
click node_real_data "https://github.com/imamh0ssain/paralegal/blob/master/paralegal/real_data.py"
click node_providers "https://github.com/imamh0ssain/paralegal/blob/master/paralegal/providers.py"
click node_local_device "https://github.com/imamh0ssain/paralegal/blob/master/paralegal/local_device.py"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_app_py,node_cli_py toneBlue
class node_ingestion,node_retrieval,node_generation,node_feedback,node_evaluation toneAmber
class node_processed_docs,node_evidence_index,node_sample_reports toneMint
class node_models,node_io_utils,node_text_utils,node_real_data,node_providers,node_local_device toneRose
```

## Components

### Interfaces

User-facing entry points and presentation layer

- [Streamlit UI](https://github.com/imamh0ssain/paralegal/blob/master/app.py): presentation layer · Interactive document prep, memo generation, evidence review, feedback, and evaluation UI · `app.py`
- [CLI](https://github.com/imamh0ssain/paralegal/blob/master/paralegal/cli.py): orchestrator · Stage-by-stage command boundary for ingest, index, draft, evaluate, and end-to-end workflows · `paralegal/cli.py`

### Pipeline

Core document-grounded memo workflow

- [Ingestion](https://github.com/imamh0ssain/paralegal/blob/master/paralegal/ingestion.py): extract/normalize · Handles PDFs, text, markdown, and images; extracts native text, OCR/layout when needed, and emits evidence blocks · `paralegal/ingestion.py`
- [Retrieval](https://github.com/imamh0ssain/paralegal/blob/master/paralegal/retrieval.py): hybrid search · Builds hybrid evidence search with FTS5, embeddings, reciprocal-rank fusion, and optional reranking · `paralegal/retrieval.py`
- [Memo Drafting](https://github.com/imamh0ssain/paralegal/blob/master/paralegal/generation.py): grounded generation · Produces cited memo drafts from retrieved evidence and learned feedback patterns · `paralegal/generation.py`
- [Feedback Loop](https://github.com/imamh0ssain/paralegal/blob/master/paralegal/feedback.py): edit learning · Captures before/after edits and reusable operator patterns that influence future drafting · `paralegal/feedback.py`
- [Evaluation](https://github.com/imamh0ssain/paralegal/blob/master/paralegal/evaluation.py): metrics/reporting · Measures retrieval, extraction, citation validity, unsupported claims, and edit-learning persistence · `paralegal/evaluation.py`

### Data Artifacts

Durable intermediate and output files

- [Processed Docs](https://github.com/imamh0ssain/paralegal/blob/master/sample_outputs/evidence_map.json): evidence corpus · Normalized page/block evidence and document summaries under data/processed · `sample_outputs/evidence_map.json`
- **Evidence Index**: search index · Separate retrieval boundary storing hybrid index artifacts
- [Sample Outputs](https://github.com/imamh0ssain/paralegal/blob/master/sample_outputs/generated_memo.md): reports · Reference memo and evaluation artifacts produced by the full workflow · `sample_outputs/generated_memo.md`

### Support

Shared models, utilities, data access, and execution backends

- [Models](https://github.com/imamh0ssain/paralegal/blob/master/paralegal/models.py): shared schemas · Common data structures shared across pipeline stages · `paralegal/models.py`
- [I/O Utils](https://github.com/imamh0ssain/paralegal/blob/master/paralegal/io_utils.py): file helpers · Filesystem and serialization helpers used across the repository · `paralegal/io_utils.py`
- [Text Utils](https://github.com/imamh0ssain/paralegal/blob/master/paralegal/text_utils.py): normalization · Text cleanup and normalization helpers for extraction and retrieval · `paralegal/text_utils.py`
- [Real Data](https://github.com/imamh0ssain/paralegal/blob/master/paralegal/real_data.py): acquisition · Public-document acquisition and download helpers · `paralegal/real_data.py`
- [Providers](https://github.com/imamh0ssain/paralegal/blob/master/paralegal/providers.py): backend routing · Routes OCR, embeddings, reranking, and drafting to local or API-assisted backends · `paralegal/providers.py`
- [Local Device](https://github.com/imamh0ssain/paralegal/blob/master/paralegal/local_device.py): hardware selection · CPU/CUDA selection and local runtime safety for mixed hardware · `paralegal/local_device.py`

## Connections

- Streamlit UI → CLI: uses workflow · UI consumes the same pipeline stages as the command line
- CLI → Ingestion: ingest · CLI triggers document extraction and normalization
- CLI → Retrieval: index/search · CLI builds and queries the evidence index
- CLI → Memo Drafting: draft · CLI runs memo generation from retrieved evidence
- CLI → Evaluation: evaluate · CLI executes end-to-end measurement
- Ingestion → Processed Docs: write evidence · Normalized blocks and summaries are persisted as durable intermediate artifacts
- Processed Docs → Retrieval: seed index · Processed evidence is indexed for hybrid retrieval
- Retrieval → Evidence Index: store search · Hybrid retrieval artifacts live in a separate search index boundary
- Retrieval → Memo Drafting: retrieve evidence · Drafting consumes ranked evidence blocks
- Feedback Loop → Memo Drafting: pattern bias · Learned edit patterns influence future memo drafting
- Memo Drafting → Sample Outputs: emit memo · Drafts and reports are written as sample outputs
- Evaluation → Sample Outputs: emit reports · Markdown and JSON evaluation outputs are saved under sample outputs
- Evaluation → Retrieval: measure · Evaluation checks retrieval quality metrics
- Evaluation → Memo Drafting: validate citations · Evaluation checks citation validity and unsupported claims
- Providers → Ingestion: ocr/extract · Backend routing supports OCR and document processing
- Providers → Retrieval: embeddings/rerank · Backend routing supports vectorization and reranking
- Providers → Memo Drafting: LLM draft · Backend routing can provide API-assisted or local drafting
- Local Device → Providers: device control · Controls local execution placement for CPU/CUDA
- Models → Ingestion: schemas · Shared data structures define extracted evidence records
- Models → Retrieval: schemas · Shared data structures shape indexed evidence and queries
- Models → Memo Drafting: schemas · Shared data structures shape memo and citation objects
- I/O Utils → Ingestion: file ops · Ingestion relies on common serialization and filesystem helpers
- Text Utils → Ingestion: normalize text · Text normalization supports extraction and cleanup
- Real Data → CLI: download-real · CLI can acquire public documents for the workflow
