昨天談 LLM 評估與 LLM-as-judge,那是實驗室裡的功夫;今天把同一把尺搬到線上——當模型真的在生產環境跑起來,你怎麼看見它、怎麼在它悄悄變笨時第一時間知道。這就是 LLM 可觀測性(observability)。
📖 學
傳統的監控(monitoring)只回答「發生了什麼」:延遲多少、花了多少 token、錯誤率多高、品質分數掉到哪。可觀測性要回答的是「為什麼」——把那些訊號連回到 trace 層級的證據:當下的 prompt、檢索到的 context、模型版本、每一次工具呼叫、每一段 span 與評分。差別在於,一個現代 LLM 請求早就不是單一次 API 呼叫,而是扇出成檢索、工具呼叫、子代理交接、重試的一整棵樹;真正壞掉的那一環,往往埋在三層深、沒人有空點開的 trace 裡。監控告訴你車子在冒煙,可觀測性讓你直接看到是哪個汽缸。
這件事在 2026 年之所以能成形,關鍵是標準統一了。OpenTelemetry 的 GenAI 語意慣例(GenAI Semantic Conventions)由 GenAI SIG 從 2024 年 4 月推進至今,把 LLM 呼叫、代理步驟、向量資料庫查詢、token 用量、成本與品質指標的屬性名稱、型別與列舉值全部標準化。核心概念是用 gen_ai.* 這組屬性把每一次呼叫包成一個 span——模型名稱、輸入輸出 token 數、finish reason 都有固定欄位可填。目前(2026 年 3 月)多數慣例仍是 experimental 狀態,但可以用 OTEL_SEMCONV_STABILITY_OPT_IN 環境變數讓新舊屬性名雙寫,過渡期不至於一次全換。涵蓋範圍已經從單純的 LLM client span,擴到 agent span、內容捕捉(prompt/completion 事件)、MCP 工具呼叫與品質評估,總共六層。Datadog、Honeycomb、New Relic 都已支援;LangChain、CrewAI、AutoGen 這類框架則能原生或透過 instrumentation 套件吐出符合 OTel 的 span。
而昨天講的 LLM-as-judge,在這裡有了新的落點:線上評估(online evaluation)。過去你在 CI 裡對固定資料集跑 judge,現在可以把同一個 rubric 掛成 managed evaluator,對「生產環境真實流量的抽樣 trace」持續打分,把 judge 的判決寫回成 score。Langfuse 就是把 tracing、監控、資料集、實驗與評估串成一個連續迴圈的開源平台,底層直接建在 OpenTelemetry 上,能吃既有的 instrumentation。這代表評估不再是上線前的一次性檢查,而是隨真實使用者互動不斷回收的訊號。
🧠 記
- monitoring 答「發生什麼」,observability 答「為什麼」——前者是聚合指標,後者是可追溯到單筆 trace 的證據。
- 一個請求 = 一棵 span 樹:LLM 呼叫、檢索、工具、子代理、重試各是一段 span,故障通常在深層。
- OpenTelemetry GenAI Semantic Conventions 是 2026 年的事實標準,用
gen_ai.*屬性統一欄位;實驗性階段用OTEL_SEMCONV_STABILITY_OPT_IN雙寫過渡。 - 線上評估 = 把 LLM-as-judge 掛在生產抽樣流量上持續打分,和昨天的離線評估形成閉環。
- 產業現實:73% 企業要求生產環境監控 AI 代理,卻有 63.4% 說缺乏足夠的可觀測性工具——這是缺口,也是機會。
✍️ 實踐
今天動手把一支既有的 LLM 應用接上 OTel + Langfuse,體感一下「看見」的差別。
第一步,裝套件並設好連線。以 Python 為例:
pip install langfuse openinference-instrumentation-openai opentelemetry-sdk
export LANGFUSE_PUBLIC_KEY="pk-..."
export LANGFUSE_SECRET_KEY="sk-..."
export LANGFUSE_HOST="https://cloud.langfuse.com"第二步,用 @observe 把你的函式包起來,並讓 OpenAI 呼叫自動吐 span:
from langfuse import observe, get_client
from openai import OpenAI
langfuse = get_client()
client = OpenAI()
@observe() # 這個函式會變成一個 root span
def answer(question: str) -> str:
resp = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": question}],
)
out = resp.choices[0].message.content
# 把一筆自訂 score 寫回這條 trace(可換成 judge 的判決)
langfuse.score_current_trace(name="has_answer", value=1 if out else 0)
return out
answer("用一句話解釋可觀測性")
langfuse.flush() # 短命腳本記得 flush,否則 span 來不及送出跑完進 Langfuse UI,你會看到這條 trace:輸入輸出、token 數、延遲、成本,以及剛剛那個 has_answer score。第三步才是重點——把離線的 judge 搬上線:在 UI 裡建一個 LLM-as-judge 的 managed evaluator(例如「回答是否切題,1-5 分」),設定對「生產 trace 的 10% 抽樣」自動執行。這樣每天真實流量都會被同一把尺量,品質下滑時你在儀表板上就看得到曲線往下彎,而不是等使用者來客訴。
驗收標準很簡單:能在 trace 樹裡點開最慢的那一段 span、看到當時完整的 prompt 與 context,並且線上 judge score 的時間序列已經開始累積。做到這兩點,你的應用就從「黑盒子」變成「可診斷」。
🔗 延伸學習
- Inside the LLM Call: GenAI Observability with OpenTelemetry
- OpenTelemetry for AI Systems: LLM and Agent Observability (2026) — Uptrace
- Langfuse Docs — Observability & Evaluation
- LLM Observability in Production: Langfuse vs LangSmith vs OpenTelemetry
- AI Observability in Production: Tracing, Evaluating, and Monitoring LLM Applications
💬 問 AI
我有一支正在生產環境運行的 LLM 應用(RAG + 工具呼叫),目前只有基本的
延遲與錯誤率監控。請幫我規劃導入可觀測性的步驟:
1. 用 OpenTelemetry GenAI semantic conventions,我應該為 LLM 呼叫、檢索、
工具呼叫分別打上哪些 gen_ai.* / 自訂屬性?給我一份最小可行的 span 設計。
2. 我想把離線用的 LLM-as-judge rubric 搬成線上評估,對抽樣流量打分。
請說明抽樣比例、成本控制、以及如何避免 judge 本身成為延遲瓶頸。
3. 哪些訊號值得設告警(語意品質、drift、成本),閾值怎麼抓起步值?
請針對 Python 技術棧,並指出常見的踩雷點。