LinkedIn 內部 Text-to-SQL chatbot 的完整工程實錄:以 knowledge graph 為核心、Researcher Agent 修 hallucination,在百萬級 table 的 data lake 上達到 53% 專家認可率與 300+ 週活用戶。
Spider/BIRD 的執行準確率從 54% 一路衝到 90% 以上,但這些數字一搬到真實企業 data lake 就崩潰。LinkedIn 想做一個「全公司任何員工都能用」的 SQL 助手 — 而這篇 paper 就是把這條工程之路完整公開。
90%+
2023.11 時的 SOTA execution accuracy — 看起來幾乎解決。
76%
2025.04 時的最佳成績。介於可用與不可用之間。
31%
2025.04 SOTA 只有 31%。Ground truth query 超過 100 行、table 超過 1000 column。真實企業場景的指標。
連 Uber 自家 QueryGPT 在內部 eval set 上,也只有大約 50% 的 ground truth tables overlap。換言之,只用一個 fine-tuned LLM 套上 schema 是不夠的。
Data lake 有數百萬張 table,熱門 table 動輒 100+ 個 column。Table 經常被 deprecated、訊息重疊嚴重 — 模型要先選對 table 才有後續。
「最新的 click-through rate」對 notifications team 與 search team 是完全不同的 metric。模型必須結合 user / product area 的上下文才能解讀。
公司內部有獨特的 acronym 與術語,公開語料學不到 — 必須從 wiki、code repo、歷史 query 中抽取。
使用者不是只要 SQL,還要 chatbot 幫忙找 table、解釋 query、修 bug。「Text-to-SQL」只是 chat 體驗的一部分。
本文三大貢獻: ① 用 knowledge graph 把 schema、code repo、query log、wiki、jargon、群眾 domain knowledge 全部整合,並以 ICA 把 table 自動分群到 product area;② Query Writer Agent 採用多階段 retrieval + ranking,並由 Researcher Agent 在 query fix 時動態取回新 table 來解 hallucination;③ Multi-Agent UI 用 intent 分流 query writing / data finding / query fixing / Q&A,確保 follow-up 體驗順暢。
「據我們所知,這是第一份公開、細節完整的 enterprise Text-to-SQL 系統。」
系統由下而上分三層:Knowledge Graph (語意基底) → Query Writer Agent (生 SQL 的核心 agent) → Multi-Agent Chat UI (使用者介面與意圖分流)。三層之間的資料流如下圖。
下圖中的每一層,在後續章節都會展開細節。先記三個關鍵字:knowledge graph 提供語意、Query Writer Agent 把語意變成 SQL、multi-agent UI 處理任何不只是 T2S 的問題。
Knowledge Graph 的中心節點是 Table,從 table 可以出發找到欄位、常見 join、example query、domain knowledge、可讀取的使用者群組。另一個組織節點是 Product Area,把 table 跟團隊綁在一起。
| Node | Attributes |
|---|---|
| Table | Database Name, Table Name, Human Description, AI Description, Usage Popularity, Table Cluster, Tags, Certification Status, Deprecation Status |
| Column | Database Name, Table Name, Column Name, Human Description, AI Description, Usage Popularity, Top Values, Data Type, Column Type (metric/dimension/attribute), Is Partition Key |
關鍵設計: Certification Status 標出資料治理已認可的高品質 table;Column Type 把欄位分成 metric / dimension / attribute,讓 LLM 知道哪些是度量、哪些是維度。沒有 human description 時用 Glean Chat API 自動補一份 AI description。
來源:DataHub。Embed 的對象是 table name + description + tags。支援 EBR、依名稱或 product area 查。每週更新。
解析成功 Trino query 的 EXPLAIN plan (JSON),聚合出 table popularity 與 common joins。每週更新。
每個 user 對應的相關 dataset list (見 §04 ICA 叢集)。每週更新。
來自 code repo 與 wiki 的人類手寫 query。Wiki 的描述直接 embed;code repo 的 query 用 gpt-35-turbo 自動生成描述後再 embed。過濾條件:creation date、execution count、filename、是否被 user 認證。
UI 上由 user 提交的 product 背景、資料說明、個人偏好。即時更新(用戶在介面送出後立刻生效)。
來源:公司 wiki。資料結構是 {jargon → explanation},query 階段用 string matching 拉出來附給 LLM。
分散式設計的關鍵:不同 index 有不同更新頻率,domain knowledge 即時、其他每週,讓 user 投入的人工標註可以即刻產生回報 — 這是「使用者貢獻 → 系統變更好 → 使用者更願意貢獻」的飛輪。
百萬張 table 不可能整個塞給 LLM。LinkedIn 用三個月的 query history 中的 user-table access matrix,跑 Independent Component Analysis (ICA) 做 soft clustering,讓每個 user 與 product area 對應到自己最相關的 table 子集。
用 user-table access count 矩陣,丟掉總 access 或 unique user 數太少的 table — 例如 data pipeline 產生的 intermediate table,沒人會直接查。
對 user 維度做標準化 (mean=0, std=1),避免少數重度使用者壓過全體。
用 sklearn.decomposition.FastICA 做 N_comp = 200 個 component。每個 component 對應一種「access pattern」 — 通常會反映某個產品團隊的工作習慣。
每個 component 取分數絕對值最高的 T_c = 20 個 table。同一張 table 可被多個 cluster 包含 — soft clustering 是這套方法的關鍵。
對每個 user 把他在每個 component 的 access count 加總,取最高的前幾個 component。Product area 則用 team email group 中的代表員工的 cluster 投票,平手時看 cluster access count。
K-means 是 hard clustering — 一張 table 只能歸到一個 cluster,但實際上一張 member 表可能同時是 growth、ads、search 都會用的「共用表」。ICA 的軟分群讓共用 table 自然出現在多個 cluster 裡,而且當有 team 解散、table deprecated 時,只要重跑 weekly job 就會自動重新分配。
效能:整個 clustering pipeline 的 P90 跑完時間是 15 分鐘。週週重跑也不會是系統瓶頸。
function GetCandidateTables(user, product_areas):
user_clusters = GetUserGroupClusters(user)
product_email_groups = GetEmailGroups(product_areas)
representative_users = GetEmployees(product_email_groups)
product_area_clusters = GetUserGroupClusters(representative_users)
clusters = merge(user_clusters, product_area_clusters)
inferred_tables = GetExtendedTables(clusters)
explicit_tables = GetExplicitTables(product_areas)
return merge(inferred_tables, explicit_tables)
每次 chat session 開始時,先用這支函式把 user + 選定 product area 對應的 cluster 全部攤平、加上手動標註的 explicit table,當作後續 EBR 的搜尋範圍。長尾 table 透過 chat 中的後續詢問動態補入。
用 langchain 實作。Input 三件事:question、user name、product area list。Output 是包含 SQL、解釋、用到的 table/column、與要 verify 的 assumption 的 dict。
目標:高 recall。先用 §04 的候選 table list 圈住搜尋範圍,接著從三個來源各取若干:
三條合起來取 K_ret = 20 張 table,接著抓所有對應的 column,再加上 product area 對應的 domain knowledge 與 jargon。
從 20 張 table 用 LLM 細選到 K_rnk = 7 張。Table Ranker LLM 給每張 table 1–10 的相關度分數並附解釋,所用線索包括:
作者特別註明:把 table schema 也丟給 ranker 反而降低 recall 並增加 latency,所以這一步不附 schema。
Column Ranker 接著從 7 張 table 的所有 column 中挑出兩個 tier:relevant 與 potentially relevant。把 potentially relevant 也帶進去能提升 recall。每張 table 用 CREATE TABLE 形式呈現,column 依 usage popularity 排序。
把上一階段選出的 table + column + 相關度分數與解釋 + examples + domain knowledge + jargon 全部塞進 prompt,Query Writer LLM (gpt-4o) 回傳:
{
"assumptions": [...], # 給用戶 verify 的假設
"query": "SELECT ...",
"explanation": "...",
"tables": [...],
"columns": [...]
}
Query validation loop 最多跑 兩次,處理兩種錯誤:
用 Trino EXPLAIN VALIDATE 驗證。錯誤訊息直接餵給一個 fixer LLM 即可修。
由另一支自製 hallucination validator 一次抓出所有不存在的 table/column (Trino EXPLAIN 每次只回一個錯)。這種錯通常表示 context 中缺乏對的 table,需要動態補進新 context — 這是 Researcher Agent 出場的時機。
Researcher 是一個會自我反思的 agent,專門解 hallucination。它有工具可以搜 table、抓 table schema、抓 metadata。例如它可以根據 hallucinated 的 table 名搜出最相似的真實 table。
速度設計:Researcher 本身用較快的 gpt-4o-mini 做搜尋,但 self-reflection 用較強的 gpt-4o。輸出是「新的 context + 推薦使用什麼資料」,丟給 query fixer LLM 重寫 query。
20
retrieval 階段保留的 table 數
7
ranking 後送給 writer 的 table 數
≤ 2
最多兩輪修錯
線上後作者學到的最大教訓:user 想要的不是 Text-to-SQL,是一個能寫 query、找 table、修 bug、回答任何資料問題的通用資料助手。所以系統長出了 multi-agent 結構。
核心 agent,§05 介紹的完整 pipeline。
只跑 Query Writer 的 retrieve + rank 階段,把 7 張建議 table 與 metadata 回傳。
專門 debug query execution failure (permission / syntax / schema)。
所有不支援的 long-tail 意圖。架構類似 Researcher Agent,有 schema 查詢、wiki 搜尋、query validate 等工具。
Q&A 範圍最廣,作者用三招控速度:① 判題目難度,簡單題目跳過 self-reflection;② 預先抓 table metadata,避免反覆 tool call;③ 兩個 LLM 都用 gpt-4o-mini。
Chatbot 不是獨立網站,是公司 SQL 編輯器側邊欄 — user 不用切換 tool。「Fix with AI」按鈕在 query 執行失敗時自動出現。
Query output 包含 inline 註解的 SQL、驗證結果、解釋、用到的 table、相關 reference query、要驗證的假設。Table output 有 description、popularity、common join、certification status,還有 checkbox 讓 user 選擇要用哪些。
聊天框上方有 suggested follow-up — 讓 user 不需打字也能順下去。
UI 上 user 可以新增 product area、新增 domain knowledge、認證 example query — 直接寫入 knowledge graph,週週飛輪滾起來。
Speed is critical. 多 agent + state 維護 + intent classifier,每一塊都會疊延遲。Production 的 full model 平均 60 秒內回覆 — 不快,但對複雜企業 query 來說可接受。
作者自製了一份內部 benchmark:133 個問題 × 10 個 product area × 167 個 ground truth table,而且 60% 的題目允許多個正確答案 (multiple ground truths)。
Table recall 與 column recall — 是否找對表格與欄位。多 ground truth 時取與回答 overlap 最高的那組。
Overall score (1–5)、compilation success rate、valid tables & columns rate。用 human eval + LLM-as-judge (gpt-4o) 一起評。
LLM call 數、EBR query 數、DB query 數 — 系統複雜度的代理指標。Full 模型平均 60 秒/題。
| Score | Definition |
|---|---|
| 1 | 完全錯,沒回答到問題。 |
| 2 | 找對 table 但 90% column 是錯的,沒回答到問題。 |
| 3 | 找對 table 與大多數 column,但有需要相當 effort 或領域知識才能 fix 的缺口,沒答到問題。 |
| 4 | Table 對、幾乎所有 column 對,有非專家就能 fix 的小問題 (例如日期 filter 錯)。回答了問題但細節可能缺。 |
| 5 | 完全正確、完整地回答問題。 |
Models: 例句 embedding 用 E5-large-v2,table/column embedding 用 text-embedding-ada-002,Researcher LLM 用 gpt-4o-mini-2024-07-18,其餘 LLM 用 gpt-4o-2024-05-13,temperature = 0,單次運行。
| Config | Description | Tab Recall | Col Recall | Score 4+ | Compile OK | Valid T&C | LLM | EBR | DB |
|---|---|---|---|---|---|---|---|---|---|
| Full | All components | 78% | 56% | 48% | 96% | 99% | 4.6 | 3.0 | 9.4 |
| A.5 | Full w/o popularity or joins | 77% | 53% | 42% | 95% | 98% | 4.8 | 3.0 | 8.4 |
| A.4 | A.5 w/o domain knowledge or jargon | 76% | 52% | 49% | 96% | 99% | 4.7 | 3.0 | 8.5 |
| A.3 | A.4 w/o example queries | 60% | 38% | 24% | 98% | 100% | 4.6 | 1.0 | 7.0 |
| A.2 | A.3 w/o table or column attributes | 56% | 30% | 11% | 93% | 99% | 5.0 | 1.0 | 7.5 |
| A.1 | A.2 w/o table clusters (schemas only) | 45% | 24% | 9% | 88% | 99% | 5.1 | 1.0 | 7.1 |
| B.3 | Full w/o researcher agent | 75% | 53% | 47% | 95% | 98% | 4.3 | 3.0 | 9.5 |
| B.2 | B.3 w/o query fixer | 76% | 55% | 47% | 76% | 85% | 4.0 | 3.0 | 8.4 |
| B.1 | B.2 w/o rankers (EBR + writer only) | 67% | 50% | 46% | 66% | 77% | 2.0 | 3.0 | 7.1 |
| C.4 | (A.4, B.3) combination | 76% | 52% | 46% | 97% | 98% | 4.3 | 3.0 | 8.6 |
| C.3 | (A.3, B.2) combination | 60% | 37% | 20% | 77% | 87% | 4.0 | 1.0 | 6.1 |
| C.2 | (A.2, B.1) combination | 49% | 27% | 17% | 68% | 83% | 2.0 | 1.0 | 5.0 |
| C.1 | (A.1, B.1) combination | 37% | 23% | 16% | 67% | 81% | 1.9 | 1.0 | 3.9 |
Score 4+ 從 A.1 的 9% → Full 的 48%,提升主要靠 example queries (A.3→A.4: +25 pp)、table clusters、table/column attributes。語意理解只能靠 KG 補。
Compilation success 從 B.1 的 66% → Full 的 96%,valid T&C 從 77% → 99%。主要靠 query fixer 與 context rankers。但 score 提升有限 — 模型元件改不了語意理解。
A.5 (有 domain knowledge) 的 Score 4+ 是 42%,A.4 (沒有) 反而是 49%。作者推測是「irrelevant domain knowledge records」造成干擾。
C.4 用比 Full 少的元件 (A.4 KG + B.3 modeling) 仍達到 Score 4+ = 46% (僅低 2 pp),且 LLM call 數 4.3 vs 4.6、DB query 8.6 vs 9.4 — 省成本但幾乎不掉品質。
Chatbot 自 2024 年 7 月上線,以下是 paper 寫作時 (2025.04) 的真實使用數據。
300+
週活用戶
100+
每月超過 100 次 chat session
20%
本週活躍用戶下週也回來
33%
session 最後有 code 被貼到編輯器
讓 10 個 product area 的 domain expert 評 production 版本的回答,收到 124/133 題回應:
53%
專家認為「答對」或「小修即可」
77%
「對找 table/column 有幫助」
24%
filter 條件錯;但 incorrect join 只有 4%。
「Very good」或「Excellent」: 39% ─ 「很好,只要小改」或「完美」。
「Passes」以上: 95% ─ 「至少需要一些修改」即可用。
這節最值得讀。作者試了三個學界主流技巧,在 LinkedIn 場景上全部失敗。這對任何想做 enterprise T2S 的工程師都是免費教訓。
學界做法是產生多個 query、選最一致的那個 (e.g. CHASE-SQL, CHESS)。但在 enterprise 場景中:
變通方案 (產生最多 3 個寫法當作 CoT) — 沒提升 recall。作者結論:self-consistency 的有效性來自 input shuffling 與實際執行,缺一不可。
仿 DIN-SQL 的做法 — 用 planner LLM 把問題拆成多個子任務,逐步解。結果:
即使後來限制 planner「儘量少拆」+ few-shot 例子,仍敗。作者假設:gpt-4o 本身已經夠強,任務分解只會額外限制它的解題空間 — 較小模型也許需要,但 gpt-4o 不需要。
把 planner 拆出的子任務當作 query 字串去做 retrieval (一種 query expansion)。結果 沒有改善 EBR table recall。作者推測:更明確設計成「query expansion」的 prompt 也許有效,但子任務的格式不夠好。
給其他想做 enterprise T2S 的人的免費教訓:學術 SOTA 的技巧 (multi-path generation、self-consistency、task decomposition) 在生產級系統上很可能水土不服 — 不是因為這些技巧不對,而是 (1) 你沒辦法執行 query,(2) 你不能讓 user 等 5 分鐘,(3) 你的 base model 可能已經比學術論文設定的模型強。把 KG 與 retrieval 做好,通常比模型側的花招更值得。
作者宣稱這是第一份完整、公開的 enterprise Text-to-SQL 系統 paper。對於想做企業內部 SQL chatbot 的團隊,這篇是必讀。
9% → 49%
schemas only → Full KG
37% → 78%
C.1 → Full
23% → 1%
schema hallucination 率
34% → 4%
SQL 編譯失敗率
① Eval set 只有 133 題,且全是 domain expert 自己出題、自己評分 — sample size 與 selection bias 都偏小,難跟 Spider/BIRD 直接比。
② Production WAU 300+ 對 LinkedIn 全公司 (~14k 員工) 只是 ~2%,作者並未討論為何不能普及給更多人 — 可能是 60 秒延遲 / 53% 正確率仍是門檻。
③ 所有實驗都是 single run + temperature 0,有 reproducibility 但 J 指標的 variance 無從評估。
④ Paper 把 negative results 寫在 appendix,但這部分對工程實作的價值,可能比正向結果更高。