# nicolasarmientor/tf-rag architecture

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

- Interactive diagram: https://gitdiagram.com/nicolasarmientor/tf-rag
- Repository: https://github.com/nicolasarmientor/tf-rag

## Overview

#### Purpose and entry points
TensorFlow-RAG is a compact retrieval-augmented Q&A system over TensorFlow Guide documentation. Its two operational entry points are the FastAPI server, `src/api/main.py`, and offline vector-store construction via `python -m src.retrieval.vector_store` in `src/retrieval/vector_store.py`. Evaluation runs separately through `src/eval/evaluate.py`.

#### Offline ingestion and indexing
The build pipeline loads Markdown and notebook source files from the externally supplied TensorFlow docs tree, extracts content, and creates source-attributed chunks. `src/ingest/loader.py` owns document loading; `src/ingest/chunker.py` performs token-aware chunking with overlap and preserves fenced code blocks intact. The resulting chunks and metadata are embedded and persisted by `src/retrieval/vector_store.py`.

#### Retrieval boundary
ChromaDB is both the persistent vector store and embedding provider, using its bundled ONNX Runtime `all-MiniLM-L6-v2` model rather than a direct Torch/sentence-transformers runtime. Query retrieval is isolated in `src/retrieval/retriever.py`, which requests top-k candidates but applies a distance threshold. This is the key grounding boundary: irrelevant questions yield no usable context rather than unrelated nearest neighbors.

#### Generation and safety
`src/generation/generator.py` converts retrieved chunks into a constrained Claude prompt, calls Anthropic, and returns answers with source information. The generator is expected to refuse when retrieval produces no qualifying context. Because model output is rendered in the browser, generated HTML is sanitized before presentation. Anthropic Claude is also used as an external evaluation judge.

#### API and BYOK UI
`src/api/main.py` composes retrieval and generation behind two interfaces: JSON `POST /ask`, using server-side `ANTHROPIC_API_KEY`, and form-oriented `POST /ask-ui`, which renders an HTMX HTML fragment. Request/response contracts reside in `src/api/schemas.py`. The browser UI is server-rendered from `src/api/templates/index.html` and `src/api/templates/answer.html`; for the UI route, a visitor-provided API key is kept client-side/session-scoped rather than persisted by the application.

#### Evaluation loop
`src/eval/testset.py` defines a hand-authored set of answerable and negative questions. `src/eval/evaluate.py` exercises both stages: whether retrieval finds the expected source and whether a second Claude call judges the answer against a reference summary. This makes refusal behavior a first-class quality criterion, not merely prompt guidance.

#### Deployment and runtime
The Python application runs under FastAPI/Uvicorn. `Dockerfile` fetches TensorFlow documentation and builds `chroma_data/` during image build, producing a runtime container with no source-data volume requirement. It preserves the Chroma/ONNX cache under `/app`, then runs non-root. The intended hosting target is Render; runtime port selection honors its `PORT` environment variable. CI is defined in `.github/workflows/ci.yml`.

