How kabitacodeforge/adaptive-rag-agent works
1. Two-user-facing entry points
- The repository is split into a FastAPI backend under src/ and a Streamlit frontend under streamlit_app/.
- Streamlit is the human interface for login/chat/document upload, while FastAPI exposes the actual RAG and upload endpoints that the UI calls through streamlit_app/utils/api_client.py.
2. Backend application boundary
- src/main.py is the backend startup point and wires the API routes from src/api/routes.py.
- This is the main service boundary: requests enter through HTTP, then move into the RAG pipeline, persistence layers, or LLM integrations depending on the route.
3. Core request paths
- The backend exposes two primary flows:
- POST /rag/query for conversational question answering
- POST /rag/documents/upload for ingesting PDFs/TXTs into the retrieval index
- Query traffic and document ingestion are separate pipelines, but they share configuration, logging, and storage backends.
4. Adaptive RAG orchestration
- The central intelligence is in src/rag/graph_builder.py and src/rag/nodes.py, which define a LangGraph-driven state machine.
- The graph coordinates query analysis, routing, retrieval, grading, rewriting, answer generation, and fallback paths.
- This is the key architectural boundary between “request handling” and “agentic reasoning.”
5. Routing logic and execution modes
- Queries are classified into three paths: index, general, or search.
- src/models/route_identifier.py and the prompt definitions in src/config/prompts.yaml support this decisioning.
- The index path uses document retrieval, general uses direct LLM answering, and search invokes external web search through the agent/tool layer.
6. Retrieval and vector storage
- Document-based answering depends on src/rag/retriever_setup.py and src/rag/document_upload.py.
- Uploaded documents are chunked, embedded, and stored in Qdrant as the vector database.
- This retrieval subsystem is isolated from the chat logic so documents can be indexed independently of active conversations.
7. LLM and agent layer
- src/llms/openai.py is the provider integration layer for OpenAI models.
- src/rag/reAct_agent.py and the tool modules in src/tools/ implement the agentic behavior, including ReAct-style tool use and helper functions for graph decisions.
- The LLM layer is therefore not called directly by the UI; it is mediated by the graph and tool abstractions.
8. Conversation memory and session state
- Chat history is modeled as persistent session state, not just ephemeral prompts.
- src/memory/chat_history_mongo.py stores conversation history in MongoDB for persistence, while src/memory/chathistory_in_memory.py provides a fallback in-memory implementation.
- This memory layer is the boundary between per-request processing and longer-lived conversational context.
9. Data models and state contracts
- src/models/ contains the shared schemas that keep backend components aligned:
- query_request.py for incoming query payloads
- state.py for graph state
- grade.py and verification_result.py for retrieval/answer evaluation
- These models define the data contracts passed between API, graph nodes, memory, and generation steps.
10. Infrastructure and external dependencies
- The system depends on:
- OpenAI for generation
- Qdrant for vector search
- MongoDB for session/chat persistence
- Tavily for live web search
- src/config/settings.py, src/core/config.py, and src/db/mongo_client.py centralize environment-driven setup, while src/core/logger.py handles observability.
11. Frontend-to-backend flow
- The Streamlit app is a thin presentation layer: it collects user input, uploads files, and forwards requests to the backend API.
- The backend returns structured responses, which Streamlit renders in the chat interface.
- This keeps the UI stateless relative to the RAG pipeline; the session continuity lives in MongoDB-backed memory.
12. Repository organization as architecture
- src/api = HTTP boundary
- src/rag = orchestration and retrieval logic
- src/llms = model provider integration
- src/memory = conversation persistence
- src/db = database clients
- src/models = shared schemas/state
- streamlit_app = user interface
- The architecture is therefore a modular, backend-first RAG system with a separate frontend client and explicit storage/service boundaries.
Main entry points: routes.py API routes · nodes.py RAG nodes · graph_builder.py Graph builder · reAct_agent.py ReAct agent
Components 20
Streamlit UI
Human-facing interface for chat, login, and document upload.
- Home UI · Streamlit landing and app shell.
streamlit_app/home.py - Chat page · Chat and upload user workflow.
streamlit_app/pages/chat.py - API client · Frontend bridge to backend endpoints.
streamlit_app/utils/api_client.py
FastAPI backend
HTTP service boundary for query handling and document ingestion.
- App start · Backend startup and application wiring.
src/main.py - API routes · RAG and upload HTTP endpoints.
src/api/routes.py
RAG engine
Adaptive orchestration, retrieval, and agent execution.
- Graph builder · Builds the adaptive reasoning state machine.
src/rag/graph_builder.py - RAG nodes · Query analysis, routing, retrieval, grading, rewrite, and answer steps.
src/rag/nodes.py - Doc upload · Chunking, embedding, and indexing for uploaded files.
src/rag/document_upload.py - Retriever · Document retrieval wiring for indexed knowledge.
src/rag/retriever_setup.py - ReAct agent · Agentic search and tool-using execution.
src/rag/reAct_agent.py - Tools · Shared helper and graph tool functions.
src/tools/common_tools.py
State and storage
Shared schemas plus persistence and external data services.
- Route ID · Classifies requests into index, general, or search paths.
src/models/route_identifier.py - Prompts · Prompt templates and routing instructions.
src/config/prompts.yaml - OpenAI · Model integration for generation and reasoning.
src/llms/openai.py - Chat memory · MongoDB-backed conversation history.
src/memory/chat_history_mongo.py - Mongo client · MongoDB connection setup.
src/db/mongo_client.py - State models · Request, graph state, grading, and verification contracts.
src/models/state.py - Settings · Environment-driven application configuration.
src/config/settings.py - Qdrant · Vector store for indexed documents.
- Tavily · External search service used by search flows.
Connections 22
- Home UI → API client: uses · UI triggers backend requests through the client.
- Chat page → API client: calls · Chat and upload actions are forwarded to the API.
- API client → API routes: HTTP · Frontend communicates with backend endpoints.
- App start → API routes: mounts · Application startup wires route handlers.
- API routes → Graph builder: query path · Query requests enter the adaptive RAG graph.
- API routes → Doc upload: upload path · Document ingestion requests enter the indexing pipeline.
- Graph builder → RAG nodes: assembles · Graph builder composes the execution nodes.
- RAG nodes → Route ID: routes · Classifies requests into execution modes.
- RAG nodes → Prompts: guides · Prompt templates shape analysis and generation.
- RAG nodes → Retriever: retrieves · Index-path nodes query the retrieval layer.
- RAG nodes → ReAct agent: delegates · Search-path nodes hand off to the agent layer.
- RAG nodes → OpenAI: generates · LLM-backed answer generation and rewriting.
- ReAct agent → Tools: uses · Agent relies on tool helpers and graph utilities.
- ReAct agent → Tavily: searches · Web search is performed through the external search service.
- Doc upload → Qdrant: indexes · Embedded chunks are stored in the vector database.
- Retriever → Qdrant: reads · Retrieval queries the vector store.
- API routes → Chat memory: loads · Conversation context is fetched and updated per request.
- Chat memory → Mongo client: persists · MongoDB-backed memory uses the database client.
- API routes → State models: validates · API payloads and graph state are shaped by shared schemas.
- Graph builder → State models: shares · Graph execution depends on common state contracts.
- App start → Settings: configures · Startup uses environment-driven settings.
- API routes → Settings: reads · Routes use shared runtime configuration.