這篇文章是「Advanced RAG 架構解析」系列的第一篇技術解析,對應的綜述概覽在這裡。本篇聚焦 TableRAG(arXiv:2506.10380),逐步拆解它的架構設計、HeteQA benchmark 數據,以及工程實踐中值得借鑒的設計方式。
前言#
某人問 RAG 系統:「2008 年由 Activision 發行且仍在上架的遊戲,占全部仍在上架遊戲的百分比是多少?」
系統回答:50%。
正確答案是:20%。
這個錯誤不是因為模型不夠聰明,也不是因為向量搜尋失效——相關的表格確實被找到了。問題在於:RAG 只找到了「部分表格片段」,然後讓 LLM 在這殘缺的資料上估算百分比。LLM 盡力了,但它總不可能從片段資料算出全局正確的統計數字。
這就是 Huawei Cloud 在 TableRAG(arXiv:2506.10380)論文中,為所有現有 RAG 方法找出的根本性缺陷,他們稱這為「缺乏全局視角(Lack of Global View)」。
這篇文章會拆解 TableRAG 的架構設計,分析它在三個 benchmark 上的數據表現,探討實驗告訴我們的事,並思考這框架在真實工程場景中的落地意義。
核心問題:為什麼 Naive RAG 操作表格會失敗#
TableRAG 論文一開頭就點出現有 RAG 方法處理表格時的兩個根本問題,先弄懂這兩點,後面的設計才看得比較懂。
問題一:結構資訊損失(Structural Information Loss)#
現有的主流做法是把表格「線性化(linearize)」成 Markdown 格式,然後和其他文字一起切塊、向量化、檢索。
這樣做有一個本質上的問題:表格是二維結構,向量是一維向量。當把這個表格:
| |
轉換成一段文字字串後,每一行的語意雖然保留了,但「行與行之間的關係」、「這 500 行資料的全局統計特性」,在 Chunking 之後就消失了。LLM 看到的只是幾個片段,永遠看不到完整的表格。
問題二:缺乏全局視角(Lack of Global View)#
這是更根本的問題。許多真實的問題需要「跨越整張表格的推理」:
- 統計某個條件下的數量(COUNT)
- 計算佔比(百分比計算)
- 找到最大值或最小值(MAX/MIN)
- 按條件分組統計(GROUP BY)
這類問題,沒有辦法在「局部片段」上正確回答。你必須看到整張表格,才能算出正確的統計結果。
Naive RAG 的 Chunking 策略,讓系統結構性地喪失了這個能力。
TableRAG 的架構設計#
TableRAG 的設計核心是:用 SQL 作為操作表格的中間語言,讓 LLM 做語意理解,讓資料庫語法做精確計算。
整個系統分為兩個階段:
階段一:離線資料庫建構#
在使用者問任何問題之前,TableRAG 預先建立兩種平行的資料結構:
文件導向的向量資料庫(Document-Oriented Database)
把文件的文字部分和 Markdown 格式的表格,都切塊後向量化,建立標準的向量搜尋索引。這部分和 Naive RAG 類似。
關鍵的不同是:對於每個表格片段,系統會記錄它來自哪張完整表格(這個對應關係稱為映射函數),以便之後能取得那張表格的欄位結構(欄位名稱、資料類型、範例值)來生成 SQL。這個對應關係在後續的推理中非常關鍵。
關聯式資料庫(Relational Database)
把每張原始表格的完整資料匯入 MySQL,每張表格在資料庫裡對應一張獨立的 SQL table,之後就能對它下 SQL 查詢。
同時,為每張表格建立一個標準化的 Schema 描述:
| |
這個 Schema 記錄了表格的欄位名稱、資料類型與範例值,讓 LLM 理解表格結構後生成正確的 SQL。
階段二:線上迭代推理#
使用者輸入問題後,TableRAG 進入一個最多執行 5 次的迭代推理迴圈,每次迭代包含四個步驟:
步驟一:情境感知的查詢分解(Context-Sensitive Query Decomposition)#
這是 TableRAG 和普通 ReAct 框架最重要的差異之一。
普通的問題分解只做「語法切割」,把一個複合問題拆成幾個子問題。但 TableRAG 先做了一件事:從向量資料庫中找到最相關的表格片段,先看清楚表格的欄位結構,再決定怎麼拆問題。
這樣做的邏輯是:同一個問題「這份名單裡有多少 2008 年發行的遊戲?」,如果對應的表格有 release_date 欄位,就可以直接下 WHERE release_date LIKE '%2008%';但如果表格把年份和月份分成兩個欄位存,就要換一種寫法。不先看表格結構就拆問題,很容易生成根本跑不起來的 SQL。
步驟二:文字檢索(Text Retrieval)#
對於每個子查詢,系統進行兩段式的文字檢索:
- 向量召回(Recall):用子查詢的 Embedding 在文件資料庫中找出 cosine 相似度最高的 top-30 候選片段
- 語意重排(Rerank):用更精確的 Reranker 模型,從 30 個候選中選出最終的 top-3 論文使用的是 BGE-M3 系列模型,在召回階段和重排階段分別使用不同的模型配置。
步驟三:SQL 程式生成與執行(SQL Programming and Execution)#
這是 TableRAG 的核心創新。
系統檢查上一步的文字檢索結果:如果 top-3 結果中,有任何片段來自表格(通過映射函數 f 判斷),系統就自動進入 SQL 執行路徑。
具體流程:
- 取得這些表格片段對應的欄位結構(若片段來自不同表格,會同時帶入多張表格的結構,讓 LLM 判斷是否需要 JOIN)
- 把子查詢和欄位結構一起送給 LLM,讓它生成可執行的 SQL
- 在 MySQL 資料庫上執行,得到精確結果 一個真實的 SQL 生成範例(來自 HeteQA 資料集):
| |
這段 SQL 是 TableRAG 把原始問題拆解出的子查詢(論文中的 sql_query 欄位):「2012 年下半年(7-12 月)上映、演員人數最多的喜劇電影是哪一部?」
但論文中使用者真正問的原始問題(query 欄位)其實是:「在《2012 年澳洲電影列表》中,2012 年下半年上映、演員人數最多的喜劇電影,是由誰編劇並主演的?」(Who wrote and starred…)。這段 SQL 只解決了「找出哪部電影」這個中間步驟(執行結果是片名 Kath & Kimderella),論文給出的最終答案是人名「Riley, Turner, and Magda Szubanski」,需要再一步從文件中查出該片的編劇與主演。
注意 SQL 使用的技巧:用字串長度差計算逗號數量(LENGTH - LENGTH(REPLACE) + 1)來估算演員人數。這種操作 LLM 完全可以生成,但若讓 LLM 直接從文字中計算,幾乎必然出錯。
步驟四:組合式中間答案生成(Compositional Intermediate Answer Generation)#
每個子查詢現在有兩個資訊來源:
- SQL 執行結果:精確,但可能有語法錯誤或邏輯錯誤
- 文字檢索結果:語意豐富,但可能不完整 TableRAG 讓 LLM 對這兩個來源進行交叉驗證:
- 如果兩者一致,直接採用
- 如果 SQL 執行失敗(如欄位名稱錯誤),退回到文字檢索結果
- 如果兩者矛盾,LLM 根據可信度評估選擇更可靠的答案 這個交叉驗證機制,讓 TableRAG 在 SQL 生成不完美時也能給出合理答案,而不是直接失敗。
HeteQA:專門為這類問題設計的 Benchmark#
TableRAG 論文的另一個重要貢獻是建立了 HeteQA(Heterogeneous Question Answering) benchmark,這個 benchmark 本身的設計值得細說。
為什麼需要新的 Benchmark?#
現有的表格 QA benchmark,大多數問題只需要「找到」資訊,而不是「計算」資訊。WikiTableQuestion 問的通常是「誰贏得了 2008 年的決賽?」這類直接查找問題。HybridQA 雖然涉及多跳推理,但表格大多是小型的、不需要全域統計的。
HeteQA 的設計哲學是:強制要求真正的「表格操作能力」。
HeteQA 的設計#
資料來源:從 Wikipedia 資料集中,篩選出至少 20 行、至少 7 欄的表格(從 15,314 張表格中篩選出 1,345 張,再去重後保留 155 張有代表性的表格)。
問題類型:每個問題都要求至少一種真正的「表格操作」:
| 操作類型 | 比例 | 典型問題 |
|---|---|---|
| Filtering(條件過濾) | 26.2% | 「找出 2008 年發行且仍在上架的遊戲」 |
| Grouping(分組統計) | 18.8% | 「按發行商統計遊戲數量」 |
| Aggregation(聚合) | 26.6% | 「計算特定條件下的平均值」 |
| Calculation(計算) | 19.2% | 「計算兩個時期的成長率」 |
| Sorting(排序) | 9.2% | 「找出演員最多的喜劇電影」 |
多源問題:18% 的問題需要同時參考表格和 Wikipedia 文字,進行跨模態推理。
建構方式:用 Claude-3.7-Sonnet 生成問題和對應的 SQL/Python 代碼,執行代碼獲得答案,再由兩位人工標注員獨立驗證每個問題的正確性。
最終 HeteQA 包含 304 個高品質問題,涵蓋 9 個語意領域(運動 40.4%、交通 12.8%、文化/文學 13.2%、軍事 3.7% 等)。
主要實驗結果#
三個 Benchmark 上的整體表現#
| 方法 | Backbone | HybridQA | WikiTQ | HeteQA Overall |
|---|---|---|---|---|
| Direct | Claude-3.5 | 9.84% | 6.21% | 10.00% |
| NaiveRAG | Claude-3.5 | 20.28% | 82.60% | 34.54% |
| ReAct | Claude-3.5 | 43.38% | 69.81% | 29.60% |
| TableGPT2 | — | 9.51% | 63.40% | 32.24% |
| TableRAG | Claude-3.5 | 47.87% | 84.62% | 44.19% |
| TableRAG | DeepSeek-V3 | 47.87% | 80.40% | 44.85% |
| TableRAG | Qwen-2.5-72B | 48.52% | 78.00% | 38.82% |
幾個觀察:
HybridQA 上,TableRAG 比 NaiveRAG 高出超過 2 倍(47.87% vs 20.28%):這個 benchmark 專注於需要跨表格和文字進行多跳推理的問題,正是 SQL 精確計算最能發揮優勢的場景。
WikiTQ 上,NaiveRAG 表現出乎意料地強(82.60%):WikiTQ 問題大多是直接查找型,不需要跨行計算,Markdown 化表格可以勉強應付。TableRAG 的 84.62% 只是略高。
ReAct 在 HeteQA 單源(Single-Source)數據上表現很差(26.40%):這驗證了論文的一個核心論點——ReAct 傾向於過度分解問題,把本可以一個 SQL 解決的問題拆成多個子查詢,反而引入了累積錯誤。
TableGPT2 的 Python 執行路徑在多源問題上表現很差(16.67%):它缺乏整合 Wikipedia 文字的能力,多源問題對它來說明顯吃力。
消融實驗:每個模組貢獻了多少#
論文做了三個消融版本:
- w/o Context-Sensitive Decomposition:不先查 Schema,直接分解問題
- w/o SQL Execution:把 SQL 路徑換成 Markdown 表格格式
- w/o Document Retrieval:只用 SQL,不查文字資料庫
在 HybridQA 上:
- 移除 Document Retrieval 帶來最大的性能下降
- 這合理,因為 HybridQA 的問題需要從 Wikipedia 文字中找到關鍵實體,再去表格中查找對應數值
在 HeteQA 上:
- 移除 SQL Execution 帶來最大的性能下降(論文僅以長條圖呈現、未給精確數字,從圖 4 目視估計降幅超過 10 個百分點)
- 這直接驗證了「表格計算必須用SQL 精確計算,不能讓 LLM 猜」的核心論點
兩個 Benchmark 的不同表現說明一件事:文字檢索和 SQL 執行是互補的,不是替代關係。不同類型的問題需要不同的能力,兩者缺一不可。
效率分析:SQL 執行是快還是慢?#
論文對 TableRAG 和 ReAct 做了延遲對比(使用 Qwen-72B-Instruct 作為 backbone):
| 方法 | 總延遲(WikiTQ) | 每步平均延遲 | 總延遲(HeteQA) | 每步平均延遲 |
|---|---|---|---|---|
| ReAct | 13.50 秒 | 5.92 秒/步 | 24.57 秒 | 7.70 秒/步 |
| TableRAG | 17.70 秒 | 7.93 秒/步 | 45.65 秒 | 10.79 秒/步 |
TableRAG 的總延遲更高,但論文指出這主要是因為 HeteQA 的問題複雜度更高,需要更多步驟。
每步平均延遲:TableRAG (7.93s) > ReAct (5.92s)。這是合理的,因為 TableRAG 的每步包含了 SQL 生成 + 執行的額外開銷。
從步驟分布來看,TableRAG 更高效:論文數據顯示絕大多數問題能在 5 步以內解決(論文以長條圖呈現,未給出精確的完成率數字)。相比之下,ReAct 和 TableGPT2 有更多問題超過 5 步或無法在限制內完成。
整體來看,TableRAG 每步更貴,但步數更少,複雜問題上反而更有效率。
從系統落地的角度再補充一點:TableRAG 因為能在 5 步內精準收斂,避免了 ReAct 框架常見的「無限 Loop」或「Token 暴漲」問題。在高並發場景中,更低的 Token 總消耗往往比單次請求多等幾秒更具成本優勢——多等 2 秒是使用者體驗問題,Token 暴漲是成本問題。
錯誤分析:系統在哪裡失敗#
論文對失敗案例做了分類:
推理失敗(Reasoning Failures):SQL 生成錯誤或中間查詢分解出現問題。這是主要的失敗類型,主要發生在問題語意非常模糊或表格結構非常複雜時。
任務未完成(Task Incompletion):超過最大迭代次數(5 步)仍未找到答案,或 LLM 拒絕回答。這主要發生在需要跨多張表格的極複雜問題。
TableGPT2 的失敗率顯著高於 TableRAG,主要原因是它缺乏整合 Wikipedia 文字上下文的能力,導致大量「拒絕回答」或「承認無法完成」的輸出。
落地的五個思考#
一、Schema 提取品質決定 SQL 生成品質#
TableRAG 的離線階段有一個容易被忽視的細節:Schema 提取時的「代表性樣本選擇(Representative Sample Selection)」。論文特別提到要在保持值多樣性的同時控制樣本長度。
這在工程實踐中很重要:如果樣本選得不夠代表性,LLM 可能對欄位類型或值格式產生誤解,導致 SQL 生成失敗。建議在 Schema 中包含:
- 每個欄位的資料類型
- 3-5 個真實值範例(不要只選最前面幾行)
- NULL 值的處理規則
二、SQL 執行的優雅降級#
論文提到 TableRAG 的容錯設計:當 SQL 執行失敗時,系統會自動退回到 Markdown 格式的文字檢索模式。這個「優雅降級(Graceful Degradation)」機制在生產環境中非常重要。
在工程實踐中,建議:
- 設置 SQL 執行的 timeout(避免全表掃描拖垮系統)
- 對常見的 SQL 錯誤類型(欄位名稱錯誤、型別不匹配)做特別的錯誤提示,讓 LLM 有機會修正
- 保留文字檢索路徑作為備援,而不是完全依賴 SQL
三、MySQL vs. 其他資料庫的選擇#
論文使用 MySQL,但在實際部署中,選擇哪個資料庫取決於使用場景:
- DuckDB:適合分析型查詢,In-process 部署,對 CSV/Parquet 友好,無需獨立伺服器
- SQLite:適合輕量場景,零配置,但並發性能差
- PostgreSQL:適合需要複雜 SQL 功能(窗口函數、JSON 操作)的場景
四、迭代次數上限的設定#
論文把最大迭代次數設為 5。在工程實踐中,這個數字應該根據:
- 業務問題的平均複雜度(簡單問題設 3 步就夠)
- 每步的平均延遲(高併發場景下必須控制總延遲)
- 使用者的等待容忍度
一個務實的做法是動態調整:先評估問題複雜度,複雜問題允許更多步驟,簡單問題就不需要。
五、Text-to-SQL 的安全防線與資源隔離#
在生產環境讓 LLM 自動生成並執行 SQL 風險不小,工程落地時至少要加上三道防線:
唯讀權限:執行 SQL 的資料庫帳號要與業務資料庫隔離,只開放特定視圖或唯讀資料表,INSERT、UPDATE、DELETE 權限都不該存在於這帳號上。
強制 LIMIT 上限:後端在執行前對 SQL 做靜態檢查,不管 LLM 有沒有自己加 LIMIT,都在末尾硬性追加一個上限(例如 500),避免全表掃描或百萬級數據回傳把系統資源吃光。
| |
過濾危險函式:SLEEP()、BENCHMARK() 這類可能被拿來做 DoS 的內建函式直接禁用,SQL 送出前做白名單或黑名單過濾。
論文沒提這些工程細節,但要把 TableRAG 從 PoC 搬進生產環境,這三道防線也是蠻需要的。
結論#
TableRAG 在 benchmark 上的數字只是表面,真正重要的是它背後的設計原則:在需要精確計算的場景,用邏輯規則執行取代語意猜測。
SQL 之所以適合作為中間語言,有三個原因:
- LLM 已經在大量 SQL 訓練資料上預訓練,SQL 生成品質相對可靠
- SQL 的語意是精確且可驗證的,執行結果確定性強
- 關聯式資料庫對大表的聚合計算有極高的效率
這個原則可以推廣:對於任何 LLM 不擅長的精確操作(數學計算、邏輯推理、精確查找),應該引入對應的外部工具,而不是試圖讓 LLM 直接完成。
TableRAG 解決了「表格計算」的問題。但它沒有解決「表格結構保存」的問題——這是另一篇要討論的 MixRAG 的內容。
系列文章導航#
- ← 綜述概覽:Advanced RAG——四篇論文的架構思考
- → MixRAG 技術解析:H-RCL 層級表示法如何保存表格結構
- → UniversalRAG 技術解析:模態路由解決多模態 RAG 困境
- → MRAG 技術解析:時序規則計算解決時間敏感問題
延伸資源#
- 📄 論文原文:arXiv:2506.10380
- 💻 官方代碼:github.com/yxh-y/TableRAG
- 📊 HeteQA Benchmark:包含在論文 GitHub 倉庫中