Controllable-RAG-Agent:用確定性圖拆解複雜問答,先讀懂它的邊界
This repository provides an advanced Retrieval-Augmented Generation (RAG) solution for complex question answering. It uses sophisticated graph based algorithm to handle the tasks.
秒懂
- 它是什麼?
- 這個專案用一張確定性圖當作 agent 的推理骨架,處理語意相似度檢索答不了的複雜問題。它的價值在可控與可追蹤,代價是你得先接受它的資料前處理流程與 LangGraph 依賴。
- 適合誰用?
- 若你的問題需要跨章節比對、需要引用原文段落、而且你能接受把資料先經過章節切分與摘要的前處理流程,這個專案值得排進評估清單;若你只需要單一事實查詢,或你的瓶頸是延遲與成本而非答案品質,它會是過重的工具。動手前先確認三件事:graphs 目錄下那張圖的節點與邊是否與你的問題型態對得上、Ragas 在你的資料上能否給出可解釋的分數、以及 Apache-2.0 授權下你對外散布修改版本時要保留哪些聲明。
- 可以商用嗎?
- 可以。Apache-2.0 是寬鬆授權:你可以使用、修改並販售以它為基礎的軟體,只需保留著作權與授權聲明。
- 還在維護嗎?
- 有在維護。儲存庫最近一次提交在 1 天前。
- 用什麼語言寫的?
- 主要是 Jupyter Notebook(依據 GitHub 的語言統計)。
以上回答依據專案的 GitHub 資料(最近同步於 2026年9月15日)與我們的分析,不構成法律意見。
開源專案深度解析
它解決的是語意檢索答不了的那類問題
一般的 RAG 流程是這樣:把文件切塊、編碼進向量庫、用問題去檢索最相近的幾塊、塞進 prompt 讓模型生成答案。這條路對「某個名詞的定義是什麼」很有效,但對「書中哪個角色的立場在第三章和第七章之間改變了,改變的依據是什麼」幾乎無能為力。原因不在模型,而在檢索:相似度只會回傳語意上靠近問題的片段,它不會替你拆解問題、不會替你把兩個章節的內容放在一起比對、也不會告訴你目前蒐集到的證據夠不夠。專案描述直接把目標寫成處理「simple semantic similarity-based retrieval cannot solve」的複雜問題,這句話就是它的適用範圍宣告。
適用對象因此相當明確:手上有一份有結構的長文件(README 的示範是 PDF 書籍),問題需要多步推理與原文引證,而且你願意為了答案的可追溯性付出額外的 LLM 呼叫與流程複雜度。反過來說,如果你的使用情境是客服 FAQ、單一產品的規格查詢,這個架構的每一層前處理都是多餘的。
確定性圖作為大腦:節點、狀態與可控制性
README 把核心機制描述為一張「sophisticated deterministic graph」,並說它扮演 agent 的「brain」。這裡的 deterministic 是關鍵字。多數 agent 框架讓模型自己決定下一步呼叫哪個工具,路徑由模型的輸出決定,因此同一個問題跑兩次可能走不同路徑。這個專案走的是另一條路:把推理步驟預先定義成圖上的節點與邊,模型負責在各節點內完成被指派的子任務,但流程的走向由圖決定。
這個設計換來兩件事。第一是可控制:你能指定什麼情況下要回頭補檢索、什麼情況下要進入比對階段,而不是祈禱模型選對工具。第二是可除錯:當答案不對,你可以沿著圖上的節點逐一檢查,而不是面對一段自由生成的中間推理。代價是彈性:圖上沒有的路徑,agent 走不出來。
README 列出的能力包括 multi-step reasoning 與 adaptive planning,後者指的是計畫會隨新資訊更新。要注意這兩者與 deterministic 並不矛盾:圖的骨架固定,但在節點內根據已蒐集到的內容調整後續要查詢什麼,這仍然是在既定拓撲內運作。倉庫把圖的示意放在 graphs/final_graph_schema.jpeg,實際的節點與邊的定義則落在 Jupyter Notebook 裡。要判斷它是否適合你,最直接的做法是打開那份 schema 圖,對照你自己的問題型態,看節點數量與分支是否覆蓋你的推理步驟。
資料流:從 PDF 到向量庫的五個階段
README 的 How It Works 段落把流程寫成編號步驟,這是理解整個系統最實用的部分。第一步是 PDF loading and processing,把文件載入並切成章節。切章節而非固定長度切塊,是為了讓後續的摘要與引用有語意單位可依附。第二步是 text preprocessing,清潔與前處理文字,README 說明目的是讓摘要與編碼的品質更好。第三步是 summarization,用 LLM 為每一章生成 extensive summaries,這份摘要之後會被編碼進向量庫,成為檢索時的替代入口。
第四步值得單獨看:book quotes database creation,建立一個資料庫,供需要引用原文的特定問題使用。這一步回答了「如何防止模型編造引文」的問題:當答案需要逐字引用,系統不是叫模型憑記憶寫,而是從一個專門的引文庫取用。第五步是 vector store encoding,把書籍內容與章節摘要都編碼進向量庫。
這裡有一個容易被忽略的設計取捨:內容與摘要同時進向量庫,意味著檢索時可能命中摘要而非原文。摘要能提高召回率,因為它壓縮了整章的語意;但它也可能讓答案停留在概括層次,而失去原文的細節。如果你的問題需要精確數字或逐字表述,檢索結果落在摘要上就是一種失敗模式,而這個失敗不會以錯誤的形式出現,它會以「答案聽起來對但沒有原文支撐」的形式出現。
防幻覺的宣稱與它的實際邊界
Key Features 裡有一條寫得很直白:Hallucination Prevention,並補充「Ensures answers are solely based on provided data」。這是一個很強的宣稱,而 README 沒有在同一段說明它的實作細節,只說答案只基於提供的資料。從資料流推回去,可以理解為兩層防線:檢索階段把可用的上下文限制在向量庫與引文庫的內容,生成階段則要求模型在這些內容內作答。
但這個宣稱有邊界,而且邊界不在這個專案獨有,是這類架構共通的。第一,摘要階段本身就是 LLM 生成的內容,如果摘要寫錯了,錯誤會被編碼進向量庫,然後被當成「提供的資料」檢索出來。防幻覺機制防的是生成階段的編造,防不了前處理階段的失真。第二,「solely based on provided data」在資料本身沒有答案時,理想行為是拒答,但 README 沒有描述拒答路徑的實作。第三,引文庫只覆蓋需要引用的問題類型,其餘問題仍然依賴一般檢索。
判斷這個機制對你是否足夠,不能只看功能列表。你需要拿一組你知道正確答案的問題去跑,並且刻意檢查答案的每一句是否能對應回原文段落。這正是 Performance Evaluation 那一條存在的理由:README 說它使用 Ragas 指標做品質評估。Ragas 提供的是分數,分數能不能反映你的失敗模式,取決於你怎麼設計測試集。
把它跑起來:從 Notebook 到 LangGraph 依賴
這個專案的主要語言是 Jupyter Notebook,不是可安裝的套件。README 沒有提供 pip install 指令,也沒有 CLI 入口,這意味著「取得並執行」的路徑是把倉庫 clone 下來,在 Notebook 環境中依序執行儲存格,並設定你的 LLM 供應商金鑰。首頁欄位是空的,沒有官方文件站,所有說明都在 README 與 Notebook 裡。
依賴方面,topics 列出 langchain、langgraph、openai 與 python,這是判斷整合成本最實際的線索。LangGraph 是流程編排層,圖的節點與邊靠它定義;LangChain 負責文件載入、切分與向量庫介接;OpenAI 是預設的模型供應商。如果你已經在用 LangChain 生態,整合摩擦小;如果你的技術棧是別的編排框架,你得先決定是要把圖的概念搬過去重寫,還是接受多引入一層依賴。
向量庫的選擇 README 沒有明講,只說 encoded into vector stores。這一項在採用前必須自己確認,因為它決定了你是用本地檔案還是外部服務,也決定了索引重建的成本。同樣沒有明講的是章節切分的實作方式:切成章節聽起來簡單,但 PDF 的章節邊界偵測是出了名的不可靠,沒有目錄結構或標題樣式不一致的 PDF 會切得很糟。這是你拿到自己的文件後第一個會撞到的問題。
什麼時候它是錯的工具
第一種情況是延遲敏感。這個流程在回答之前要跑多個節點,每個節點都是一次或多次 LLM 呼叫,加上檢索與可能的回頭補查。互動式應用要求秒級回應時,這個架構的每一步都在累加時間。README 沒有提供延遲數據,所以任何具體數字都不該由我來給,但你應該假設它比單次檢索生成慢一個量級以上,並在真實資料上量測。
第二種情況是資料更新頻繁。章節摘要與引文庫都是前處理產物,原始文件一改,這些產物就要重建。如果你的知識庫每天變動,維護這條前處理管線的成本會超過它帶來的答案品質提升。
第三種情況是問題本身很簡單。單一事實查詢用傳統 RAG 就夠了,套上多步推理圖只是把一次檢索變成五次,還可能因為中間步驟的判斷失誤而讓原本答得對的問題答錯。確定性圖的好處是路徑可預測,壞處是路徑一旦不適合問題型態,它不會自己繞開。
第四種情況是你需要模型自由探索工具。這個架構的設計哲學是收斂而非開放,如果你的任務需要 agent 自己發掘該用哪個 API,這個框架的圖會成為限制。
與傳統 RAG 的差異,以及與自由 agent 的取捨
最直接的替代方案就是傳統的檢索增強生成:一次向量檢索加一次生成,用 LangChain 的 RetrievalQA 這類封裝就能搭起來。兩者的差異不在模型,在檢索與推理的組織方式。傳統 RAG 把問題當成一個查詢字串,檢索器回傳最相近的片段,模型負責在片段內找答案。這個專案把問題當成一個待拆解的任務,先產生子問題,逐一檢索,再整合。前者快、便宜、好維護;後者在問題需要跨段落整合時才有優勢,其他時候都是負擔。
另一條路線是讓 LLM 自主決定呼叫哪些工具的 agent,例如 ReAct 風格的做法。差別在控制權的位置:ReAct 把路徑交給模型,這個專案把路徑交給圖。ReAct 在工具集合開放、任務型態多變時更靈活;這個專案在流程固定、需要可重現結果時更可靠。如果你在意的是「同一個問題今天和明天要得到同樣的推理路徑」,確定性圖是更合適的選擇。如果你在意的是「不要漏掉任何可能的工具組合」,ReAct 更合適。這兩者不是誰取代誰,而是把不確定性放在不同位置。
授權、維護成本與採用前該確認的事
授權是 Apache-2.0,這是一個寬鬆授權,允許商業使用、修改與再散布,條件包含保留版權與授權聲明、標示修改,並附上授權全文。相對於 copyleft 授權,它對商業整合的摩擦較小。這不是法律意見,實際條文與你的使用情境請自行核對,涉及專利或再散布義務時應諮詢律師。
維護成本方面,README 顯示這個倉庫同時是多個商業產品的入口:一本書、一門課程、一份 newsletter,以及另外兩個 GitHub 倉庫。這不代表專案本身不再維護,最後推送時間是 2026 年 9 月,屬於活躍狀態;但它確實意味著這個倉庫的定位偏向教學與示範,而不是一個有版本節奏與語意化版本號的函式庫。倉庫沒有檢索到任何 release,預設分支是 main,這表示升級的方式是拉取最新提交,而不是鎖定版本號。對生產系統來說,這是一個要自己承擔的風險:你需要 fork 或鎖定 commit,否則上游的 Notebook 變動會直接影響你。
採用前該驗證的具體事項有三個。第一,打開 graphs/final_graph_schema.jpeg,確認圖的節點與分支覆蓋你的推理步驟,這是最省時間的可行性判斷。第二,用你自己的 PDF 跑一次章節切分,檢查切出來的邊界是否符合預期,PDF 章節偵測是這條流程最脆弱的一環。第三,設計一組你已知答案的測試問題跑 Ragas,並人工抽查答案的引文是否真的落在原文中,摘要層的失真只有這樣才看得出來。
編輯結論
若你的問題需要跨章節比對、需要引用原文段落、而且你能接受把資料先經過章節切分與摘要的前處理流程,這個專案值得排進評估清單;若你只需要單一事實查詢,或你的瓶頸是延遲與成本而非答案品質,它會是過重的工具。動手前先確認三件事:graphs 目錄下那張圖的節點與邊是否與你的問題型態對得上、Ragas 在你的資料上能否給出可解釋的分數、以及 Apache-2.0 授權下你對外散布修改版本時要保留哪些聲明。
社群筆記