一、什麼是「關鍵事件」
「關鍵事件」是 GPTBots 內建的長程業務記憶能力:在用戶與 Bot 多輪對話過程中,平台會調用 LLM 自動從對話裡識別出有業務價值的事件(如取款、投訴、預約、退款……),按用戶維度結構化儲存下來,並在後續對話中作為上下文回注給 Bot,讓 Bot「記得」這位用戶過去發生了什麼、當前事件處理到哪一步。
解決的核心問題是:
- 跨會話記憶缺失:傳統 LLM 只能看到當前會話的短期記憶視窗,跨會話或長會話中關鍵業務動作被遺忘。
- 結構化資料沉澱:把零散對話沉澱為可查詢、可統計、可稽核的事件流,供風控、客服質檢、用戶畫像複用。
- 狀態推進追蹤:每條事件有
PENDING / IN_PROGRESS / RESOLVED / CLOSED狀態,能夠在多次對話間持續推進。
二、設計理念
1. 把「對話」沉澱為「事件流」
對話是非結構化的,事件是結構化的。關鍵事件把「用戶說過什麼、做過什麼」翻譯成「分類 + 摘要 + 實體 + 狀態 + 優先級 + 置信度」的事件記錄,讓 LLM 之外的下游系統(統計、風控、人工質檢)也能消費這份記憶。
2. 雙軌觸發,避免漏抓也避免狂抓
單次對話裡事件可能在中途出現,也可能在用戶離開之後才需要補抽。系統採用訊息閾值(即時)+ 空閒逾時(批次)+ 手動觸發(兜底)的三級方案,開發者可調參數權衡成本與時效。
3. 預設開啟 LLM 抽取,可降級到便宜模型
事件抽取本身需要 LLM 推理,會消耗 Token。因此抽取模型與 Bot 主對話模型可以獨立配置——例如主對話用 Claude / GPT,抽取用更便宜的小模型,單獨計費、單獨優化。
4. 用戶身份雙鏈路兜底
事件按用戶維度歸集。優先使用開發者透傳的 userId(最高級標識),缺失時回退到平台產生的 anonymousId(如未登入用戶)。即使開發者沒傳 userId,匿名訪客的對話也能完成事件累積。
5. 嚴格隔離用戶作用域,防 LLM 幻覺汙染
LLM 在 UPDATE / DELETE / MERGE 時可能「編造」出別的用戶的 eventId。程式碼內部對每條操作都做 matchesUserScope 校驗,強制把 userId / anonymousId 作為硬過濾條件,防止跨用戶事件汙染。
6. Prompt 注入顯式 + 隱式兩條路徑
- 顯式:Prompt 裡寫
{{key_event_<eventType>}}佔位符,按事件類型精確取值。 - 隱式:未寫佔位符時,自動追加
## Recent Key Events段落到 Prompt 末尾,零配置可用。
三、核心原理
3.1 資料模型
| 角色 | 備註 |
|---|---|
| 關鍵事件主表 | 按用戶/類型/時間多維索引 |
| Bot 級配置(每個 Bot 唯一) | 控制開關、閾值、提取規則 |
| 會話級提取狀態 | 記錄待抽訊息數、空閒時間、並發狀態 |
| 提取執行記錄 | 每次抽取的稽核 + Token / 積分消耗 |
事件主結構(BotEventEntity)核心欄位:
| 欄位 | 含義 |
|---|---|
eventType |
事件分類,與 Bot 配置的字典嚴格一致(如 withdrawal / complaint) |
summary |
事件摘要,≤200 字 |
status |
PENDING(待處理)/ IN_PROGRESS(處理中)/ RESOLVED(已解決)/ CLOSED(已關閉) |
priority |
LOW / MEDIUM / HIGH / CRITICAL |
confidence |
LLM 自評的置信度:HIGH(API 資料)/ MEDIUM(雙方確認)/ LOW(用戶單方聲稱) |
credibilityLabel |
自然語言真實性標籤(「系統 API 確認」/「用戶聲稱待核實」/「雙方確認」) |
disputeFlag |
是否存在矛盾資訊(用戶陳述 ↔ 系統資料衝突) |
entities |
靈活 KV 結構化實體(可存金額、訂單號、時間等) |
relatedEventIds |
關聯事件 ID(典型用於 MERGE 後的來源指針) |
sourceMsgIds |
觸發該事件的訊息 ID 列表 |
createdBy |
來源:LLM / API / UI |
3.2 三級觸發機制
┌── Level 1:即時觸發 ─────────────────┐
│ 每條用戶訊息 +1 計數 │
│ pendingMessageCount ≥ messageThreshold │
│ 立即調 LLM 抽取 │
└──────────────────────────────────────┘
┌── Level 2:空閒觸發 ─────────────────┐
│ 定時掃描(30/60/300 秒一輪) │
│ 命中條件: │
│ - lastMessageTime > idleTimeout 前 │
│ - pendingMessageCount > 0 │
│ - extractionStatus == IDLE │
└──────────────────────────────────────┘
┌── Level 3:手動觸發 ─────────────────┐
│ 調 API: │
│ POST /bot/event/execute/.../retry │
│ 或在執行記錄頁點「重試」 │
└──────────────────────────────────────┘
三個入口最終都會進入同一個 pipeline(BotEventExtractionService.extract),透過 Redis 鎖(bot:event:extract:{botId}:{conversationId},5 分鐘逾時)保證同一會話不會並發抽取。
3.3 提取流水線
1. 校驗開關 → Redis 搶鎖
2. 讀 Track / Redis / c_conversation 三級兜底身份
3. 取自 lastExtractedMessageTime 之後的新訊息(≤100 條)
+ 向上追加 10 條歷史訊息保證語境完整
+ 即時觸發時再裁掉短期記憶視窗尾部(與主對話視窗對齊)
4. 拉取該用戶最近 N 條歷史事件(recentEventCount)
5. 按範本拼 Prompt:
- 用戶自訂提取規則
- 允許的事件分類(name + description)
- 歷史事件(去重比對用)
- 待分析對話
6. 選擇提取模型,下發 JSON Schema(OpenAI 系才生效)
7. 解析 LLM 回傳的 operations 陣列:
CREATE → 新建事件
UPDATE → 推進既有事件狀態/摘要
MERGE → 合併多條冗餘事件
DELETE → 軟刪(用戶撤銷/否定)
8. 跨用戶作用域強制校驗
9. 寫積分消耗(CONSUME_KEY_EVENT 類型)
10. 寫執行記錄 + 重置 Track
3.4 注入機制
模式 A:自動追加(零配置)
當 Bot 啟用關鍵事件,且 Prompt 中未出現 {{key_event_*}} 佔位符時,系統在每次對話調用 LLM 之前,把最近 N 條事件按以下格式自動拼到 Prompt 末尾:
## Recent Key Events
eventType: withdrawal | summary: 用戶申請提現 5000 元 | status: 處理中 | priority: 高 | confidence: 高 | updateTime: 2026-04-28 09:21:33 | entities: {"amount":5000,"channel":"bank"}
eventType: complaint | summary: 用戶投訴客服回應慢 | status: 已解決 | priority: 中 | confidence: 中 | updateTime: 2026-04-27 18:02:11
模式 B:佔位符替換(精確控制)
在 Prompt / 工作流元件 / 規則中寫:
{{key_event_withdrawal}} ← 僅注入「取款」類事件
{{key_event_complaint}} ← 僅注入「投訴」類事件
平台按 eventType 分組產生對應變數,未匹配的事件類型不會被注入。最多注入 30 條 / 變數。
Flow Bot:元件級獨立控制
工作流的每個 LLM 節點都有自己的 FlowKeyEventConfig:可單獨開關、單獨選事件類型、單獨設 recentEventCount(預設 5 條)。同一會話內事件只查一次(快取在 ChatContext),多個節點共享資料。
四、使用指南
4.1 在 Bot 配置面板啟用
進入路徑:開發者控制台 → Bot 詳情 → 用戶管理(User Manage) → 「關鍵事件」抽屜
操作步驟:
- 開啟總開關
- 提取模型:可選項;不選時使用 Bot 預設對話模型。建議選一個便宜模型(例如 GPT-4o-mini / Haiku 系列)。
- 提取規則(≤2000 字元):用自然語言告訴 LLM 這個 Bot 場景下「什麼算關鍵事件」。例:只抽取與資金相關的業務動作(取款、存款、轉帳、退款)。 忽略閒聊和情緒表達。 實體欄位必須包含金額(amount)、幣種(currency)、訂單號(orderId)。
只抽取與資金相關的業務動作(取款、存款、轉帳、退款)。 忽略閒聊和情緒表達。 實體欄位必須包含金額(amount)、幣種(currency)、訂單號(orderId)。此代碼塊在浮窗中顯示 - 最近事件數(0
50):每次對話注入 Prompt 的事件數。0 表示不注入,常見 510。 - 觸發時機:
- 訊息閾值(5~50):預設 10。
- 空閒逾時(2~60 分鐘):預設 3。
- 事件分類字典(最多 10 個):每個分類含「名稱」(≤10 字)和「描述」(≤100 字,告訴 LLM 這個分類裝什麼)。
- 點儲存。
⚠️ 警告:分類名一旦上線就不要隨意改名 —— 歷史事件依然存的是舊名字,會出現
{{key_event_<舊名>}}取不到值的情況。前端在分類已存在時會彈出橙色警示。
4.2 在 Prompt 中引用事件
通用 Bot Prompt
你是一個資金客服助手。
【該用戶最近的資金動作】
{{key_event_withdrawal}}
【該用戶最近的投訴】
{{key_event_complaint}}
請基於上述上下文回答用戶問題。
Flow Bot 元件 Prompt
- 在畫布中點擊 LLM 驅動的節點 → 設定面板找到「記憶-關鍵事件」配置。
- 勾選
enable,選擇當前節點要注入的事件類型,設定召回的最近事件數(預設 5)。
4.3 監控提取執行記錄
進入路徑:開發者控制台 → Bot 詳情 → 用戶管理 → 執行記錄頁籤
可看到的資訊:
- 每次抽取的狀態(PENDING / RUNNING / COMPLETED / FAILED)
- 觸發來源(REALTIME / SCHEDULED / MANUAL)
- 處理訊息數 / 抽取出事件數
- Token 消耗 / 積分消耗
- 失敗原因 + 「重試」按鈕
- 詳情抽屜:列出本次抽取產生 / 修改的所有事件
4.4 帳單與計費
關鍵事件的 LLM 調用費用計入帳單的 關鍵事件 項,與對話主流程的扣費分開統計,方便單獨控制成本。
五、典型應用場景
| 場景 | 事件類型範例 | 價值 |
|---|---|---|
| 金融 / 出海支付客服 | withdrawal 取款 / deposit 存款 / kyc 身份認證 / dispute 爭議 |
跨會話追蹤資金動作;風控與人工坐席接管時一眼看到該用戶的歷史業務流 |
| 電商售後 | refund 退款 / return 退貨 / complaint 投訴 |
自動維護用戶售後狀態機,多次對話中持續推進 |
| 預約 / 排程 | appointment 預約 / cancellation 取消 |
讓 Bot 記得用戶改過幾次時間、當前確認的是哪個時段 |
| HR / 內部 IT 助手 | leave_request 請假 / it_ticket 工單 |
把對話沉澱為可查詢的工單流 |
| 教育 / 學習陪伴 | homework_submission / quiz_score / weak_topic |
長期記錄學生學習狀態,產生個人化複習計畫 |
| 醫療 / 健康諮詢 | symptom 症狀 / medication 用藥 / appointment 複診 |
跨次諮詢保留病程資訊,提升問診連貫性 |
六、最佳實踐
✅ 配置層
- 分類字典寫描述——
name+description都要填。LLM 主要靠description判斷「這條對話是不是這個分類」。description留空會顯著降低分類準確率。 - 分類數量控制在 5~10 個。太多會讓 LLM 抽取時糾結歸類,且 Prompt 體積膨脹。同義類合併(「取款」 和 「提現」 用一個)。
- 抽取規則要寫「做什麼」也要寫「不做什麼」。例如:只抽取已確認完成或正在進行的業務動作。 排除:假設性討論(「如果...怎麼辦」)、純情緒、閒聊。
只抽取已確認完成或正在進行的業務動作。 排除:假設性討論(「如果...怎麼辦」)、純情緒、閒聊。此代碼塊在浮窗中顯示 - 抽取模型選小不選大。抽取是結構化輸出任務,對推理能力要求低。GPT-4o-mini / Claude Haiku / DeepSeek-V3 通常夠用,單次成本可比主對話模型低一個數量級。
- 不要一開始就把
recentEventCount拉滿。注入太多事件會擠占主對話上下文。從 5 起步,發現 Bot 經常「想不起來」再加。
✅ 觸發參數
- 長會話 / 客服場景:
messageThreshold = 10、idleTimeoutMinutes = 3一般合適。 - 短互動 / 任務型 Bot:把
idleTimeoutMinutes調到 2,避免用戶對話結束後事件抽取遲遲不發生。 - 高頻低價值對話(如普通問答):
messageThreshold提到 20~30,避免每輪都跑 LLM 抽取燒成本。
✅ Prompt 引用
- 優先用佔位符而不是依賴自動追加。佔位符可控、可按類型精確切片,自動追加適合「什麼都想要」的兜底場景。
- Flow Bot 中不要每個節點都啟用。只在真正需要事件上下文的節點(如客服回覆節點、風控判斷節點)啟用,意圖識別 / 路由節點沒必要。
- 避免
{{key_event_xxx}}出現在系統級 Prompt 頂部——歷史事件往往會隨時間增長,如果它撐爆 Token,主指令會被截斷。建議放在 Prompt 中段或 Few-shot 之前。
✅ 資料治理
- 定期人工 review LOW 置信度事件。LLM 把「用戶單方聲稱」的內容也會抽出來,業務方應該過濾一遍——可以按
confidence=LOW+disputeFlag=true篩查。 - 重要業務流配合 API 寫入。如訂單系統已經有結構化資料時,直接
createdBy=API寫入比讓 LLM 從對話裡抽取更準確,與 LLM 抽取結果共存。 - MERGE 操作小心使用。LLM 偶爾會把不該合併的事件合併掉。建議在執行記錄裡關注 MERGE 類操作,必要時透過 API 拆分恢復。
- 善用
entities欄位。在抽取規則裡明確要求 LLM 抽出關鍵 KV(金額、訂單號、時間等),後續可直接結構化查詢,比解析 summary 文字可靠。
⚠️ 排查清單
| 現象 | 排查路徑 |
|---|---|
| 事件沒抽出來 | ① 總開關是否開 ② Bot 是否有積分餘額 ③ 執行記錄是否有 FAILED ④ 提取規則是否過嚴 |
| 某類型關鍵事件內容為空 | ① 該用戶是否有該類型事件 ② 是否正確建立該類型的事件 ③ 分類名拼寫是否一致 |
| 跨用戶串擾 | 檢查是否傳了正確的 userId;如未登入用戶,檢查 anonymousId 是否穩定 |
| 抽取費用偏高 | ① 降低提取頻率 ② 切換更便宜的提取模型 |
| 抽取結果亂歸類 | ① 給分類更準確的描述資訊 ② 在提取規則欄裡給若干 few-shot 範例 |
七、能力邊界與注意事項
- 抽取不是即時的。即使是 Level 1 即時觸發,也是在訊息累計到閾值後才抽。嚴格強一致的業務(如交易)不能依賴事件流來下決策——事件是輔助記憶,不是真理之源。
- 抽取視窗最多 100 條訊息(
MAX_MESSAGES_PER_BATCH)。超長會話被切成多個視窗處理,跨視窗的因果關係靠「歷史事件比對」召回。 - 事件查詢有 500ms 逾時保護。慢查詢不會拖慢聊天鏈路,但極端情況下會無事件注入。
- 匿名 ID 在端清理後會重置。匿名用戶切換裝置 / 清快取後視為新用戶,事件不會跟隨。
- multi-agent 模式下事件流不參與(參見 oversea-ailab CLAUDE.md 的廢棄聲明)。
