> ## Documentation Index
> Fetch the complete documentation index at: https://data-machi.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Day 13｜實作：讓 AI 查 Google Sheets，而不是自己猜數字

> 從 Google 服務帳號（Service Account）、試算表權限、欄位對應到 Pandas 計算，建立 Data Machi 的第一個結構化資料工具。

前兩天我們已經把檢索增強生成（RAG）與工具使用（Tool Use）的邊界講清楚：文件適合找「已經存在的知識」，但精確數字、最新狀態與計算結果，應該直接從結構化資料來源取得。今天就把這個觀念落地，讓 Data Machi 第一次真正查詢 Google Sheets。

這一篇的重點不是教你把整張試算表貼進提示詞（Prompt）。剛好相反，我們希望把「資料存取與計算」交給程式，把「理解使用者意圖與整理答案」留給模型。這樣數字才有機會維持一致與可驗證。

## 為什麼需要服務帳號（Service Account）？

如果後端要自動讀取 Google Sheets，不適合依賴個人手動登入。比較穩定的方式，是建立 Google 服務帳號，讓後端以一個機器身分存取指定試算表。

建立服務帳號後，你會取得一組憑證。接著需要啟用對應的 Google API，並把測試試算表分享給服務帳號的電子郵件地址。這一步很容易漏掉：即使憑證本身有效，如果試算表沒有授權給這個帳號，後端仍然讀不到資料。

具體流程大致是：先在 Google Cloud Console 選擇或建立一個 Project，到 API Library 啟用 Google Sheets API（若程式需要依檔名列出試算表，再視需要啟用 Google Drive API）；接著到 IAM 建立一個容易辨識用途的 Service Account，例如 `data-machi-sheets-reader`，第一版只需要讀取指定試算表，不必給它專案管理者權限。建立完成後，在 Keys 頁籤新增一組 JSON Key 並妥善下載保存，再複製這個 Service Account 的 Email，回到匿名測試試算表把這個 Email 加進分享名單，權限先設為 Viewer 即可。

憑證和 Gemini API 金鑰一樣，不應直接提交到 GitHub。本機可以把 JSON 暫放在 `backend/` 並加入 `.gitignore`；更適合正式環境的做法，是把整份 JSON 內容存成一個環境變數：

```env theme={null}
GOOGLE_SERVICE_ACCOUNT_JSON={"type":"service_account",...}
GOOGLE_SHEET_KEY=your_sheet_id
```

部署到 Render 時，同樣建立這兩個 Environment Variables，不要把 JSON 檔案本身上傳到 GitHub。

## 先用匿名資料驗證，不要直接碰正式資料

最適合的第一個測試，是建立一張結構清楚、內容可公開的匿名試算表。例如需求工單資料可以有日期、市場、類別、狀態與處理天數等欄位，內容可以簡單到像下面這樣：

| Request ID | Created Date | Category   | Status      | Owner  |
| ---------- | ------------ | ---------- | ----------- | ------ |
| R001       | 2026-07-01   | Dashboard  | Completed   | User A |
| R002       | 2026-07-03   | Data Query | In Progress | User B |
| R003       | 2026-07-04   | Dashboard  | Completed   | User A |

你應該先確認程式能正確讀到欄位名稱與列數，再開始加入自然語言查詢。

這裡同樣延續前面的原則：**一次只驗證一層。** 先驗證 Google 權限，再驗證資料讀取，接著才驗證篩選與統計。不要一開始就把大型語言模型（LLM）、工具分流與資料權限全部混在一起除錯。如果權限沒設好，通常會遇到 `SpreadsheetNotFound`（Sheet ID 錯誤或尚未分享）或 Permission Denied（已分享但權限不足）；這代表身分驗證成功、但資源授權不足，回頭確認分享名單即可。

## 不要讓大型語言模型自己做精確計算

假設使用者問：「今年哪一個市場的工單最多？」比較可靠的流程不是把所有資料列丟給模型請它自己算，而是先把自然語言需求轉成程式可以理解的條件，再由 Pandas 或其他資料處理程式執行篩選、分組與彙總。

```mermaid theme={null}
flowchart LR
    Q[自然語言問題] --> P[解析篩選條件]
    P --> D[Pandas / 程式計算]
    D --> R[精確結果]
    R --> L[模型整理成回答]
```

模型可以理解「今年」、「市場」、「最多」代表什麼，但真正的計數、加總、平均、排序與比例，應該由可驗證的程式邏輯完成。這個分工是企業分析型代理（Agent）很重要的設計原則。

## 欄位別名：讓使用者不需要知道資料結構

真實資料欄位常常不是人類會使用的語言。例如資料庫裡可能叫 `request_market`、`created_at`、`ticket_category`，使用者卻只會問「市場」、「今年」、「需求類別」。因此工具層通常需要一張欄位別名對照（Alias Mapping），將業務語言映射到真實資料結構（Schema）。

這一層做得好，模型不需要猜欄位；資料欄位未來改名時，也不必重寫整個提示詞。對使用者來說，他仍然可以用平常工作的語言發問。

## 快取不是為了偷懶，而是控制成本與延遲

Google Sheets 不需要每一次對話都完整重新讀取。對更新頻率沒有那麼高的資料，可以設計短時間快取（Cache），降低 API 呼叫與等待時間。不過快取也代表資料可能不是即時，因此快取時間應該根據業務需求決定，而不是一律愈長愈好。

如果使用者問的是「目前最新狀態」，系統也應該有能力選擇重新抓取，而不是盲目沿用舊結果。這個問題之後會在代理記憶與協調者設計中再處理一次。

## 今天要怎麼驗證資料工具真的成功？

至少要測三種問題。第一種是簡單查詢，例如「共有多少筆資料」；第二種是篩選與彙總，例如「今年台灣有多少工單」；第三種是組合條件，例如「今年台灣哪一類工單最多」。

每一次都應該把資料工具的計算結果和試算表人工核對，而不是只看模型最後講得通不通順。可以直接把匿名 Sheet 的原始資料、你問的問題與系統回答放在同一個畫面比對，確認筆數、金額或狀態統計都能被人工重算。當這三層都正確，Data Machi 才真正擁有第一個可驗證的結構化資料工具。

## 實務踩坑｜最新資料、日期與不存在的欄位

實務上有三個很重要的提醒。第一，快取雖然能加快速度，但回答最好保留資料取得時間，讓使用者知道數字是不是最新；如果使用者明確說「我剛更新資料」或「請重新確認」，就應跳過快取重新查詢。第二，「上個月」「最近三個月」「Q1」這些時間語言最好由程式轉成明確日期範圍，而不是讓模型每次自由解讀。第三，如果資料表根本沒有某個欄位，資料工具就應直接回報不存在，而不是自行找一個「看起來很像」的欄位替代。

這三件事都指向同一個原則：**模型可以幫忙理解使用者在問什麼，但事實條件最好被轉成可以驗證的程式規則。**

<Info>
  今天的里程碑是：模型不再負責「猜數字」，而是知道什麼時候把數據問題交給程式計算。
</Info>

下一篇，我們會把視角拉大：企業知識從來不只存在於 Google Sheets 或 PDF。先畫出資料來源的企業知識地圖（Knowledge Map），才能決定下一個工具應該接什麼。