Main entry points: [`src/api/main.py`](https://github.com/nicolasarmientor/tf-rag/blob/main/src/api/main.py) (FastAPI application), [`src/eval/evaluate.py`](https://github.com/nicolasarmientor/tf-rag/blob/main/src/eval/evaluate.py) (Evaluation runner), [`src/retrieval/retriever.py`](https://github.com/nicolasarmientor/tf-rag/blob/main/src/retrieval/retriever.py) (Threshold retriever), [`src/generation/generator.py`](https://github.com/nicolasarmientor/tf-rag/blob/main/src/generation/generator.py) (Grounded generator)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_ingestion["Offline indexing"]
  node_docs["TensorFlow docs tree<br/>external source"]
  node_loader["Document loader<br/>ingestion<br/>[loader.py]"]
  node_chunker["Token-aware chunker<br/>ingestion<br/>[chunker.py]"]
  node_vector_store["Vector-store builder<br/>indexing<br/>[vector_store.py]"]
  node_chroma[("ChromaDB + ONNX embeddings<br/>vector database")]
  node_docker["Image build<br/>container build"]
end

subgraph group_serving["Serving"]
  node_api["FastAPI application<br/>API server<br/>[main.py]"]
  node_schemas["API contracts<br/>schemas<br/>[schemas.py]"]
  node_retriever["Threshold retriever<br/>retrieval<br/>[retriever.py]"]
  node_generator["Grounded generator<br/>generation<br/>[generator.py]"]
  node_anthropic{{"Anthropic Claude<br/>external LLM"}}
  node_browser["Browser + HTMX<br/>web client"]
  node_templates["Server-rendered templates<br/>HTML templates<br/>[index.html]"]
end

subgraph group_evaluation["Evaluation"]
  node_testset["Evaluation test set<br/>test data<br/>[testset.py]"]
  node_evaluation_runner["Evaluation runner<br/>[evaluate.py]"]
  node_ci["CI workflow<br/>[ci.yml]"]
end

node_docs -->|"loads"| node_loader
node_loader -->|"documents"| node_chunker
node_chunker -->|"chunks + metadata"| node_vector_store
node_vector_store -->|"embeds and persists"| node_chroma
node_docker -->|"fetches"| node_docs
node_docker -->|"builds index"| node_vector_store
node_browser -->|"POST /ask-ui"| node_api
node_api -->|"uses"| node_schemas
node_api -->|"renders"| node_templates
node_api -->|"asks"| node_retriever
node_retriever -->|"top-k query"| node_chroma
node_retriever -->|"qualified context"| node_generator
node_api -->|"JSON /ask or UI"| node_generator
node_generator -->|"constrained prompt"| node_anthropic
node_testset -->|"questions and references"| node_evaluation_runner
node_evaluation_runner -.->|"tests source retrieval"| node_retriever
node_evaluation_runner -.->|"tests answers"| node_generator
node_evaluation_runner -->|"judges answers"| node_anthropic
node_ci -->|"runs"| node_evaluation_runner

click node_loader "https://github.com/nicolasarmientor/tf-rag/blob/main/src/ingest/loader.py"
click node_chunker "https://github.com/nicolasarmientor/tf-rag/blob/main/src/ingest/chunker.py"
click node_vector_store "https://github.com/nicolasarmientor/tf-rag/blob/main/src/retrieval/vector_store.py"
click node_docker "https://github.com/nicolasarmientor/tf-rag/blob/main/Dockerfile"
click node_api "https://github.com/nicolasarmientor/tf-rag/blob/main/src/api/main.py"
click node_schemas "https://github.com/nicolasarmientor/tf-rag/blob/main/src/api/schemas.py"
click node_retriever "https://github.com/nicolasarmientor/tf-rag/blob/main/src/retrieval/retriever.py"
click node_generator "https://github.com/nicolasarmientor/tf-rag/blob/main/src/generation/generator.py"
click node_templates "https://github.com/nicolasarmientor/tf-rag/blob/main/src/api/templates/index.html"
click node_testset "https://github.com/nicolasarmientor/tf-rag/blob/main/src/eval/testset.py"
click node_evaluation_runner "https://github.com/nicolasarmientor/tf-rag/blob/main/src/eval/evaluate.py"
click node_ci "https://github.com/nicolasarmientor/tf-rag/blob/main/.github/workflows/ci.yml"

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_docs,node_loader,node_chunker,node_vector_store,node_chroma,node_docker toneBlue
class node_api,node_schemas,node_retriever,node_generator,node_anthropic,node_browser,node_templates toneAmber
class node_testset,node_evaluation_runner,node_ci toneMint
```

## Components

### Offline indexing

- **TensorFlow docs tree**: external source · Markdown and notebooks supplied during image build.
- [Document loader](https://github.com/nicolasarmientor/tf-rag/blob/main/src/ingest/loader.py): ingestion · `src/ingest/loader.py`
- [Token-aware chunker](https://github.com/nicolasarmientor/tf-rag/blob/main/src/ingest/chunker.py): ingestion · Preserves fenced code and source attribution. · `src/ingest/chunker.py`
- [Vector-store builder](https://github.com/nicolasarmientor/tf-rag/blob/main/src/retrieval/vector_store.py): indexing · Embeds chunks and persists the Chroma collection. · `src/retrieval/vector_store.py`
- **ChromaDB + ONNX embeddings**: vector database · Persistent store using bundled all-MiniLM-L6-v2 embeddings.
- [Image build](https://github.com/nicolasarmientor/tf-rag/blob/main/Dockerfile): container build · Fetches docs and builds chroma_data before runtime. · `Dockerfile`

### Serving

- [FastAPI application](https://github.com/nicolasarmientor/tf-rag/blob/main/src/api/main.py): API server · Provides JSON and HTMX question-answering routes. · `src/api/main.py`
- [API contracts](https://github.com/nicolasarmientor/tf-rag/blob/main/src/api/schemas.py): schemas · `src/api/schemas.py`
- [Threshold retriever](https://github.com/nicolasarmientor/tf-rag/blob/main/src/retrieval/retriever.py): retrieval · Rejects top-k candidates beyond the distance threshold. · `src/retrieval/retriever.py`
- [Grounded generator](https://github.com/nicolasarmientor/tf-rag/blob/main/src/generation/generator.py): generation · Refuses without qualifying context and returns sources. · `src/generation/generator.py`
- **Anthropic Claude**: external LLM
- **Browser + HTMX**: web client · Supplies a session-scoped BYOK key for the UI route.
- [Server-rendered templates](https://github.com/nicolasarmientor/tf-rag/blob/main/src/api/templates/index.html): HTML templates · `src/api/templates/index.html`

### Evaluation

- [Evaluation test set](https://github.com/nicolasarmientor/tf-rag/blob/main/src/eval/testset.py): test data · Includes answerable and negative questions. · `src/eval/testset.py`
- [Evaluation runner](https://github.com/nicolasarmientor/tf-rag/blob/main/src/eval/evaluate.py): evaluation · Checks retrieval sources and Claude-judged answers. · `src/eval/evaluate.py`
- [CI workflow](https://github.com/nicolasarmientor/tf-rag/blob/main/.github/workflows/ci.yml): CI · `.github/workflows/ci.yml`

## Connections

- TensorFlow docs tree → Document loader: loads
- Document loader → Token-aware chunker: documents
- Token-aware chunker → Vector-store builder: chunks + metadata
- Vector-store builder → ChromaDB + ONNX embeddings: embeds and persists
- Image build → TensorFlow docs tree: fetches
- Image build → Vector-store builder: builds index
- Browser + HTMX → FastAPI application: POST /ask-ui
- FastAPI application → API contracts: uses
- FastAPI application → Server-rendered templates: renders
- FastAPI application → Threshold retriever: asks
- Threshold retriever → ChromaDB + ONNX embeddings: top-k query
- Threshold retriever → Grounded generator: qualified context
- FastAPI application → Grounded generator: JSON /ask or UI
- Grounded generator → Anthropic Claude: constrained prompt
- Evaluation test set → Evaluation runner: questions and references
- Evaluation runner → Threshold retriever: tests source retrieval
- Evaluation runner → Grounded generator: tests answers
- Evaluation runner → Anthropic Claude: judges answers
- CI workflow → Evaluation runner: runs
