看到 OpenAI 這篇 Inside our in-house data agent,覺得蠻有料的。這不是在推銷產品,而是他們分享自己內部怎麼用 AI Agent 來做數據分析的實戰經驗。

背景: 為什麼要自己造?

OpenAI 內部有 3,500+ 個使用者、70k 個 datasets、600 PB 的資料。光是「找到正確的 table」就是最痛苦的事之一。他們內部同事的原話: 「我們有很多長得很像的 table,我花大量時間搞清楚它們的差異和該用哪一張。有些包含登出用戶,有些不包含;有些欄位重疊,根本分不清楚。」

即使找到正確的 table,要產出正確結果也很難。Analyst 必須理解 table 之間的關係,確保 join、filter 都寫對。常見的 silent failure 包括 many-to-many joins、filter pushdown errors、unhandled nulls,這些錯誤不會報錯但會讓結果是錯的。他們的態度是: analyst 的時間應該花在定義 metrics、驗證假設和做決策,不是花在除錯 SQL。

這個 Agent 能做什麼

這個 Agent 用 GPT-5 驅動,搭配 Codex、Embeddings API 和 Evals API,都是 OpenAI 公開提供的工具。它涵蓋完整的分析流程: 找資料、寫 SQL、跑查詢、產出 notebook 和報告。使用者用自然語言問問題,Agent 端到端處理。

文章裡的範例是: 使用者問「紐約計程車哪些路線最不可靠,typical 和 worst-case 行程時間差距最大的是哪些?」Agent 自己去探索資料、寫 SQL、跑查詢、產生分析結果。

一個關鍵能力是 Agent 會自我修正。它不是一次性產 SQL 就結束,而是會評估中間結果。如果 query 回來 0 筆 (可能是 join 寫錯或 filter 條件不對),它會自己查原因、調整再重試,整個除錯迭代在 Agent 內部完成,不用人介入。

六層 Context 架構

這是我覺得這篇最有價值的部分。一般 text-to-SQL 只拿 schema 就開始生成 SQL,他們堆了六層 context:

1️⃣ Metadata Grounding: schema metadata (欄位名稱、資料型別) 加上 table lineage (上下游關係)。這是基本功

2️⃣ Query Inference: 吃進歷史查詢紀錄,學習哪些 table 通常一起 join、query 怎麼寫。這個很實用,因為很多 SQL 的寫法是「約定俗成」的,光看 schema 推不出來

3️⃣ Human Annotations: 由領域專家寫的 table 和 column 描述,記錄商業含義和已知的坑。這些是機器推不出來的東西

4️⃣ Codex Enrichment: 這層很有意思。他們用 Codex 去爬產生這些 table 的 pipeline 程式碼,從 code 層面理解 table 到底裝了什麼。原文說得好: schema 和 query history 只描述了 table 的「形狀和用法」,但 table 真正的含義是在產生它的程式碼裡。Pipeline 邏輯會告訴你這張 table 的更新頻率、資料範圍、uniqueness、是否排除了特定欄位等細節。例如它能判斷某張 table 是不是只包含 first-party ChatGPT traffic。而且因為是直接爬 codebase,當上游 pipeline code 改了,enrichment 會自動更新,不需要人工維護

5️⃣ Organizational Context: 從 Slack、Google Docs、Notion 抓公司內部知識,像是產品上線紀錄、事故報告、內部代號、指標的定義和計算邏輯等。這些文件會做 embedding 並且帶有權限控制,runtime 透過 retrieval service 存取

6️⃣ Memory: Agent 能記住使用者的修正和在對話中發現的 data nuances。目標是保留那些「非顯而易見但對數據正確性很關鍵」的知識,靠前面五層都推不出來的東西。例如某個 experiment 的 filter 要用特定字串比對 (不是模糊匹配),這種知識只有人告訴它或它踩過坑才知道。Memory 分 global 和 personal 兩個層級,使用者可以手動建立和編輯,Agent 也會在對話中發現有用的 learning 時主動提示你存起來

RAG 架構: 怎麼把六層串起來

