Controllable-RAG-Agent: A Deterministic Graph Over Your Own PDFs
This repository provides an advanced Retrieval-Augmented Generation (RAG) solution for complex question answering. It uses sophisticated graph based algorithm to handle the tasks.
At a glance
- What is it?
- NirDiamant/Controllable-RAG-Agent is a Jupyter Notebook walkthrough of a graph-based RAG agent built on LangChain and LangGraph, aimed at multi-step questions that plain vector similarity retrieval handles badly. The core idea is a fixed graph acting as the agent's planner, with a Ragas evaluation step at the end.
- Who is it for?
- Adopt it if you have a bounded document set, mostly PDFs, and questions that need several retrieval hops rather than one similarity lookup, and you are willing to read and adapt notebook code. Do not adopt it if you need a pip-installable library with a stable API, a non-PDF ingestion path, or a hosted service.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly Jupyter Notebook, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The question type that breaks naive RAG
Single-shot semantic retrieval works when the answer sits in one chunk. It fails when the answer requires assembling facts from several places, or when the correct next lookup depends on what the previous one returned. The README frames the project against exactly that gap: it is "designed to tackle complex questions that simple semantic similarity-based retrieval cannot solve." The stated audience is anyone pointing an agent at their own data and expecting non-trivial answers, which in practice means engineers building internal question-answering over document sets they control. The repository is a Jupyter Notebook project, not a library, so the realistic user is someone who reads the code, runs the cells, and edits them. The README's Key Features list names the intended properties directly: a deterministic graph as the agent's brain, multi-step reasoning that breaks queries into sub-tasks, adaptive planning that updates the plan as information arrives, and a hallucination-prevention claim that answers stay grounded in the provided data. Those are claims from the project description, not results I can verify from the material.
The graph is the planner, not the model
The distinguishing design choice is that control flow lives in a graph rather than in the model's free-form reasoning. The README describes a "sophisticated deterministic graph acting as the 'brain' of a highly controllable autonomous agent." Deterministic here means the set of transitions is defined by the graph, so the agent's path through the task is constrained rather than invented at each turn. The README's How It Works section lists the pipeline in order: load PDF documents and split them into chapters; clean and preprocess the text for summarization and encoding; generate extensive summaries of each chapter with large language models; build a separate database for questions that need book quotes; and encode both the book content and the chapter summaries into vector stores. Two retrieval surfaces come out of that, one over raw content and one over summaries, plus a quote-oriented store. The README also states that the plan is continuously updated based on new information, which is the adaptive part layered on top of the fixed graph. The repository ships a schema image at graphs/final_graph_schema.jpeg and a demo GIF at graphs/demo.gif, so the intended reading order is diagram first, then code.
Ingestion assumes a book-shaped PDF
Step one is not generic document loading. The README says to load PDF documents and split them into chapters, and the summarization step is described as producing extensive summaries of each chapter. That is a strong structural assumption: the pipeline expects a document with chapter boundaries, which fits a book, a long report, or a manual, and fits poorly a folder of short memos, tickets, or web pages. The README does not describe a fallback chunking strategy for documents without chapters, and it does not describe ingestion from HTML, Markdown, or a database. If your corpus is not chaptered PDFs, you are rewriting the ingestion cells before anything else in the notebook is useful. The text preprocessing step is also described only at the level of cleaning and preparing text "for better summarization and encoding," so the specific cleaning rules are in the notebook code rather than in the documentation. That is the first place to look when adapting it, because cleaning decisions change what the summarizer sees.
Running it: notebooks, keys, and the Ragas step
The material does not include a requirements file, an environment file, or a setup command, so I cannot give you a verified install line. What the README and repository metadata do establish: the primary language is Jupyter Notebook, the stack is Python with LangChain and LangGraph, and the topics list includes openai, so an OpenAI API key is the expected credential. The practical path is to clone the repository, open the notebooks in Jupyter or a compatible environment, install the imports the first cells reference, set your API key in the environment, and point the ingestion cells at your own PDF. The one named evaluation component is Ragas: the README lists "Performance Evaluation" as a key feature and says it "utilizes Ragas metrics for comprehensive quality assessment." That matters more than it looks, because a graph-based agent can reach a plausible answer through a wrong path, and Ragas metrics give you a way to score the answer rather than eyeball it. The README does not specify which Ragas metrics are used or what dataset they run against, so that is a cell to read before you trust the score.
The notebook format is the real adoption cost
There are no retrieved releases for this repository, so there is no versioned artifact to pin. The unit of distribution is the notebook on the main branch, and the last push date is recent, which means the code moves. LangChain and LangGraph both change their APIs on a short cycle, and a notebook that imports either will break when those packages move, with no changelog to tell you which cell broke. There is also no packaged interface: no importable module, no CLI, no server. You either run the notebook interactively or you extract the graph into your own project and maintain it there. For a one-off analysis that is fine. For a service that other people call, the extraction work is the project, and the notebook is the reference. The README's own framing supports that reading: it points to a separate repository, Agents Towards Production, for "horizontal, code-first tutorials" covering the production lifecycle, which implies this repository is not that.
What the deterministic graph trades away
A fixed graph buys controllability and costs generality. If a question needs a retrieval pattern the graph does not contain, the agent cannot improvise its way there; the failure is structural, not a prompting problem you can fix with a better system message. The README's hallucination-prevention claim is likewise a property of the design, since answers are constrained to the ingested data, but constrained retrieval over a bad summary is still a bad answer. Summarization is the weak point in that chain: if the chapter summary drops a detail, every plan that routes through the summary store misses it, and the raw-content store may never be consulted. The README does not describe how the agent decides between the summary store, the content store, and the quote database, so that routing logic is another thing you have to read in the code and test against your own questions. Anyone expecting the graph to be correct out of the box for arbitrary corpora will be disappointed.
Where a plain LangChain retriever is the better choice
The honest alternative is a standard LangChain retrieval chain: embed the documents, put them in a vector store, retrieve the top-k chunks for the question, and pass them to the model. That approach has one retrieval step and no planner, and for a large share of real questions it is enough. It is also far cheaper to run, since it makes one model call instead of a sequence of planning and retrieval calls, and it is trivial to deploy because there is no graph state to manage. The difference in approach is where the reasoning lives. In a plain retriever, the model sees the chunks and answers. In this project, the graph decides what to retrieve next based on what came back, which is what lets it handle questions whose second lookup depends on the first answer. If your questions do not have that shape, the graph adds latency and moving parts without adding answers. A reasonable test is to run both against the same question set and compare, using the Ragas metrics the README already names as the scoring mechanism.
Licence, maintenance, and what the README is selling
The repository is Apache-2.0, which permits commercial use and modification and includes a patent grant, with the usual requirements around preserving notices and stating changes. That is a permissive licence, and it means copying the graph structure into a private codebase is straightforward. This is not legal advice; read the licence text and your own policy. On maintenance: no releases are retrieved, so there is no upgrade path other than pulling the main branch, and the dependency risk sits with LangChain and LangGraph rather than with this repository. Budget for reading the diff before you pull. One more thing worth naming plainly: the README is heavily promotional. It leads with a paid book, states sales figures and an Amazon ranking, and links a paid course and a newsletter, with tracked URLs. None of that affects the code's licence or its usefulness, but it does mean the README is not a neutral specification. Read the notebooks for what the project does, and treat the surrounding copy as advertising.
Editorial conclusion
Adopt it if you have a bounded document set, mostly PDFs, and questions that need several retrieval hops rather than one similarity lookup, and you are willing to read and adapt notebook code. Do not adopt it if you need a pip-installable library with a stable API, a non-PDF ingestion path, or a hosted service. Before committing, verify three things in the repository: which LangGraph and LangChain versions the notebooks pin, whether the ingestion cells assume a single book-shaped PDF, and how the Ragas evaluation is wired to your own answer set. The Apache-2.0 licence lets you copy the graph into a private codebase without a redistribution obligation, but the README is also a funnel to a paid book and course, so treat the notebook as the artifact and the surrounding links as marketing.
Community notes