# vivektiwari-s/doqa architecture

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

- Interactive diagram: https://gitdiagram.com/vivektiwari-s/doqa
- Repository: https://github.com/vivektiwari-s/doqa

## Overview

DoQA is a conversational PDF question-answering app. A user uploads a PDF in Streamlit; the API parses pages, chunks text, embeds it, and stores vectors in Pinecone. The user then asks a question; the API embeds it, retrieves relevant chunks, builds grounded context, and requests an answer from Gemma through OpenRouter, returning the answer and source chunks to the chat UI. The README documents citations and multi-document support as roadmap items; they are not represented as implemented features here.

Main entry points: [`app/api/routes.py`](https://github.com/vivektiwari-s/doqa/blob/main/app/api/routes.py) (Question endpoint), [`app/core/ingestion.py`](https://github.com/vivektiwari-s/doqa/blob/main/app/core/ingestion.py) (Embed and upsert), [`app/core/retrieval.py`](https://github.com/vivektiwari-s/doqa/blob/main/app/core/retrieval.py) (Chunk retrieval), [`ui/streamlit_app.py`](https://github.com/vivektiwari-s/doqa/blob/main/ui/streamlit_app.py) (Streamlit chat)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_frontend["Chat interface"]
  node_ui["Streamlit chat<br/>[streamlit_app.py]"]
end

subgraph group_api["API layer"]
  node_app["FastAPI app<br/>[main.py]"]
  node_routes["Upload and query routes<br/>[routes.py]"]
  node_schemas["Request and response models<br/>[schemas.py]"]
  node_upload["PDF upload handling<br/>[routes.py]"]
  node_query_route["Question endpoint<br/>[routes.py]"]
end

subgraph group_ingestion["Document ingestion"]
  node_parse["PDF page parsing<br/>[ingestion.py]"]
  node_chunk["Page text chunking<br/>[ingestion.py]"]
  node_embed_store["Embed and upsert<br/>[ingestion.py]"]
  node_index_setup["Index setup<br/>[ingestion.py]"]
end

subgraph group_qa["Question answering"]
  node_retrieve["Chunk retrieval<br/>[retrieval.py]"]
  node_prompt["Grounded prompt<br/>[retrieval.py]"]
  node_generate["Answer generation<br/>[retrieval.py]"]
end

node_user(("Document user"))
node_pinecone[("Pinecone vector index")]
node_embedding_model["HuggingFace embeddings"]
node_openrouter["OpenRouter Gemma"]

node_user -->|"uploads or asks"| node_ui
node_ui -->|"HTTP requests"| node_app
node_app -->|"mounts router"| node_routes
node_routes -->|"handles upload"| node_upload
node_routes -->|"handles query"| node_query_route
node_upload -->|"returns upload model"| node_schemas
node_query_route -->|"validates and returns"| node_schemas
node_upload -->|"calls ingestion"| node_parse
node_parse -->|"passes pages"| node_chunk
node_chunk -->|"passes chunks"| node_embed_store
node_embed_store -->|"embeds documents"| node_embedding_model
node_embed_store -->|"gets index"| node_index_setup
node_index_setup -->|"creates or opens index"| node_pinecone
node_embed_store -->|"upserts vectors"| node_pinecone
node_query_route -->|"calls answer generation"| node_retrieve
node_retrieve -->|"embeds question"| node_embedding_model
node_retrieve -->|"searches vectors"| node_pinecone
node_retrieve -->|"passes matching chunks"| node_prompt
node_prompt -->|"provides context"| node_generate
node_generate -->|"requests completion"| node_openrouter
node_generate -->|"returns answer and sources"| node_query_route
node_query_route -->|"returns response"| node_ui
node_ui -->|"shows answer and sources"| node_user

click node_ui "https://github.com/vivektiwari-s/doqa/blob/main/ui/streamlit_app.py"
click node_app "https://github.com/vivektiwari-s/doqa/blob/main/main.py"
click node_routes "https://github.com/vivektiwari-s/doqa/blob/main/app/api/routes.py"
click node_schemas "https://github.com/vivektiwari-s/doqa/blob/main/app/models/schemas.py"
click node_upload "https://github.com/vivektiwari-s/doqa/blob/main/app/api/routes.py"
click node_parse "https://github.com/vivektiwari-s/doqa/blob/main/app/core/ingestion.py"
click node_chunk "https://github.com/vivektiwari-s/doqa/blob/main/app/core/ingestion.py"
click node_embed_store "https://github.com/vivektiwari-s/doqa/blob/main/app/core/ingestion.py"
click node_index_setup "https://github.com/vivektiwari-s/doqa/blob/main/app/core/ingestion.py"
click node_query_route "https://github.com/vivektiwari-s/doqa/blob/main/app/api/routes.py"
click node_retrieve "https://github.com/vivektiwari-s/doqa/blob/main/app/core/retrieval.py"
click node_prompt "https://github.com/vivektiwari-s/doqa/blob/main/app/core/retrieval.py"
click node_generate "https://github.com/vivektiwari-s/doqa/blob/main/app/core/retrieval.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_ui,node_user toneBlue
class node_app,node_routes,node_schemas,node_upload,node_query_route,node_pinecone toneAmber
class node_parse,node_chunk,node_embed_store,node_index_setup,node_openrouter toneMint
class node_retrieve,node_prompt,node_generate toneRose
class node_embedding_model toneIndigo
```

## Components

### Chat interface

- [Streamlit chat](https://github.com/vivektiwari-s/doqa/blob/main/ui/streamlit_app.py): `ui/streamlit_app.py`

### API layer

- [FastAPI app](https://github.com/vivektiwari-s/doqa/blob/main/main.py): `main.py`
- [Upload and query routes](https://github.com/vivektiwari-s/doqa/blob/main/app/api/routes.py): `app/api/routes.py`
- [Request and response models](https://github.com/vivektiwari-s/doqa/blob/main/app/models/schemas.py): `app/models/schemas.py`
- [PDF upload handling](https://github.com/vivektiwari-s/doqa/blob/main/app/api/routes.py): `app/api/routes.py`
- [Question endpoint](https://github.com/vivektiwari-s/doqa/blob/main/app/api/routes.py): `app/api/routes.py`

### Document ingestion

- [PDF page parsing](https://github.com/vivektiwari-s/doqa/blob/main/app/core/ingestion.py): `app/core/ingestion.py`
- [Page text chunking](https://github.com/vivektiwari-s/doqa/blob/main/app/core/ingestion.py): `app/core/ingestion.py`
- [Embed and upsert](https://github.com/vivektiwari-s/doqa/blob/main/app/core/ingestion.py): `app/core/ingestion.py`
- [Index setup](https://github.com/vivektiwari-s/doqa/blob/main/app/core/ingestion.py): `app/core/ingestion.py`

### Question answering

- [Chunk retrieval](https://github.com/vivektiwari-s/doqa/blob/main/app/core/retrieval.py): `app/core/retrieval.py`
- [Grounded prompt](https://github.com/vivektiwari-s/doqa/blob/main/app/core/retrieval.py): `app/core/retrieval.py`
- [Answer generation](https://github.com/vivektiwari-s/doqa/blob/main/app/core/retrieval.py): `app/core/retrieval.py`

### Other components

- **Document user**
- **Pinecone vector index**
- **HuggingFace embeddings**
- **OpenRouter Gemma**

## Connections

- Document user → Streamlit chat: uploads or asks
- Streamlit chat → FastAPI app: HTTP requests
- FastAPI app → Upload and query routes: mounts router
- Upload and query routes → PDF upload handling: handles upload
- Upload and query routes → Question endpoint: handles query
- PDF upload handling → Request and response models: returns upload model
- Question endpoint → Request and response models: validates and returns
- PDF upload handling → PDF page parsing: calls ingestion
- PDF page parsing → Page text chunking: passes pages
- Page text chunking → Embed and upsert: passes chunks
- Embed and upsert → HuggingFace embeddings: embeds documents
- Embed and upsert → Index setup: gets index
- Index setup → Pinecone vector index: creates or opens index
- Embed and upsert → Pinecone vector index: upserts vectors
- Question endpoint → Chunk retrieval: calls answer generation
- Chunk retrieval → HuggingFace embeddings: embeds question
- Chunk retrieval → Pinecone vector index: searches vectors
- Chunk retrieval → Grounded prompt: passes matching chunks
- Grounded prompt → Answer generation: provides context
- Answer generation → OpenRouter Gemma: requests completion
- Answer generation → Question endpoint: returns answer and sources
- Question endpoint → Streamlit chat: returns response
- Streamlit chat → Document user: shows answer and sources