這些 context 實際怎麼用? 他們跑一個 daily offline pipeline:

  • 離線階段: 每天跑批次處理,把 table usage、人工標註、Codex enrichment 這些資料整合成統一格式,用 OpenAI Embeddings API 轉成向量存起來
  • 查詢階段: 使用者問問題時,Agent 透過 RAG 只撈出最相關的 context,不用掃全部 metadata 或 log。這樣即使有幾萬張 table,查詢速度和延遲都可以控制住
  • 即時補充: 如果 RAG 撈出來的資訊不夠,或者既有資訊已經過時,Agent 還可以直接對資料倉儲下 live query 即時查詢。它也能跟其他 Data Platform 系統 (metadata service、Airflow、Spark) 溝通,取得倉儲以外的 context

簡單說就是: 預先把所有 context 做好向量索引,查詢時用 RAG 快速定位,不夠再即時補。這是很標準的 RAG 架構,只是他們的 context 層次比一般的豐富很多。而且因為是 daily pipeline,context 索引會自動保持更新。要注意的是,這裡更新的是「幫助 Agent 理解 table 是什麼、怎麼用」的知識層,不是資料本身。要查實際數據時還是直接對資料倉儲下 query。

像隊友一樣協作

Agent 設計成對話式的,能跨 turn 保持完整 context。使用者可以追問、調整方向、中途打斷,不用每次重述背景。如果問題不清楚,Agent 會主動問 clarifying questions;如果沒得到回應,它會套用合理預設值往前推進 (例如沒指定時間範圍就假設最近 7 或 30 天)。

他們還觀察到使用者經常跑重複的分析,所以做了 Workflows 功能,把常見的分析封裝成可重複使用的 instruction sets,例如每週業務報告、table 驗證等。

Eval 怎麼做

用 golden SQL 來評估 Agent 生成的 SQL 是否正確。但不是做字串比對 (因為同一個問題可以有不同寫法的正確 SQL),而是同時比對 SQL 和實際查詢結果,再餵給 OpenAI Evals grader 打分,輸出分數和解釋。這些 eval 像 unit test 一樣在開發期間持續跑、在 production 當 canary,確保每次改動不會 regress。

安全性

Agent 完全繼承既有的權限模型,是 pass-through 的: 使用者只能查自己有權限的 table。沒權限時,Agent 會提示或 fallback 到使用者可以用的替代 dataset。每次回答都會附上推理過程摘要和假設,query 結果會直接連結到底層資料,讓使用者可以 inspect 每一步。

實戰教訓

三個我覺得很值得記住的 lessons:

🔹 工具太多反而害了 Agent: 一開始把所有工具都暴露給 Agent,功能重疊讓 Agent 很困惑。人在工具重疊時可以靠經驗判斷該用哪個,但 Agent 不行。後來精簡合併工具才改善。這在做 Agent 開發時是很常見的坑

🔹 Prompt 太死板反而降低品質: 過度 prescriptive 的 prompting 會把 Agent 推向錯誤路徑。雖然很多分析問題的大致形狀類似,但細節差異夠大,死板的指令反而有害。改成高層級的指引,讓 GPT-5 自己推理選擇執行路徑,結果反而更好。這跟我的經驗一致,越強的模型越適合給高層級指示而不是 step-by-step 的死板指令

🔹 Table 的真正含義在程式碼裡: Schema 和 query history 描述的是 table 的形狀和用法,但 pipeline 邏輯才真正承載了假設、freshness 保證和商業意圖。這是他們用 Codex 爬 codebase 的核心原因

小結

這篇的含金量在於它展示了一個真正 production 等級的 data agent 架構。與其說是 text-to-SQL,更像是一個完整的 data analysis agent,text-to-SQL 只是其中一個環節。六層 context 的設計思路很值得參考,特別是 Codex Enrichment (用 AI 去爬程式碼來理解 table 含義) 和 Memory (累積使用者修正) 這兩層,是跟一般 RAG 架構拉開差距的地方。

而且他們用的 GPT-5、Codex、Embeddings API、Evals API 都是公開工具,這個架構的思路是可以複製的。

原文: Inside OpenAI’s in-house data agent