我曾用一份約一萬列的交易 CSV 做測試,讓系統回答某個名稱一共出現幾筆。模型回答得很肯定,但數字並不正確。
問題不在模型是否具備計數能力,而在一般 RAG 的工作方式通常不適合這類任務。它先把文件切成片段,再找出和問題最相關的前幾個片段交給模型。對「解釋這條規定」或「找出相關段落」很有用,但對計數、加總、找最大值或確認整份資料是否完全不存在某項紀錄,模型看到的往往只是資料的一部分。
遇到這類問題,我採用的原則是:計算路徑交給 deterministic code,語意判斷與結果說明再交給模型。
RAG 提供的是相關片段,不是完整資料視圖
假設 CSV 被切成 200 個片段,而檢索器只取回前 5 個。即使這 5 個片段都與查詢高度相關,也不能代表其他 195 個片段沒有符合條件的資料。
因此,一般檢索式 RAG 不適合直接保證以下答案:
- 某個名稱總共出現幾次。
- 所有符合條件的金額加總是多少。
- 是否完全沒有任何一筆符合資料。
- 全部資料中的最大值、最小值或平均值。
增加 top-k 可以讓模型看到更多片段,但仍沒有完整掃描的保證,也會增加上下文長度與成本。即使整份資料放得進模型的 context window,語言模型對長表格的精確計算仍可能出錯。
這不是說 RAG 完全不能碰結構化資料,而是 retrieval 與完整計算要分工。RAG 可以協助找出欄位定義、規則說明或可能相關的資料集;真正的 aggregation 與 filtering,應由 database query 或程式執行。
讓程式讀取原始資料並回傳可驗證結果
在這個案例中,我讓工具使用 pandas 讀取原始 CSV,依明確條件掃描所有列,最後只把結構化結果交給模型。模型負責把結果解釋成人能理解的文字,不自行重算。
工具回傳內容可以像這樣:
{ "status": "exact_match", "query": "王小明", "rows_scanned": 10000, "matched_rows": 7, "source_version": "transactions-2026-08-20.csv", "normalization": ["NFKC", "trim_whitespace"]}
這種格式有三個好處。第一,計算可以重複執行;第二,模型不必猜測自己看到的資料是否完整;第三,日後可以追查使用哪一版資料與哪一組規則得到結果。
如果資料已經在關聯式資料庫中,通常直接用參數化 SQL 更合適。CSV 工具適合離線檔案或原型驗證,但資料量、併發與更新頻率提高後,仍要評估索引、交易一致性與權限管理。
字串比對前要先定義正規化規則
表面上相同的名稱,實際資料可能包含全形與半形字元、多餘空白、大小寫差異或不同 Unicode 組合。若沒有先正規化,精確比對會漏掉應該算在一起的紀錄。
常見處理包括:
- Unicode NFKC 正規化。
- 去除前後空白,並統一連續空白。
- 對英文字母採一致的大小寫規則。
- 依業務需求處理標點、公司別稱與常見字尾。
繁簡轉換則要更謹慎。繁體轉簡體可能產生多對一的字形合併,簡體轉繁體也可能需要語境判斷。它可以降低部分字形差異,但不能保證所有變體都被正確合併。較安全的做法是保留原始值,另外建立正規化欄位,並讓稽核紀錄能回到原文。
正規化規則本身就是業務邏輯,應有版本、測試案例與變更紀錄。
識別碼應先當字串讀取
帳號、交易序號與客戶編號雖然只包含數字,卻不一定是可計算的數值。如果一開始就由資料工具推斷成整數,前導零可能消失;被推斷成浮點數時,還可能出現科學記號或精度問題。
因此,識別碼欄位應先按字串讀取。只有真正需要加總或比較的金額與數量欄位,才進一步解析成數值。
金融資料的數值解析也要明確處理千分位、貨幣符號、全形數字、空值與會計負數,例如 (1,250)。解析失敗時不應默默轉成零,而應回報異常列數,避免在總和中隱藏資料品質問題。
結果至少要區分精確、疑似與不存在
名稱比對不一定只有符合與不符合兩種狀態。若工具只做精確比對,拼字差異、別名或多餘字尾都可能漏掉;若模糊比對門檻太寬,又會把不同對象合併。
在需要人工判斷的情境中,可以把結果分成三類:
- 精確符合:依已核准的正規化規則可直接判定。
- 疑似符合:相似度或部分欄位接近,但需要人工覆核。
- 未找到:在指定資料版本、欄位與規則下沒有符合紀錄。
第三種尤其要附上查詢範圍,例如掃描了多少列、哪些欄位與哪一版檔案。工具只能說「在這次完整掃描的範圍內未找到」,不能推論現實世界中一定不存在。
這樣的分級也適合制裁名單或客戶名稱初篩,但它不能取代正式的 AML 或 KYC 系統。實務系統還可能需要別名、羅馬拼音、出生日期、國籍、法人關係與風險規則,並由具權責的人員處理疑似結果。
提示詞不能取代工具層的限制
可以在 system prompt 中要求模型遇到計數問題時一定呼叫工具,但提示詞本身不是可靠的執行保證。更穩健的做法是在應用層辨識這類意圖,將問題導向指定工具,並限制模型只能根據工具結果回答。
對高風險操作,可以再加上幾項控制:
- 工具只接受固定欄位與允許的運算。
- 檔案或資料表由伺服器端選定,不接受任意路徑。
- SQL 使用參數化查詢,資料庫帳號採最小權限。
- 工具回傳資料版本、掃描範圍與異常列數。
- 若執行失敗,模型必須明確說明無法完成,不可自行估算。
模型可以理解「使用者想計算什麼」,程式則負責保證「資料以完整且一致的方式完成計算」。
Audit log 不必複製敏感內容
要讓計算可追溯,不代表把整份資料與每次 query 都寫進 log。比較合適的欄位包括:
- 工具與規則版本。
- 資料來源識別碼或雜湊。
- 執行時間、請求識別碼與授權主體。
- 使用的欄位、運算類型與正規化規則。
- 掃描列數、符合列數、異常列數與執行狀態。
對敏感查詢值,可以依稽核需求採遮罩、代碼化或受控雜湊,並限制只有具權限的人員能查閱。日誌設計要同時滿足追查能力與資料最小化,而不是在兩者之間只選一邊。
RAG、程式與模型各自負責什麼
我把這類系統的分工整理成三層:
- RAG:找出可能相關的文件、規則與欄位說明。
- deterministic code:完整執行 filtering、計數、加總與排序。
- LLM:理解自然語言意圖、選擇合適操作,並解釋結果與限制。
這樣的設計不會排除 LLM,反而讓模型專注在它更擅長的工作。當答案需要「每次以相同規則得到相同結果」時,就把那段路徑寫成可以測試、重跑與稽核的程式。
如果現有 RAG 已經在回答計數或加總問題,可以先把這類查詢從紀錄中挑出來,確認模型實際看到了多少資料。只要輸入不是完整資料視圖,就應改由資料庫或程式工具執行。
常見問題
把完整 CSV 放進 full context,就能準確計數嗎?
不能保證。完整上下文可以避免檢索遺漏,但模型仍可能在長表格中漏列或算錯。需要精確計數時,應使用資料庫或程式掃描,模型只負責解釋結果。
「計算交給程式,判斷交給模型」適用哪些任務?
適用於資料篩選、加總、日期區間、路徑搜尋、權限檢查與規則驗證等需要確定性結果的工作。語意分類或模糊比對可由模型協助,但高影響結論仍應有明確規則或人工覆核。
這種工具可以直接拿來做 AML 名稱篩檢嗎?
不建議。簡單的精確與模糊比對只能作為輔助。正式 AML 系統還需要多欄位匹配、名單版本、風險規則、人工覆核、申訴與完整稽核流程。
資料來源與延伸閱讀
關於作者 KJ Huang
KJ Huang(KJH)是來自台灣的軟體工程師與技術主管,擁有超過八年橫跨 AI、區塊鏈、遊戲化、資安與金融的開發及管理經驗,目前投入企業級自架 LLM 平台、RAG 檢索與 AI 治理的實務工作。更多內容請見 kjhuang.com。
本文屬於《銀行裡的 AI 工程》系列。
系列文章:銀行為什麼自架 LLM?、RAG 優化實戰。
English version: Why RAG Cannot Count.
