Agent 如何整理資料洞察?先分群,再讓模型命名
想讓 Agent 從客服對話找出產品問題,需要先整理資料與群組證據,再讓模型提議名稱。用 DBSCAN 互動圖解與 SDK 結構化輸出,分清分群、命名與人工判斷的責任。
本文目錄
把累積的對話整理成產品問題,是 Agent 可以協助的工作之一,也能幫助團隊決定先處理哪一類需求。這項功能需要一條可檢查的資料流:哪些片段被放在一起、群組名稱根據什麼,以及少數但重要的問題有沒有被漏掉。
假設客服每天收到「忘記密碼」、「一直登入失敗」、「驗證信沒有寄來」等對話。關鍵字規則能各自歸類,但產品團隊可能想知道:這些是不是同一個帳號流程的問題?當訊息改成「換手機後就進不去了」,字面比對又可能漏掉。
如果產品提供「整理本週客服問題」的 Agent 功能,分群能幫忙整理候選問題,卻不能直接證明共同根因。登入失敗也可能來自停權、網路中斷或瀏覽器設定。工程上要把「文字相近」與「原因相同」分成兩個判斷,否則一個看似漂亮的群組,會讓團隊修錯地方。
先決定每個點代表什麼
資料流可以拆成:選取對話片段、移除不必要的個資、產生 embedding、計算距離、分群、挑出代表片段,再由人或模型提議群組名稱。每一步都會改變結果。
如果每個點是一整場對話,登入、付款、退貨可能擠在同一個向量裡;如果切得只剩「還是不行」,又會失去對話脈絡。對客服問題整理,我會先以一個可理解的問題片段作為單位,保留必要的前一句與事件類型。這是資料集的設計決定,不是演算法能自動補救的資訊。
向量也需要版本。記錄 embedding 模型、切分規則與資料時間範圍,才能判斷新一批群組改變,是使用者真的遇到新問題,還是前處理被改過。不同模型產生的向量不應直接混在同一個距離空間,舊資料要重算或分開處理。
依資料空間設定分群條件
相近有多近?先用平面理解密度
教學圖解採用 DBSCAN:對每個點找出半徑 eps 內的鄰居,數量達到 minPts 就是核心點;核心點可向外擴展群組,鄰近但不夠密集的點可能是邊界點,其餘點保留為雜訊。這個例子把點本身算在鄰居數裡。密度連結、核心點與邊界點的定義來自 DBSCAN 原始論文。
調整鄰域半徑 eps 與 minPts,看看核心點能不能擴展成群,以及哪些點仍是雜訊。
用 eps = 4、minPts = 3 實際執行小型 DBSCAN,得到 2 群與 2 個雜訊點。雜訊表示未滿足這組密度條件,不表示內容沒有價值。
- 群數
- 2
- 雜訊點
- 2 / 10
- 距離計算
- 二維歐氏距離
數字為點編號;圓點為群 1,方形為群 2,叉號為雜訊。其他群組保留群編號。座標是人工設計的教學資料。
查看每個點的座標與分群
| 點 | 內容 | 座標 | 結果 |
|---|---|---|---|
| 1 | P1 | (18, 24) | 群 1 |
| 2 | P2 | (22, 24) | 群 1 |
| 3 | P3 | (22, 28) | 群 1 |
| 4 | P4 | (26, 24) | 群 1 |
| 5 | P5 | (64, 60) | 群 2 |
| 6 | P6 | (68, 60) | 群 2 |
| 7 | P7 | (68, 64) | 群 2 |
| 8 | P8 | (72, 60) | 群 2 |
| 9 | P9 | (46, 46) | 雜訊 |
| 10 | P10 | (90, 12) | 雜訊 |
- 01找鄰居完成
距離 ≤ 4,並且把自己算進去。
- 02判定核心點完成
至少 3 個鄰居,才可以從這裡擴展。
- 03擴展與邊界完成
先被標成雜訊的點,若後來落在核心點鄰域,可提升為邊界點。
圖中的資料只用來說明流程,不是實際服務的測試結果。 圖中使用二維歐氏距離,eps 單位就是座標單位;不是文字 embedding 或降維後語意品質。minPts 含點本身,邊界距離等於 eps 也算鄰居。
操作圖解時,先固定 minPts,慢慢增加 eps,觀察原本分開的點群何時合併,以及雜訊點何時加入群組。再固定 eps,提高 minPts,觀察群組與雜訊結果如何改變。圖中的座標與距離都是合成平面單位,不能把滑桿數字當成正式 embedding 的門檻;文字摘要提供同一組分群結果,不需要只靠顏色辨識。
下面這段 TypeScript 只示範鄰居查詢與核心點判斷,完整分群還需要擴展群組、避免重訪,以及處理原先標為雜訊的邊界點:
type Point = { id: string; x: number; y: number };
function neighbors(points: Point[], p: Point, eps: number) {
return points.filter(q =>
Math.hypot(p.x - q.x, p.y - q.y) <= eps
);
}
function isCore(points: Point[], p: Point, eps: number, minPts: number) {
// 距離自身為 0,因此 p 也計入鄰居數。
return neighbors(points, p, eps).length >= minPts;
}
DBSCAN 不需要預先指定群組數,但仍有密度假設。兩個主題之間若有足夠密集的連接點,可能被合併;稀少但重要的問題,則可能留在雜訊裡。雜訊是「目前參數下不屬於群組」,不表示內容沒價值。少數人的付款失敗,仍然可能比大量重複詢問更值得追查。
正式向量空間不能照抄平面參數
文字 embedding 常用餘弦相似度描述向量方向:cos(a, b) = (a · b) / (||a|| × ||b||)。距離則可以定義成 1 - cos(a, b)。這個定義與上圖的歐幾里得距離不同,數值範圍與尺度不能互換;零向量也無法用這個公式計算,需要先檢查輸入。
如果向量已經正規化為單位長度,平方歐幾里得距離與餘弦相似度具有 ||a - b||² = 2 - 2cos(a, b) 的關係。這能幫助理解兩種度量,但不會替你找出適合任務的門檻。付款與退款在文字上可能接近,客服路由卻可能需要把它們分開。
把高維向量壓成二維散佈圖,適合檢查與溝通,卻不能保證原有鄰近關係都保留。正式分群應在選定的向量空間進行,圖面只展示結果。不能看到兩個點在畫面上靠近,就反推它們在原始空間的距離。
用證據支撐群組命名
群組名稱要能回到原始證據
分完群之後,模型可以根據代表片段提議「驗證流程卡住」等名稱。這一步有另一種風險:模型可能把各種登入問題說成「帳號安全意識較低的使用者」,從問題分類跳成對人的推測。群組名稱應描述可觀察的問題,附上代表片段,讓讀者檢查命名是否涵蓋群內內容。
資料表可以保留 clusterRunId、成員片段 ID、命名版本與人工修正紀錄。重跑時產生的新群組編號沒有穩定語意,不能把「群組 3」當成永遠相同的產品類別。要比較兩次結果,應比較成員重疊、代表問題與人工判斷。
涉及使用者資料時,查詢權限與租戶隔離要在取樣前生效。不能先把所有人的向量混合,分群完成後才期待群組名稱不洩漏資料。保留期限也應包含向量與衍生群組,刪掉原對話卻留下可追溯的摘要,並沒有完成資料移除。
讓 SDK 負責命名,資料管線負責分群
OpenAI Agents SDK(@openai/agents)可以用 Agent 的 outputType 定義結構化輸出,執行後從 result.finalOutput 取得資料。放到這條流程裡,適合讓 Agent 根據已選好的代表片段,回傳群組名稱、描述與證據 ID,供產品介面展示。OpenAI:Agent definitions
例如,把模型的任務縮到替一組已完成分群的片段命名。以下只展示輸出形狀;representativeFragments 是應用程式先完成去識別化與權限檢查的資料:
import { Agent, run } from "@openai/agents";
import { z } from "zod";
const namingAgent = new Agent({
name: "問題群組命名",
instructions: "用臺灣繁體中文描述共同問題,只引用輸入中的片段 ID。",
outputType: z.object({
label: z.string(),
summary: z.string(),
evidenceIds: z.array(z.string()),
}),
});
const result = await run(namingAgent, JSON.stringify(representativeFragments));
const proposedName = result.finalOutput;
這個介面承接的是命名工作。embedding、DBSCAN、資料版本與群組成員仍由應用程式管理;不能因為接上 Agent,就把整條分群流程當成 SDK 內建能力。結構化輸出也只約束資料形狀,產品仍要檢查證據 ID 是否屬於這次輸入、名稱是否涵蓋群內問題,才能把建議交給團隊使用。OpenAI:Agent definitions
如何知道這批群組值得使用
我會準備一組經人工檢查的問題片段,包含不同說法的相同問題、文字相近但目的不同的問題,以及少數案例。驗證分成兩層:成員是否合理地放在一起,以及群組是否真的有助於客服分派或產品排程。群內距離較小,只能支持前一層的一部分。
參數驗證也需要看變動。稍微調整 eps 或 minPts 就大量合併的群組,不適合直接作為固定分類。觀察雜訊比例、重要少數案例與抽樣誤分,記錄哪個版本被採用及理由。若人工仍必須逐筆拆開群組,分群可能沒有節省足夠的整理成本。
圖解讓我們看到一個可檢查的事實:同一批點,參數一改就可能得到不同分群。正式系統的下一步,是確認哪一種結果能回答當初的產品問題,而不是替每個群組取一個聽起來合理的名字。
延伸閱讀
- DBSCAN 原始論文:核心點、密度連結與雜訊的定義。
- OpenAI Agents SDK:Agent definitions:設定命名任務與結構化輸出。
SDK 文件參考日期:2026-10-07。