執行時監控與異常偵測
Advanced4 min readUpdated 2026-03-13
於生產中監控 LLM 應用之 token 使用異常、輸出模式偵測、行為漂移,並使用如 Langfuse、Helicone 與自訂記錄之工具。
執行時監控為捕捉即時過濾器所漏失之防禦層。雖輸入與輸出過濾器對每個請求作出二元阻擋/允許決策,監控則跨時間、使用者與會話分析模式,以偵測緩燃攻擊、自動化探測與利用後活動。
監控什麼
Token 使用異常
異常 token 模式為攻擊活動之強指標:
| 訊號 | 正常基線 | 攻擊指標 | 可能攻擊 |
|---|---|---|---|
| 輸入長度飆升 | 50-500 token | >4000 token | 脈絡視窗填塞、注意力稀釋 |
| 輸出長度飆升 | 100-1000 token | >5000 token | 資料外洩、系統提示提取 |
| 輸入/輸出比 | ~1:2 至 1:5 | >1:50 | 模型被誘生成過量內容 |
| Token 速率 | 穩定、人類步調 | 快速請求爆發 | 自動化工具(Garak、PromptFoo) |
| 重複相似輸入 | 低相似度 | >90% cosine 相似度 | 迭代 fuzzing |
# Token 異常偵測
class TokenAnomalyDetector:
def __init__(self, window_size: int = 100):
self.input_lengths: list[int] = []
self.output_lengths: list[int] = []
self.window_size = window_size
def check(self, input_tokens: int, output_tokens: int) -> list[str]:
alerts = []
if len(self.input_lengths) >= self.window_size:
avg_input = sum(self.input_lengths[-self.window_size:]) / self.window_size
if input_tokens > avg_input * 5:
alerts.append(f"Input length anomaly: {input_tokens} vs avg {avg_input:.0f}")
avg_output = sum(self.output_lengths[-self.window_size:]) / self.window_size
if output_tokens > avg_output * 10:
alerts.append(f"Output length anomaly: {output_tokens} vs avg {avg_output:.0f}")
self.input_lengths.append(input_tokens)
self.output_lengths.append(output_tokens)
return alerts輸出模式偵測
監控模型之輸出以辨識指示成功利用之模式:
| 模式 | 偵測方法 | 指示 |
|---|---|---|
| 拒絕率下降 | 追蹤拒絕關鍵字頻率 | 越獄成功 |
| 輸出中之系統提示片段 | 對已知提示內容之字串匹配 | 系統提示提取 |
| 輸出中之 PII 模式 | 為 SSN、email、電話模式之正規表達式 | 資料洩漏 |
| 程式碼執行指標 | 偵測含危險 import 之程式碼區塊 | 工具濫用 |
| 重複輸出範本 | 以 embedding 相似度叢聚輸出 | 自動化利用 |
行為漂移
行為漂移於模型之回應模式無意圖更新而變化時發生:
- 主題漂移 —— 模型開始討論其預期範圍外之主題
- 語調轉變 —— 模型隨時間變得更遵從或更積極
- 能力擴張 —— 模型開始使用其先前迴避之工具或格式
- 安全退化 —— 跨會話或跨多會話拒絕率下降
監控工具
Langfuse 為捕捉軌跡、指標與評估之開源 LLM 可觀測性平台。
from langfuse import Langfuse
langfuse = Langfuse()
# 追蹤每次 LLM 互動
trace = langfuse.trace(name="chat-completion", user_id=user_id)
generation = trace.generation(
name="main-llm",
model="gpt-4o",
input=user_message,
output=response,
metadata={
"input_tokens": usage.prompt_tokens,
"output_tokens": usage.completion_tokens,
"refusal_detected": "sorry" in response.lower()[:50],
},
)
# 為安全評估評分
trace.score(name="safety", value=safety_score, comment="automated check")安全相關特性:
- 為每請求分析之軌跡層級指標
- 為多輪行為監控之會話追蹤
- 為安全評估管線之自訂分數
- 為視覺化隨時間異常之儀表板
Helicone 提供請求記錄與分析,具需極少程式碼變更之以代理為本之整合。
from openai import OpenAI
# 經 Helicone 代理路由以自動記錄
client = OpenAI(
base_url="https://oai.helicone.ai/v1",
default_headers={
"Helicone-Auth": f"Bearer {HELICONE_API_KEY}",
"Helicone-User-Id": user_id,
"Helicone-Session-Id": session_id,
"Helicone-Property-SecurityCheck": str(passed_security),
},
)安全相關特性:
- 無程式碼變更之自動請求/回應記錄
- 為標記安全相關 metadata 之自訂屬性
- 成本追蹤(異常成本 = 可能利用)
- 為辨識濫用帳戶之使用者層級分析
為最大控制,打造自訂記錄管線:
import json
import hashlib
from datetime import datetime
class SecurityLogger:
def __init__(self, log_sink):
self.sink = log_sink
def log_interaction(
self,
user_id: str,
session_id: str,
input_text: str,
output_text: str,
metadata: dict,
):
record = {
"timestamp": datetime.utcnow().isoformat(),
"user_id": user_id,
"session_id": session_id,
"input_hash": hashlib.sha256(input_text.encode()).hexdigest()[:16],
"input_tokens": metadata.get("input_tokens"),
"output_tokens": metadata.get("output_tokens"),
"input_flagged": metadata.get("input_flagged", False),
"output_flagged": metadata.get("output_flagged", False),
"refusal_detected": metadata.get("refusal_detected", False),
"latency_ms": metadata.get("latency_ms"),
}
self.sink.write(json.dumps(record))何時選擇自訂記錄:
- 你需記錄至特定 SIEM(Splunk、Elastic、Datadog)
- 合規需特定資料處理(無第三方記錄)
- 你需與現有事件回應之即時警報整合
警報策略
有效警報必須於敏感度(捕捉攻擊)與特異性(不以偽警報壓垮操作員)間平衡。
分層警報模型
| 層級 | 嚴重性 | 觸發 | 動作 |
|---|---|---|---|
| P0 | 關鍵 | 已確認資料外洩、輸出中之系統提示 | 呼叫 on-call,自動阻擋使用者 |
| P1 | 高 | 持續注入嘗試、偵測到安全繞過 | 警報安全團隊,標記帳戶 |
| P2 | 中 | Token 異常、拒絕率變化 | 記錄供審查,無立即動作 |
| P3 | 低 | 異常但非威脅性模式 | 儀表板指標、每週審查 |
警報調整
# 範例:為持續注入嘗試之 P1 警報
class InjectionRateAlert:
def __init__(self, threshold: int = 5, window_minutes: int = 10):
self.threshold = threshold
self.window_minutes = window_minutes
self.injection_attempts: dict[str, list[datetime]] = {}
def record_attempt(self, user_id: str) -> bool:
now = datetime.utcnow()
cutoff = now - timedelta(minutes=self.window_minutes)
attempts = self.injection_attempts.get(user_id, [])
attempts = [a for a in attempts if a > cutoff]
attempts.append(now)
self.injection_attempts[user_id] = attempts
if len(attempts) >= self.threshold:
return True # 觸發 P1 警報
return False紅隊意涵
理解監控助紅隊員避免偵測:
- 變化 payload —— 勿重複送出相同攻擊字串;監控將其叢聚
- 調整請求步調 —— 匹配正常使用者流量模式;爆發觸發速率警報
- 使用不同會話 —— 將嘗試散布於會話間以避免每會話升級偵測
- 注意 token 使用 —— 盡可能將輸入與輸出長度保於正常範圍
- 輪換身分 —— 若可能,使用不同 API 金鑰或帳戶以避免使用者層級標記
延伸閱讀
- LLM 應用之縱深防禦 —— 監控於防禦堆疊中之位置
- 速率限制、沙箱化與執行控制 —— 互補之基礎設施控制
- AI 防禦地景 —— 更廣之防禦工具概觀
相關主題
- LLM 應用之縱深防禦 - 監控於防禦堆疊中之位置
- 速率限制、沙箱化與執行控制 - 互補之基礎設施控制
- AI 防禦地景 - 更廣之防禦工具概觀,含監控供應商
- 如防禦方思考 - 理解防禦方如何優先警報與監控
參考資料
- "Langfuse Documentation: LLM Observability" - Langfuse(2025)- 開源 LLM 可觀測性平台之參考文件
- "Helicone: LLM Monitoring and Analytics" - Helicone(2025)- 以代理為本之 LLM 請求記錄與分析文件
- "Detecting Adversarial Attacks on Neural Network Policies with Visual Foresight" - 多位研究者(2024)- 適用於 LLM 監控之異常偵測途徑研究
- "MITRE ATT&CK for Enterprise: Detection" - MITRE(2025)- 適配 AI 系統監控之偵測方法論框架
Knowledge Check
紅隊員於 5 分鐘內自單一使用者帳戶送出 50 個提示注入攻擊變化。全部被輸入過濾器阻擋。何監控訊號將警示安全團隊?