# rafsun-jany-rafy/rag-doc-assistant architecture

> Architecture diagram of the GitHub repository rafsun-jany-rafy/rag-doc-assistant, 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/rafsun-jany-rafy/rag-doc-assistant
- Repository: https://github.com/rafsun-jany-rafy/rag-doc-assistant

## Overview

1. **What this repository is**
   - This is a **local Retrieval-Augmented Generation (RAG) document assistant** for PDFs.
   - The core architecture is a **single-user Streamlit app** that sends a user question through a local retrieval pipeline and then into a **local LLM served by Ollama**.

2. **Primary runtime entrypoint**
   - `app.py` is the documented UI entrypoint for the Streamlit experience.
   - `main.py` likely provides an alternate launch path or helper entrypoint, but the README positions `app.py` as the main application boundary.

3. **User-facing layer**
   - The only interactive surface is the **Streamlit UI**.
   - It accepts a PDF upload, accepts a natural-language query, and renders the generated answer with **streaming output**.
   - There is no separate web API tier in the current design.

4. **Orchestration boundary**
   - `src/pipeline.py` is the central coordinator.
   - Its role is to connect ingestion, embedding, vector retrieval, prompt/context assembly, and LLM generation into one RAG flow.
   - This is the main “application logic” layer, sitting between UI and model/storage subsystems.

5. **Document ingestion subsystem**
   - `src/ingest.py` handles **PDF text extraction and chunking**.
   - The README indicates **PyMuPDF** is used for parsing PDFs.
   - This stage converts uploaded documents into text chunks suitable for embedding and later retrieval, with chunk overlap used to preserve context.

6. **Embedding subsystem**
   - `src/embeddings.py` converts text chunks into vectors using **sentence-transformers**.
   - This is the semantic representation layer that feeds the vector index.
   - It is local and model-based, so no external embedding API is part of the architecture.

7. **Retrieval and persistence subsystem**
   - `src/retriever.py` owns the **FAISS** vector store logic.
   - It is responsible for adding chunk embeddings, searching for relevant chunks, and persisting the index so documents do not need to be re-indexed on every run.
   - The architecture therefore includes a **local durable retrieval store** on disk, separate from the UI and LLM.

8. **Generation subsystem**
   - `src/llm.py` wraps the **Ollama** connection for the local **Llama 3.2** model.
   - It receives the prompt plus retrieved context and produces the final answer.
   - Responses are streamed back to the UI, so generation is not a single blocking “all at once” step from the user’s perspective.

9. **End-to-end data flow**
   - The runtime path is: **upload PDF → extract/chunk text → embed chunks → store/search FAISS index → retrieve top context → build prompt → call local LLM → stream answer to UI**.
   - The first document query is slower because ingestion and indexing happen before retrieval can reuse the persisted index.

10. **State and storage boundaries**
   - The repo is designed around **local persistence** rather than remote services.
   - The README references project directories for uploaded documents and saved vector indexes, which means the system keeps both raw document inputs and retrieval state on disk.
   - This creates a clear separation between ephemeral request handling and durable document/index storage.

11. **Infrastructure and deployment shape**
   - The presence of `Dockerfile` and `docker-compose.yml` indicates the project is intended to be containerizable, even though the README’s primary workflow is local execution.
   - The Ollama dependency is an important runtime boundary: the app expects a **locally running model server** rather than a cloud API.

12. **Non-production / experimental code**
   - `notebooks/rag_experiment.ipynb` is an R&D workspace for trying retrieval or prompting ideas.
   - It is not part of the primary application path, but it likely informed the chunking, retrieval, or prompting strategy used in `src/`.

13. **How to draw the architecture**
   - The diagram should show three main zones:
     - **UI layer:** Streamlit app
     - **RAG backend layer:** ingestion, embeddings, retriever, pipeline, LLM wrapper
     - **Local persistence/runtime layer:** stored PDFs, FAISS index files, Ollama/Llama 3.2
   - The key external dependency is **Ollama**, and the key storage dependency is **FAISS-backed local index files**.

