# vaishnavsreekumar/factline architecture

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

- Interactive diagram: https://gitdiagram.com/vaishnavsreekumar/factline
- Repository: https://github.com/vaishnavsreekumar/factline

## Overview

FACTLINE is an evidence-first cross-document fact analysis application. Users upload financial or economic PDFs; the API parses pages, selects relevant context, extracts candidate claims, verifies page-level evidence, normalizes facts, evaluates candidate pairs through comparability before classifying relationships, and persists results for retrieval in the UI. The README documents the domain stages; sampled source confirms the parser, API routes, database behavior, and selected context logic. Some service orchestration and extraction internals were not sampled, so their detailed call wiring is represented only where documented.

Main entry points: [`backend/services/analysis.py`](https://github.com/vaishnavsreekumar/factline/blob/main/backend/services/analysis.py) (Analysis Service), [`backend/api/routes.py`](https://github.com/vaishnavsreekumar/factline/blob/main/backend/api/routes.py) (API Routes), [`frontend/src/App.jsx`](https://github.com/vaishnavsreekumar/factline/blob/main/frontend/src/App.jsx) (FACTLINE App), [`backend/extraction/pdf_parser.py`](https://github.com/vaishnavsreekumar/factline/blob/main/backend/extraction/pdf_parser.py) (Page PDF Parser)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_interface["User Interface"]
  node_webapp["FACTLINE App<br/>[App.jsx]"]
  node_uploader["Document Uploader"]
  node_analysisprogress["Analysis Progress"]
  node_resultsviews["Results Views"]
end

subgraph group_api["API &amp; Orchestration"]
  node_apiapp["FastAPI App<br/>[main.py]"]
  node_routes["API Routes<br/>[routes.py]"]
  node_analysisservice["Analysis Service<br/>[analysis.py]"]
end

subgraph group_ingest["Document &amp; Extraction"]
  node_parser["Page PDF Parser<br/>[pdf_parser.py]"]
  node_pagefilter["Page Relevance Filter<br/>[relevance.py]"]
  node_context["Context Selection<br/>[selector.py]"]
  node_expander["Context Expansion"]
  node_quota["Quota Planner<br/>[planner.py]"]
  node_extractor["Fact Extraction<br/>[fact_extractor.py]"]
  node_evidence["Evidence Verification<br/>[evidence.py]"]
end

subgraph group_reasoning["Fact Reasoning"]
  node_normalizer["Fact Normalization<br/>[normalizer.py]"]
  node_matcher["Candidate Matching<br/>[matcher.py]"]
  node_comparability["Comparability Gate<br/>[comparability.py]"]
  node_surfacing["Relationship Surfacing<br/>[surfacing.py]"]
  node_relationshipengine["Relationship Engine<br/>[relationships.py]"]
  node_models["Fact &amp; Document Models<br/>[fact.py]"]
end

subgraph group_persistence["Persistence"]
  node_sqlite[("SQLite Store<br/>[database.py]")]
end

node_user(("Analyst"))
node_pdf["Source PDFs"]
node_gemini{{"Gemini Model"}}

node_user -->|"uses"| node_webapp
node_webapp -->|"renders"| node_uploader
node_webapp -->|"shows progress"| node_analysisprogress
node_webapp -->|"renders results"| node_resultsviews
node_uploader -->|"submits PDFs"| node_webapp
node_webapp -->|"uploads analysis"| node_routes
node_webapp -->|"retrieves analysis"| node_routes
node_apiapp -->|"mounts routes"| node_routes
node_routes -->|"runs analysis"| node_analysisservice
node_routes -->|"parses uploads"| node_parser
node_routes -->|"matches pair"| node_matcher
node_routes -->|"gates pair"| node_comparability
node_routes -->|"evaluates pair"| node_relationshipengine
node_routes -->|"loads analysis"| node_analysisservice
node_analysisservice -->|"parses PDFs"| node_parser
node_analysisservice -->|"filters pages"| node_pagefilter
node_analysisservice -->|"selects context"| node_context
node_context -->|"expands regions"| node_expander
node_analysisservice -->|"plans extraction"| node_quota
node_analysisservice -->|"extracts facts"| node_extractor
node_extractor -.->|"requests candidates"| node_gemini
node_extractor -->|"verifies claims"| node_evidence
node_analysisservice -->|"normalizes facts"| node_normalizer
node_analysisservice -->|"pairs facts"| node_matcher
node_analysisservice -->|"checks comparability"| node_comparability
node_analysisservice -->|"filters relationships"| node_surfacing
node_analysisservice -->|"classifies pairs"| node_relationshipengine
node_analysisservice -->|"persists results"| node_sqlite
node_routes -->|"retrieves records"| node_sqlite
node_pdf -->|"provides bytes"| node_parser
node_parser -->|"returns page records"| node_analysisservice
node_webapp -->|"displays analysis"| node_resultsviews
node_evidence -->|"grounds facts"| node_models
node_normalizer -->|"produces normalized facts"| node_models
node_sqlite -->|"returns analysis data"| node_webapp

click node_webapp "https://github.com/vaishnavsreekumar/factline/blob/main/frontend/src/App.jsx"
click node_uploader "https://github.com/vaishnavsreekumar/factline/blob/main/frontend/src/components/DocumentUploader.jsx"
click node_analysisprogress "https://github.com/vaishnavsreekumar/factline/blob/main/frontend/src/components/AnalysisProgress.jsx"
click node_resultsviews "https://github.com/vaishnavsreekumar/factline/blob/main/frontend/src/components/RelationshipsView.jsx"
click node_apiapp "https://github.com/vaishnavsreekumar/factline/blob/main/backend/main.py"
click node_routes "https://github.com/vaishnavsreekumar/factline/blob/main/backend/api/routes.py"
click node_analysisservice "https://github.com/vaishnavsreekumar/factline/blob/main/backend/services/analysis.py"
click node_parser "https://github.com/vaishnavsreekumar/factline/blob/main/backend/extraction/pdf_parser.py"
click node_pagefilter "https://github.com/vaishnavsreekumar/factline/blob/main/backend/page_filter/relevance.py"
click node_context "https://github.com/vaishnavsreekumar/factline/blob/main/backend/context_selector/selector.py"
click node_expander "https://github.com/vaishnavsreekumar/factline/blob/main/backend/context_selector/context_expander.py"
click node_quota "https://github.com/vaishnavsreekumar/factline/blob/main/backend/quota_experiment/planner.py"
click node_extractor "https://github.com/vaishnavsreekumar/factline/blob/main/backend/extraction/fact_extractor.py"
click node_evidence "https://github.com/vaishnavsreekumar/factline/blob/main/backend/extraction/evidence.py"
click node_normalizer "https://github.com/vaishnavsreekumar/factline/blob/main/backend/normalization/normalizer.py"
click node_matcher "https://github.com/vaishnavsreekumar/factline/blob/main/backend/reasoning/matcher.py"
click node_comparability "https://github.com/vaishnavsreekumar/factline/blob/main/backend/reasoning/comparability.py"
click node_surfacing "https://github.com/vaishnavsreekumar/factline/blob/main/backend/reasoning/surfacing.py"
click node_relationshipengine "https://github.com/vaishnavsreekumar/factline/blob/main/backend/reasoning/relationships.py"
click node_sqlite "https://github.com/vaishnavsreekumar/factline/blob/main/backend/db/database.py"
click node_models "https://github.com/vaishnavsreekumar/factline/blob/main/backend/models/fact.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_webapp,node_uploader,node_analysisprogress,node_resultsviews toneBlue
class node_apiapp,node_routes,node_analysisservice toneAmber
class node_parser,node_pagefilter,node_context,node_expander,node_quota,node_extractor,node_evidence toneMint
class node_normalizer,node_matcher,node_comparability,node_surfacing,node_relationshipengine,node_models toneRose
class node_sqlite,node_user,node_pdf,node_gemini toneIndigo
```

## Components

### User Interface

- [FACTLINE App](https://github.com/vaishnavsreekumar/factline/blob/main/frontend/src/App.jsx): `frontend/src/App.jsx`
- [Document Uploader](https://github.com/vaishnavsreekumar/factline/blob/main/frontend/src/components/DocumentUploader.jsx): `frontend/src/components/DocumentUploader.jsx`
- [Analysis Progress](https://github.com/vaishnavsreekumar/factline/blob/main/frontend/src/components/AnalysisProgress.jsx): `frontend/src/components/AnalysisProgress.jsx`
- [Results Views](https://github.com/vaishnavsreekumar/factline/blob/main/frontend/src/components/RelationshipsView.jsx): `frontend/src/components/RelationshipsView.jsx`

### API & Orchestration

- [FastAPI App](https://github.com/vaishnavsreekumar/factline/blob/main/backend/main.py): `backend/main.py`
- [API Routes](https://github.com/vaishnavsreekumar/factline/blob/main/backend/api/routes.py): `backend/api/routes.py`
- [Analysis Service](https://github.com/vaishnavsreekumar/factline/blob/main/backend/services/analysis.py): `backend/services/analysis.py`

### Document & Extraction

- [Page PDF Parser](https://github.com/vaishnavsreekumar/factline/blob/main/backend/extraction/pdf_parser.py): `backend/extraction/pdf_parser.py`
- [Page Relevance Filter](https://github.com/vaishnavsreekumar/factline/blob/main/backend/page_filter/relevance.py): `backend/page_filter/relevance.py`
- [Context Selection](https://github.com/vaishnavsreekumar/factline/blob/main/backend/context_selector/selector.py): `backend/context_selector/selector.py`
- [Context Expansion](https://github.com/vaishnavsreekumar/factline/blob/main/backend/context_selector/context_expander.py): `backend/context_selector/context_expander.py`
- [Quota Planner](https://github.com/vaishnavsreekumar/factline/blob/main/backend/quota_experiment/planner.py): `backend/quota_experiment/planner.py`
- [Fact Extraction](https://github.com/vaishnavsreekumar/factline/blob/main/backend/extraction/fact_extractor.py): `backend/extraction/fact_extractor.py`
- [Evidence Verification](https://github.com/vaishnavsreekumar/factline/blob/main/backend/extraction/evidence.py): `backend/extraction/evidence.py`

### Fact Reasoning

- [Fact Normalization](https://github.com/vaishnavsreekumar/factline/blob/main/backend/normalization/normalizer.py): `backend/normalization/normalizer.py`
- [Candidate Matching](https://github.com/vaishnavsreekumar/factline/blob/main/backend/reasoning/matcher.py): `backend/reasoning/matcher.py`
- [Comparability Gate](https://github.com/vaishnavsreekumar/factline/blob/main/backend/reasoning/comparability.py): `backend/reasoning/comparability.py`
- [Relationship Surfacing](https://github.com/vaishnavsreekumar/factline/blob/main/backend/reasoning/surfacing.py): `backend/reasoning/surfacing.py`
- [Relationship Engine](https://github.com/vaishnavsreekumar/factline/blob/main/backend/reasoning/relationships.py): `backend/reasoning/relationships.py`
- [Fact & Document Models](https://github.com/vaishnavsreekumar/factline/blob/main/backend/models/fact.py): `backend/models/fact.py`

### Persistence

- [SQLite Store](https://github.com/vaishnavsreekumar/factline/blob/main/backend/db/database.py): `backend/db/database.py`

### Other components

- **Analyst**
- **Source PDFs**
- **Gemini Model**

## Connections

- Analyst → FACTLINE App: uses
- FACTLINE App → Document Uploader: renders
- FACTLINE App → Analysis Progress: shows progress
- FACTLINE App → Results Views: renders results
- Document Uploader → FACTLINE App: submits PDFs
- FACTLINE App → API Routes: uploads analysis
- FACTLINE App → API Routes: retrieves analysis
- FastAPI App → API Routes: mounts routes
- API Routes → Analysis Service: runs analysis
- API Routes → Page PDF Parser: parses uploads
- API Routes → Candidate Matching: matches pair
- API Routes → Comparability Gate: gates pair
- API Routes → Relationship Engine: evaluates pair
- API Routes → Analysis Service: loads analysis
- Analysis Service → Page PDF Parser: parses PDFs
- Analysis Service → Page Relevance Filter: filters pages
- Analysis Service → Context Selection: selects context
- Context Selection → Context Expansion: expands regions
- Analysis Service → Quota Planner: plans extraction
- Analysis Service → Fact Extraction: extracts facts
- Fact Extraction → Gemini Model: requests candidates
- Fact Extraction → Evidence Verification: verifies claims
- Analysis Service → Fact Normalization: normalizes facts
- Analysis Service → Candidate Matching: pairs facts
- Analysis Service → Comparability Gate: checks comparability
- Analysis Service → Relationship Surfacing: filters relationships
- Analysis Service → Relationship Engine: classifies pairs
- Analysis Service → SQLite Store: persists results
- API Routes → SQLite Store: retrieves records
- Source PDFs → Page PDF Parser: provides bytes
- Page PDF Parser → Analysis Service: returns page records
- FACTLINE App → Results Views: displays analysis
- Evidence Verification → Fact & Document Models: grounds facts
- Fact Normalization → Fact & Document Models: produces normalized facts
- SQLite Store → FACTLINE App: returns analysis data
