# kishoraditya/wexa_demo architecture

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

- Interactive diagram: https://gitdiagram.com/kishoraditya/wexa_demo
- Repository: https://github.com/kishoraditya/wexa_demo

## Overview

1. This is a FastAPI-based RAG backend for AWS Well-Architected Framework Q&A, with a small Streamlit frontend and separate evaluation/fine-tuning assets. The repo is organized around two main flows: offline ingestion of PDFs into a local vector index, and online question answering over that index.

2. The backend entrypoint is `backend/main.py`, which wires app startup/lifespan, middleware, and route registration. Configuration is centralized in `backend/core/config.py` and driven by `config.yaml` plus `.env` values, so most tunable behavior is externalized rather than hardcoded.

3. The online API surface is split into three route groups in `backend/routes/`: `generate.py` for `/generate`, `ingest.py` for `/ingest` and `/ingest/upload`, and `health.py` for liveness/readiness endpoints. This separation reflects the system boundary between request-time inference and document/index lifecycle management.

4. The ingestion subsystem lives in `backend/services/ingestion.py`. It loads the source PDFs, chunks text, normalizes metadata such as pillar/page/source, and deduplicates chunks before indexing. The README indicates this is an offline or manual-trigger pipeline, not an always-on crawler.

5. The retrieval layer is implemented in `backend/services/vector_store.py`. It uses local embeddings plus a FAISS index persisted on disk, with a metadata sidecar for source attribution. The architecture relies on local, file-backed storage rather than an external managed vector database, which keeps deployment self-contained but limits horizontal sharing of the index.

6. The generation pipeline is orchestrated in `backend/services/rag_pipeline.py`. It combines retrieval, reranking, prompt assembly, model routing, and post-generation checks into one request path. The prompt templates themselves are versioned in `backend/services/prompts.py`, which helps keep answer style and refusal behavior consistent.

7. Model selection is handled by `backend/services/llm_manager.py`. The primary path is a fine-tuned Phi-3-mini adapter, with transparent fallback to OpenAI GPT-4o-mini when the local model or adapter is unavailable. That router is a key architectural boundary because it turns model availability into a runtime concern rather than a deployment blocker.

8. Safety and answer quality are enforced in `backend/services/guardrails.py`. The system applies input checks before retrieval/generation and output grounding/PII-style checks after generation, with refusal behavior when retrieval confidence is too low or the question is out of scope. This is central to the repo’s “no hallucination” contract.

9. Cross-cutting runtime concerns are in `backend/core/`: `cache.py` provides a two-level cache for embeddings and responses, `logging.py` sets up structured loguru logging, `metrics.py` exposes Prometheus counters/histograms, and `dependencies.py` provides FastAPI dependency wiring. These modules make observability and performance part of the core architecture rather than an afterthought.

10. The data model boundary is in `backend/models/schemas.py`, which defines the request/response payloads for generation, ingestion, and health endpoints. This is where validation constraints such as query length, `top_k`, and pillar filtering are enforced at the API edge.

11. The frontend in `frontend/app.py` is a thin Streamlit client over the backend API. It is not the system of record; its role is to provide a user-facing chat/query surface and render sources, confidence, and latency returned by the API.

12. Testing is concentrated under `backend/tests/` and is organized by subsystem: ingestion, vector store, RAG pipeline, observability, and API integration. That test layout mirrors the runtime boundaries and suggests the architecture was designed to be validated end-to-end as well as at the service level.

13. The `eval/` directory is a separate quality-assurance lane, not part of the serving path. It contains a gold dataset, a RAGAS evaluation runner, and latency benchmarking scripts, which means the repository distinguishes production request handling from offline scoring and regression measurement.

14. The `notebooks/fine_tuning_phi3_qlora.ipynb` notebook documents the adapter-training workflow used to produce the local generation model. It is operationally separate from serving: the app can run with the adapter if available, but the fine-tuning process itself is outside the backend runtime.

15. Deployment is currently “local first” in code, but `Dockerfile` and `docs/deployment_plan.md` describe a production split between stateless API routing and heavier inference workers, with shared cache/storage services in the target cloud design. That means the repo contains both the current monolithic implementation and a forward-looking production topology.

