問題現場
每週都有一大批 Wi-Fi 模組的 issue / topic 文字等著看。一開始我就是手動把它丟給聊天機器人摘要——當下很省事,但這招撐不成流程,兩個問題很快冒出來:
- review 負擔重:文字量大,人工逐筆讀很累。
- 一次性 prompt 不成流程:手動丟一段、這次有用,下週又得重來;變不成穩定、可重複、可維護的東西。
所以目標很清楚:讓 AI 自動為每筆 issue 產出「摘要、標籤、重點」並回寫資料庫,而且要能每週穩定重跑。
最小技術背景
- 資料加值(enrichment):在原始資料上自動補充有用欄位(這裡是摘要、標籤、重點)。
- 設定檔驅動(config-driven):把「用哪個 prompt、處理哪張表 / 哪個欄位、輸出哪些欄位」寫在設定檔,要調整改設定就好,不用改程式。
- 固定欄位 JSON:規定 LLM 只能回固定結構(如
summary_md/tags/key_points),方便驗證與回寫。 - content hash:把內容算成一個指紋,用來判斷「這列跟上次比有沒有變」。
系統架構與資料流
AI 被放進資料管線當一個「加工站」,不是一個要人去聊天的視窗;內容沒變就跳過,不浪費 LLM 呼叫:
flowchart LR
DB["MySQL|weekly issue 列"] --> EN["enrichment 加工站|讀 config"]
EN --> H{"content hash 變了?"}
H -->|否| SKIP["跳過,不叫 LLM"]
H -->|是| LLM["LLM|只回固定欄位 JSON"]
LLM --> WB["回寫 summary / tags / key_points"]
WB --> DB
關鍵設計決策(含取捨)
| 決策 | 選了什麼 | 否決的替代 | 為什麼 |
|---|---|---|---|
| AI 定位 | 當資料庫的 row 加工站 | 當聊天介面,人工逐筆丟 | 否決:一次性、無法重複、之後也維護不了 |
| 設定 | prompt / 表 / 欄位 / 輸出 schema 全externalize 成 config | 寫死在程式裡 | 否決:每次想調一下都得回去改程式碼 |
| 輸出 | LLM 只回固定欄位 JSON | 自由文字回覆 | 否決:難驗證、難回寫,還很容易漂移 |
| 重複控制 | content hash,內容沒變就跳過 | 每次都全量重叫 LLM | 否決:又慢又貴,還白白重算一堆沒變的東西 |
代表性技術證據
設定檔(示意)
table: weekly_issues
input_field: issue_text
prompt_file: prompts/weekly_summary.md
output_schema:
summary_md: text
tags: json
key_points: json
加工迴圈(pseudo-code,示意)
for row in db.rows("weekly_issues"):
h = content_hash(row.issue_text)
if h == row.enrich_hash: # 跟上次比,內容沒變
continue # → 直接跳過,不勞駕 LLM
out = llm.summarize(row.issue_text, schema=OUTPUT_SCHEMA) # 規定它只回固定那幾個欄位
assert_keys(out, ["summary_md", "tags", "key_points"]) # 少一欄就當失敗
db.write_back(row.id, out, enrich_hash=h) # 寫回去,順便記下這次的指紋
踩過的坑
| 欄位 | 內容 |
|---|---|
| 症狀 | 每週重跑都把所有列重新叫 LLM,又慢又花成本 |
| 初判(猜錯) | 本來以為每筆資料每次都在變,重算是應該的 |
| 驗證 | 比對前後內容,發現大多數列其實沒變 |
| 根因 | 沒有「這列沒變就跳過」的機制,每次全量重算 |
| 修法 | 加 content hash,內容沒變就跳過摘要 |
| 預防 | 加「第二次重跑時 LLM 呼叫數接近 0」的測試 |
驗證方式
- 可重複:同一批資料重跑,未變動的列不再呼叫 LLM(content hash 生效)。
- 格式:LLM 回覆缺少必要欄位即視為失敗,不回寫。
- schema 同步:輸出欄位有版本 / migration,欄位變動不會悄悄壞掉。
- 驗收標準:重跑只處理有變動的列;回寫欄位齊全且結構固定。
可複製 SOP:把 AI 做成可重複的資料加工站
適用情境:要對大量資料列,定期、自動地用 AI 補上結構化欄位。
不適用情境:一次性、少量、不需重複的內容,直接對話即可。
前置條件
- 資料在資料庫裡、每列有穩定 id。
- 一份設定檔,集中描述 prompt / 表 / 欄位 / 輸出 schema。
步驟
- 定位成加工站:把 AI 擺進管線、對每一列做固定加工,而不是開個視窗跟它聊。
- 設定外部化:prompt、表、欄位、輸出 schema,全部寫進 config,別寫死在程式裡。
- 鎖輸出:LLM 只准回固定欄位的 JSON,少一欄就算失敗。
- 指紋去重:用 content hash 判斷有沒有變,沒變就跳過、別重算。
- 可回寫、可演進:輸出欄位要能 schema 同步 / migration,之後改得動。
停損點
- 重跑仍全量呼叫 LLM → 停,檢查 content hash。
- 回寫欄位不齊 → 停,先修輸出 schema 約束。
驗收標準
- 重跑只動有變動的列;回寫結構固定、欄位齊全。
回滾:以 enrich_hash 與上一版輸出欄位為基準,可重算或回退。
可複製到:任何「大量資料列要定期用 AI 加值」的場景(摘要、分類、抽取)。
決策回放(三個月後回讀用)
- 背景:每週大量 Wi-Fi 模組 issue 文字,人工 review 重,且一次性 prompt 不成流程。
- 限制:不可外流真實 issue 內容與供應商名;沿用內部 LLM 服務;回寫不可破壞既有欄位。
- 考慮過但放棄:每次都手動丟 prompt 叫它摘要——被「不可重複、不可維護」否決。
- 證據:config 驅動、固定欄位 JSON、content hash 去重、schema migration。
- 未解:摘要品質要人工抽查多少比例;還有跨週的主題趨勢怎麼彙整。
作者備註: 一次性 prompt 很爽,但下週就沒了。把 AI 做成「產線上的一個工站」,它才會變成資產,而不是每次重來的勞動。