Main entry points: [`src/pipeline.py`](https://github.com/rafsun-jany-rafy/rag-doc-assistant/blob/main/src/pipeline.py) (RAG Pipeline), [`src/retriever.py`](https://github.com/rafsun-jany-rafy/rag-doc-assistant/blob/main/src/retriever.py) (Retriever), [`src/ingest.py`](https://github.com/rafsun-jany-rafy/rag-doc-assistant/blob/main/src/ingest.py) (PDF Ingest), [`app.py`](https://github.com/rafsun-jany-rafy/rag-doc-assistant/blob/main/app.py) (Streamlit App)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_ui["UI"]
  node_app["Streamlit App<br/>ui entrypoint<br/>[app.py]"]
  node_main["Main Entrypoint<br/>launch helper<br/>[main.py]"]
end

subgraph group_rag["RAG Backend"]
  node_pipeline["RAG Pipeline<br/>orchestrator<br/>[pipeline.py]"]
  node_ingest["PDF Ingest<br/>text extraction<br/>[ingest.py]"]
  node_embed(("Embeddings<br/>vectorizer<br/>[embeddings.py]"))
  node_retrieve[("Retriever<br/>vector store<br/>[retriever.py]")]
  node_llm["LLM Client<br/>generation wrapper<br/>[llm.py]"]
end

subgraph group_runtime["Local Runtime"]
  node_pdfs["Uploaded PDFs<br/>document store"]
  node_chunks["Chunk Store<br/>derived text"]
  node_index[("FAISS Index<br/>durable retrieval store")]
  node_ollama{{"Ollama Server<br/>local model server"}}
end

node_app -->|"query / upload"| node_pipeline
node_main -->|"starts"| node_app
node_pipeline -->|"ingest docs"| node_ingest
node_pipeline -->|"search context"| node_retrieve
node_pipeline -->|"generate answer"| node_llm
node_ingest -->|"read"| node_pdfs
node_ingest -->|"emit chunks"| node_chunks
node_chunks -->|"vectorize"| node_embed
node_embed -->|"store vectors"| node_retrieve
node_retrieve -->|"persist / load"| node_index
node_retrieve -->|"top-k context"| node_pipeline
node_llm -->|"call model"| node_ollama
node_ollama -->|"stream output"| node_app

click node_app "https://github.com/rafsun-jany-rafy/rag-doc-assistant/blob/main/app.py"
click node_main "https://github.com/rafsun-jany-rafy/rag-doc-assistant/blob/main/main.py"
click node_pipeline "https://github.com/rafsun-jany-rafy/rag-doc-assistant/blob/main/src/pipeline.py"
click node_ingest "https://github.com/rafsun-jany-rafy/rag-doc-assistant/blob/main/src/ingest.py"
click node_embed "https://github.com/rafsun-jany-rafy/rag-doc-assistant/blob/main/src/embeddings.py"
click node_retrieve "https://github.com/rafsun-jany-rafy/rag-doc-assistant/blob/main/src/retriever.py"
click node_llm "https://github.com/rafsun-jany-rafy/rag-doc-assistant/blob/main/src/llm.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,node_main toneBlue
class node_pipeline,node_ingest,node_embed,node_retrieve,node_llm toneAmber
class node_pdfs,node_chunks,node_index,node_ollama toneMint
```

## Components

### UI

Streamlit user interface and launch entrypoints

- [Streamlit App](https://github.com/rafsun-jany-rafy/rag-doc-assistant/blob/main/app.py): ui entrypoint · Primary user-facing Streamlit experience for upload, query, and streaming answers · `app.py`
- [Main Entrypoint](https://github.com/rafsun-jany-rafy/rag-doc-assistant/blob/main/main.py): launch helper · Alternate application launch path or wrapper around the main app · `main.py`

### RAG Backend

Document ingestion, retrieval, and answer generation

- [RAG Pipeline](https://github.com/rafsun-jany-rafy/rag-doc-assistant/blob/main/src/pipeline.py): orchestrator · Coordinates ingestion, retrieval, prompt assembly, and generation · `src/pipeline.py`
- [PDF Ingest](https://github.com/rafsun-jany-rafy/rag-doc-assistant/blob/main/src/ingest.py): text extraction · Extracts PDF text and chunks it for downstream embedding · `src/ingest.py`
- [Embeddings](https://github.com/rafsun-jany-rafy/rag-doc-assistant/blob/main/src/embeddings.py): vectorizer · Converts text chunks into local semantic vectors · `src/embeddings.py`
- [Retriever](https://github.com/rafsun-jany-rafy/rag-doc-assistant/blob/main/src/retriever.py): vector store · Adds vectors, searches relevant chunks, and manages FAISS-backed retrieval · `src/retriever.py`
- [LLM Client](https://github.com/rafsun-jany-rafy/rag-doc-assistant/blob/main/src/llm.py): generation wrapper · Builds prompts with context and streams answers from the local model · `src/llm.py`

### Local Runtime

On-disk persistence and local model server

- **Uploaded PDFs**: document store · Locally stored source PDFs used for ingestion and reuse
- **Chunk Store**: derived text · Intermediate text chunks produced from PDF parsing
- **FAISS Index**: durable retrieval store · Persistent local vector index used for reuse across runs
- **Ollama Server**: local model server · Local runtime serving the Llama 3.2 model for answer generation

## Connections

- Streamlit App → RAG Pipeline: query / upload · User actions enter the orchestration layer
- Main Entrypoint → Streamlit App: starts · Alternate entrypoint launches the Streamlit app
- RAG Pipeline → PDF Ingest: ingest docs · Routes uploaded PDFs into parsing and chunking
- RAG Pipeline → Retriever: search context · Requests relevant chunks for a question
- RAG Pipeline → LLM Client: generate answer · Sends prompt and retrieved context to the model wrapper
- PDF Ingest → Uploaded PDFs: read · Consumes stored or uploaded PDF sources
- PDF Ingest → Chunk Store: emit chunks · Produces chunked text for embedding
- Chunk Store → Embeddings: vectorize · Chunk text is converted into embeddings
- Embeddings → Retriever: store vectors · Embeddings are indexed for later lookup
- Retriever → FAISS Index: persist / load · Uses the local FAISS index across runs
- Retriever → RAG Pipeline: top-k context · Returns the most relevant retrieved passages
- LLM Client → Ollama Server: call model · Delegates generation to the local Ollama service
- Ollama Server → Streamlit App: stream output · Generated tokens flow back to the UI for streaming display