Main entry points: [`backend/services/rag_pipeline.py`](https://github.com/kishoraditya/wexa_demo/blob/main/backend/services/rag_pipeline.py) (RAG pipeline), [`backend/main.py`](https://github.com/kishoraditya/wexa_demo/blob/main/backend/main.py) (App entry), [`backend/routes/generate.py`](https://github.com/kishoraditya/wexa_demo/blob/main/backend/routes/generate.py) (Generate API), [`backend/routes/ingest.py`](https://github.com/kishoraditya/wexa_demo/blob/main/backend/routes/ingest.py) (Ingest API)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_backend["Backend"]
  node_backend_main["App entry<br/>FastAPI startup<br/>[main.py]"]
  node_backend_config["Config<br/>settings<br/>[config.py]"]
  node_backend_dependencies["Dependencies<br/>DI wiring<br/>[dependencies.py]"]
  node_backend_cache[("Cache<br/>[cache.py]")]
  node_backend_logging["Logging<br/>observability<br/>[logging.py]"]
  node_backend_metrics["Metrics<br/>prometheus<br/>[metrics.py]"]
  node_backend_models["Schemas<br/>API models<br/>[schemas.py]"]
  node_route_generate["Generate API<br/>route<br/>[generate.py]"]
  node_route_ingest["Ingest API<br/>route<br/>[ingest.py]"]
  node_route_health["Health API<br/>route<br/>[health.py]"]
  node_svc_ingestion["Ingestion<br/>document pipeline<br/>[ingestion.py]"]
  node_svc_vector[("Vector store<br/>faiss index<br/>[vector_store.py]")]
  node_svc_rag["RAG pipeline<br/>orchestration<br/>[rag_pipeline.py]"]
  node_svc_prompts["Prompts<br/>templates<br/>[prompts.py]"]
  node_svc_llm["LLM router<br/>model routing<br/>[llm_manager.py]"]
  node_svc_guardrails["Guardrails<br/>safety checks<br/>[guardrails.py]"]
end

subgraph group_client["Client"]
  node_frontend_app["Streamlit app<br/>ui client<br/>[app.py]"]
end

subgraph group_offline["Offline workflows"]
  node_eval_suite["Eval suite<br/>offline QA<br/>[run_ragas.py]"]
  node_fine_tune["Fine-tuning<br/>notebook"]
end

subgraph group_docs["Docs"]
  node_arch_docs["Architecture docs<br/>design notes<br/>[architecture.mmd]"]
end

node_backend_main -->|"loads"| node_backend_config
node_backend_main -->|"wires"| node_backend_dependencies
node_backend_main -->|"mounts"| node_route_generate
node_backend_main -->|"mounts"| node_route_ingest
node_backend_main -->|"mounts"| node_route_health
node_route_generate -->|"validates"| node_backend_models
node_route_ingest -->|"validates"| node_backend_models
node_route_generate -->|"calls"| node_svc_rag
node_route_ingest -->|"calls"| node_svc_ingestion
node_route_health -->|"reports"| node_backend_metrics
node_svc_ingestion -->|"indexes"| node_svc_vector
node_svc_rag -->|"retrieves"| node_svc_vector
node_svc_rag -->|"assembles"| node_svc_prompts
node_svc_rag -->|"generates"| node_svc_llm
node_svc_rag -->|"checks"| node_svc_guardrails
node_svc_rag -->|"uses"| node_backend_cache
node_svc_vector -->|"shares"| node_backend_cache
node_svc_llm -->|"reads"| node_backend_config
node_svc_guardrails -->|"reads"| node_backend_config
node_frontend_app -->|"queries"| node_route_generate
node_frontend_app -->|"uploads"| node_route_ingest
node_frontend_app -->|"checks"| node_route_health
node_eval_suite -->|"benchmarks"| node_svc_rag
node_fine_tune -.->|"produces"| node_svc_llm
node_arch_docs -.->|"describes"| node_backend_main

click node_backend_main "https://github.com/kishoraditya/wexa_demo/blob/main/backend/main.py"
click node_backend_config "https://github.com/kishoraditya/wexa_demo/blob/main/backend/core/config.py"
click node_backend_dependencies "https://github.com/kishoraditya/wexa_demo/blob/main/backend/core/dependencies.py"
click node_backend_cache "https://github.com/kishoraditya/wexa_demo/blob/main/backend/core/cache.py"
click node_backend_logging "https://github.com/kishoraditya/wexa_demo/blob/main/backend/core/logging.py"
click node_backend_metrics "https://github.com/kishoraditya/wexa_demo/blob/main/backend/core/metrics.py"
click node_backend_models "https://github.com/kishoraditya/wexa_demo/blob/main/backend/models/schemas.py"
click node_route_generate "https://github.com/kishoraditya/wexa_demo/blob/main/backend/routes/generate.py"
click node_route_ingest "https://github.com/kishoraditya/wexa_demo/blob/main/backend/routes/ingest.py"
click node_route_health "https://github.com/kishoraditya/wexa_demo/blob/main/backend/routes/health.py"
click node_svc_ingestion "https://github.com/kishoraditya/wexa_demo/blob/main/backend/services/ingestion.py"
click node_svc_vector "https://github.com/kishoraditya/wexa_demo/blob/main/backend/services/vector_store.py"
click node_svc_rag "https://github.com/kishoraditya/wexa_demo/blob/main/backend/services/rag_pipeline.py"
click node_svc_prompts "https://github.com/kishoraditya/wexa_demo/blob/main/backend/services/prompts.py"
click node_svc_llm "https://github.com/kishoraditya/wexa_demo/blob/main/backend/services/llm_manager.py"
click node_svc_guardrails "https://github.com/kishoraditya/wexa_demo/blob/main/backend/services/guardrails.py"
click node_frontend_app "https://github.com/kishoraditya/wexa_demo/blob/main/frontend/app.py"
click node_eval_suite "https://github.com/kishoraditya/wexa_demo/blob/main/eval/run_ragas.py"
click node_fine_tune "https://github.com/kishoraditya/wexa_demo/blob/main/notebooks/fine_tuning_phi3_qlora.ipynb"
click node_arch_docs "https://github.com/kishoraditya/wexa_demo/blob/main/docs/architecture.mmd"

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_backend_main,node_backend_config,node_backend_dependencies,node_backend_cache,node_backend_logging,node_backend_metrics,node_backend_models,node_route_generate,node_route_ingest,node_route_health,node_svc_ingestion,node_svc_vector,node_svc_rag,node_svc_prompts,node_svc_llm,node_svc_guardrails toneBlue
class node_frontend_app toneAmber
class node_eval_suite,node_fine_tune toneMint
class node_arch_docs toneRose
```

## Components

### Backend

FastAPI app, services, and API contracts

- [App entry](https://github.com/kishoraditya/wexa_demo/blob/main/backend/main.py): FastAPI startup · Wires lifespan, middleware, and route registration. · `backend/main.py`
- [Config](https://github.com/kishoraditya/wexa_demo/blob/main/backend/core/config.py): settings · Loads YAML and env-driven runtime configuration. · `backend/core/config.py`
- [Dependencies](https://github.com/kishoraditya/wexa_demo/blob/main/backend/core/dependencies.py): DI wiring · FastAPI dependency injection and shared service wiring. · `backend/core/dependencies.py`
- [Cache](https://github.com/kishoraditya/wexa_demo/blob/main/backend/core/cache.py): runtime cache · Caches embeddings and responses. · `backend/core/cache.py`
- [Logging](https://github.com/kishoraditya/wexa_demo/blob/main/backend/core/logging.py): observability · Structured application logging setup. · `backend/core/logging.py`
- [Metrics](https://github.com/kishoraditya/wexa_demo/blob/main/backend/core/metrics.py): prometheus · Counters and histograms for runtime observability. · `backend/core/metrics.py`
- [Schemas](https://github.com/kishoraditya/wexa_demo/blob/main/backend/models/schemas.py): API models · Request and response validation for API endpoints. · `backend/models/schemas.py`
- [Generate API](https://github.com/kishoraditya/wexa_demo/blob/main/backend/routes/generate.py): route · Question answering endpoint group. · `backend/routes/generate.py`
- [Ingest API](https://github.com/kishoraditya/wexa_demo/blob/main/backend/routes/ingest.py): route · Document ingestion and upload endpoints. · `backend/routes/ingest.py`
- [Health API](https://github.com/kishoraditya/wexa_demo/blob/main/backend/routes/health.py): route · Liveness and readiness endpoints. · `backend/routes/health.py`
- [Ingestion](https://github.com/kishoraditya/wexa_demo/blob/main/backend/services/ingestion.py): document pipeline · Loads PDFs, chunks text, normalizes metadata, and deduplicates. · `backend/services/ingestion.py`
- [Vector store](https://github.com/kishoraditya/wexa_demo/blob/main/backend/services/vector_store.py): faiss index · Local embeddings, FAISS retrieval, and persisted metadata. · `backend/services/vector_store.py`
- [RAG pipeline](https://github.com/kishoraditya/wexa_demo/blob/main/backend/services/rag_pipeline.py): orchestration · Retrieval, reranking, prompt assembly, generation, and checks. · `backend/services/rag_pipeline.py`
- [Prompts](https://github.com/kishoraditya/wexa_demo/blob/main/backend/services/prompts.py): templates · Versioned prompt templates and response style rules. · `backend/services/prompts.py`
- [LLM router](https://github.com/kishoraditya/wexa_demo/blob/main/backend/services/llm_manager.py): model routing · Selects local Phi-3 adapter or OpenAI fallback. · `backend/services/llm_manager.py`
- [Guardrails](https://github.com/kishoraditya/wexa_demo/blob/main/backend/services/guardrails.py): safety checks · Input, grounding, refusal, and output quality checks. · `backend/services/guardrails.py`

### Client

Thin UI and user-facing entrypoint

- [Streamlit app](https://github.com/kishoraditya/wexa_demo/blob/main/frontend/app.py): ui client · Thin chat/query interface over the backend API. · `frontend/app.py`

### Offline workflows

Evaluation and fine-tuning assets outside serving path

- [Eval suite](https://github.com/kishoraditya/wexa_demo/blob/main/eval/run_ragas.py): offline QA · Gold data, RAGAS scoring, and latency benchmarks. · `eval/run_ragas.py`
- [Fine-tuning](https://github.com/kishoraditya/wexa_demo/blob/main/notebooks/fine_tuning_phi3_qlora.ipynb): notebook · Phi-3 QLoRA training workflow for the local adapter. · `notebooks/fine_tuning_phi3_qlora.ipynb`

### Docs

Architecture and deployment references

- [Architecture docs](https://github.com/kishoraditya/wexa_demo/blob/main/docs/architecture.mmd): design notes · System diagrams, deployment plan, and tradeoff discussion. · `docs/architecture.mmd`

## Connections

- App entry → Config: loads · Startup reads centralized configuration.
- App entry → Dependencies: wires · App startup registers shared dependencies.
- App entry → Generate API: mounts · Registers generation routes.
- App entry → Ingest API: mounts · Registers ingestion routes.
- App entry → Health API: mounts · Registers health routes.
- Generate API → Schemas: validates · Uses schemas for request and response payloads.
- Ingest API → Schemas: validates · Uses schemas for ingestion payloads.
- Generate API → RAG pipeline: calls · Generation requests enter the RAG pipeline.
- Ingest API → Ingestion: calls · Ingestion endpoints trigger document processing.
- Health API → Metrics: reports · Health endpoints expose runtime status.
- Ingestion → Vector store: indexes · Processed chunks are stored in the local vector index.
- RAG pipeline → Vector store: retrieves · RAG fetches relevant context from FAISS.
- RAG pipeline → Prompts: assembles · Prompt templates shape answer construction.
- RAG pipeline → LLM router: generates · Model router produces the answer.
- RAG pipeline → Guardrails: checks · Applies pre- and post-generation safety checks.
- RAG pipeline → Cache: uses · Caches embeddings and responses.
- Vector store → Cache: shares · Vector operations benefit from shared caching.
- LLM router → Config: reads · Model selection and fallbacks are config-driven.
- Guardrails → Config: reads · Safety thresholds and policies come from config.
- Streamlit app → Generate API: queries · UI sends user questions to the backend.
- Streamlit app → Ingest API: uploads · UI can trigger ingestion/upload flows.
- Streamlit app → Health API: checks · UI or operator can probe service health.
- Eval suite → RAG pipeline: benchmarks · Offline evaluation measures retrieval and answer quality.
- Fine-tuning → LLM router: produces · Training workflow yields the local adapter used by the model router.
- Architecture docs → App entry: describes · Docs capture the current service architecture.
