實(shí)踐:基于觀測(cè)云構(gòu)建AgentOps運(yùn)維體系)
1. 為什么 LLM 應(yīng)用上線后反而更讓人睡不著覺(jué)做過(guò)傳統(tǒng)后端服務(wù)的同學(xué)大概都有個(gè)共識(shí)服務(wù)上線之后只要 CPU、內(nèi)存、QPS、錯(cuò)誤率這幾條曲線不飄晚上基本能睡個(gè)安穩(wěn)覺(jué)。但換成 LLM 應(yīng)用和 AI Agent這套經(jīng)驗(yàn)幾乎全部失效。我見(jiàn)過(guò)太多團(tuán)隊(duì)接口成功率 99.9%平均響應(yīng) 300ms監(jiān)控大盤一片綠結(jié)果用戶投訴不斷——回答答非所問(wèn)、工具調(diào)用莫名其妙失敗、多輪對(duì)話到第三輪就開(kāi)始胡言亂語(yǔ)、賬單一天燒掉幾百美金卻查不出是哪條鏈路在漏。這就是 LLM 與 AI Agent 可觀測(cè)實(shí)踐要解決的核心問(wèn)題傳統(tǒng) APM 看得見(jiàn)服務(wù)活著但看不見(jiàn)智能體是否在做正確的事?;谟^測(cè)云搭建 AgentOps 運(yùn)維體系本質(zhì)上就是把可觀測(cè)的邊界從基礎(chǔ)設(shè)施 應(yīng)用性能擴(kuò)展到模型行為 智能體決策鏈路 Token 成本這一整條新維度上。這篇文章適合三類人一是正在把 LLM 能力接入生產(chǎn)系統(tǒng)的后端和平臺(tái)工程師二是負(fù)責(zé) AI Agent 從 0 到 1 搭建、需要為線上穩(wěn)定性兜底的開(kāi)發(fā)同學(xué)三是技術(shù)負(fù)責(zé)人想搞清楚 AgentOps 到底要觀測(cè)哪些指標(biāo)、怎么落地、值不值得投入。我會(huì)從整體設(shè)計(jì)思路講到具體埋點(diǎn)、指標(biāo)建模、鏈路追蹤、成本歸因再到踩過(guò)的坑和排查技巧盡量給到可以直接抄作業(yè)的方案。先說(shuō)清楚一個(gè)概念邊界因?yàn)闊嵩~里很多人問(wèn)agent 和 llm 和 ai 模型有什么區(qū)別。LLM 是底層的大語(yǔ)言模型負(fù)責(zé)理解和生成AI Agent 是在 LLM 之上加了一層感知—規(guī)劃—行動(dòng)—記憶的循環(huán)結(jié)構(gòu)它能調(diào)用工具、訪問(wèn)外部數(shù)據(jù)、做多步?jīng)Q策。所以 LLM 的可觀測(cè)關(guān)注的是單次推理的質(zhì)量與成本而 Agent 的可觀測(cè)要復(fù)雜得多它要追蹤一整條決策鏈路上每一步的輸入輸出、工具調(diào)用、狀態(tài)流轉(zhuǎn)。AgentOps 就是把這套運(yùn)維方法論工程化觀測(cè)云則是承載這套體系的平臺(tái)底座。2. AgentOps 觀測(cè)體系的整體設(shè)計(jì)與選型思路2.1 傳統(tǒng)可觀測(cè)三支柱為什么不夠用傳統(tǒng)可觀測(cè)性建立在 Metrics、Logs、Traces 三支柱上。放到 LLM 場(chǎng)景里這三根柱子都出現(xiàn)了維度缺失。Metrics 層面?zhèn)鹘y(tǒng)指標(biāo)是數(shù)值型的、低基數(shù)的比如請(qǐng)求數(shù)、延遲分位。但 LLM 的關(guān)鍵指標(biāo)很多是語(yǔ)義型的——回答相關(guān)性、幻覺(jué)率、工具選擇準(zhǔn)確率這些沒(méi)法用簡(jiǎn)單的計(jì)數(shù)器表達(dá)。Logs 層面一次 Agent 調(diào)用產(chǎn)生的日志量可能是普通接口的幾十倍因?yàn)槊恳徊酵评淼?prompt、completion、工具返回都要記錄而且這些內(nèi)容是非結(jié)構(gòu)化的長(zhǎng)文本直接塞進(jìn)日志系統(tǒng)會(huì)爆炸。Traces 層面?zhèn)鹘y(tǒng)鏈路追蹤假設(shè)調(diào)用是確定性的、有明確父子關(guān)系但 Agent 的決策是動(dòng)態(tài)的它可能循環(huán)調(diào)用、可能并行調(diào)用多個(gè)工具、可能中途改變計(jì)劃鏈路結(jié)構(gòu)每次都不一樣。所以 AgentOps 體系的設(shè)計(jì)核心是在三支柱之上補(bǔ)一層語(yǔ)義觀測(cè)層專門處理 LLM 特有的輸入輸出、Token 計(jì)量、工具調(diào)用語(yǔ)義、會(huì)話上下文這些內(nèi)容。2.2 觀測(cè)云作為底座的能力匹配選觀測(cè)云做這套體系的底座主要看中幾個(gè)能力。第一是它支持 OpenTelemetry 標(biāo)準(zhǔn)協(xié)議這意味著 LLM 生態(tài)里主流的埋點(diǎn)方案比如 OpenLLMetry、OpenInference 這類基于 OTel 的 SDK可以無(wú)縫接入不用被廠商鎖定。第二是它對(duì)高基數(shù)標(biāo)簽和非結(jié)構(gòu)化數(shù)據(jù)的處理能力Agent 的 trace 里天然帶大量高基數(shù)屬性比如 session_id、user_id、tool_name、model_name傳統(tǒng)時(shí)序庫(kù)扛不住觀測(cè)云的存儲(chǔ)模型更適合。第三是它把指標(biāo)、日志、鏈路、事件放在同一個(gè)數(shù)據(jù)平面里做關(guān)聯(lián)分析排查問(wèn)題時(shí)可以從一條異常 trace 直接下鉆到對(duì)應(yīng)的日志和指標(biāo)不用在多個(gè)系統(tǒng)之間來(lái)回跳。這里要強(qiáng)調(diào)一個(gè)選型原則AgentOps 平臺(tái)必須支持自定義語(yǔ)義指標(biāo)的上報(bào)。因?yàn)槊總€(gè)業(yè)務(wù)對(duì)好回答的定義不一樣客服場(chǎng)景看重解決率代碼助手場(chǎng)景看重編譯通過(guò)率這些指標(biāo)只能業(yè)務(wù)自己定義平臺(tái)要能靈活接收。2.3 分層架構(gòu)設(shè)計(jì)我把整套體系分成四層從下往上依次是采集層、傳輸層、存儲(chǔ)計(jì)算層、應(yīng)用層。采集層負(fù)責(zé)在 LLM 調(diào)用和 Agent 執(zhí)行的關(guān)鍵節(jié)點(diǎn)埋點(diǎn)包括模型推理、工具調(diào)用、會(huì)話管理、成本計(jì)量。傳輸層用 OTel Collector 做統(tǒng)一匯聚和預(yù)處理比如脫敏、采樣、字段裁剪。存儲(chǔ)計(jì)算層由觀測(cè)云承擔(dān)做指標(biāo)聚合、鏈路存儲(chǔ)、日志索引。應(yīng)用層是最終呈現(xiàn)的儀表盤、告警規(guī)則、根因分析視圖。這個(gè)分層的好處是每層職責(zé)單一采集層只管采全傳輸層只管過(guò)濾和路由存儲(chǔ)層只管存和算應(yīng)用層只管看和告警。任何一層要換方案不影響其他層。比如后面想把某個(gè)模型供應(yīng)商換成另一個(gè)只需要改采集層的適配器上層完全無(wú)感。3. 核心觀測(cè)指標(biāo)建模與埋點(diǎn)實(shí)操3.1 LLM 調(diào)用層的關(guān)鍵指標(biāo)單次 LLM 調(diào)用要采集的指標(biāo)我整理成下面這張表這是整個(gè)體系最基礎(chǔ)的數(shù)據(jù)源。指標(biāo)類別具體指標(biāo)采集方式用途性能首 Token 延遲 TTFTSDK 埋點(diǎn)衡量用戶感知速度性能端到端延遲SDK 埋點(diǎn)衡量整體響應(yīng)性能輸出 Token 速率計(jì)算得出衡量生成效率質(zhì)量輸入/輸出 Token 數(shù)API 返回成本計(jì)量基礎(chǔ)質(zhì)量完成原因 finish_reasonAPI 返回判斷是否被截?cái)噘|(zhì)量重試次數(shù)SDK 埋點(diǎn)衡量穩(wěn)定性成本單次調(diào)用費(fèi)用按 Token 單價(jià)計(jì)算成本歸因異常錯(cuò)誤碼與錯(cuò)誤類型SDK 埋點(diǎn)故障排查TTFT 這個(gè)指標(biāo)特別重要很多人只盯端到端延遲但流式輸出場(chǎng)景下用戶真正感知的是第一個(gè)字什么時(shí)候出來(lái)。我實(shí)測(cè)過(guò)一個(gè)案例端到端延遲 8 秒但 TTFT 只有 400ms用戶體感是很快另一個(gè)端到端 5 秒但 TTFT 3 秒用戶體感是卡死了。所以這兩個(gè)指標(biāo)必須分開(kāi)看。埋點(diǎn)的時(shí)候有個(gè)細(xì)節(jié)finish_reason 一定要記錄。如果大量請(qǐng)求的 finish_reason 是 length說(shuō)明輸出被 max_tokens 截?cái)嗔擞脩裟玫降幕卮鹗遣煌暾牡涌趯用媸浅晒Φ膫鹘y(tǒng)監(jiān)控完全發(fā)現(xiàn)不了。這個(gè)坑我踩過(guò)線上投訴回答說(shuō)到一半就沒(méi)了查了半天才發(fā)現(xiàn)是參數(shù)配置問(wèn)題。3.2 Agent 決策鏈路的關(guān)鍵指標(biāo)Agent 比 LLM 復(fù)雜的地方在于多步?jīng)Q策所以要額外采集這些指標(biāo)。步數(shù)分布一次任務(wù)平均走多少步步數(shù)突然飆升往往意味著 Agent 陷入循環(huán)工具調(diào)用成功率按工具名分組統(tǒng)計(jì)某個(gè)工具失敗率上升要立刻告警工具選擇準(zhǔn)確率需要人工標(biāo)注或規(guī)則校驗(yàn)衡量 Agent 是否選對(duì)了工具循環(huán)檢測(cè)相同工具 相同參數(shù)連續(xù)調(diào)用超過(guò)閾值就標(biāo)記異常上下文長(zhǎng)度增長(zhǎng)曲線多輪對(duì)話里上下文膨脹速度直接關(guān)系到成本和截?cái)囡L(fēng)險(xiǎn)任務(wù)完成率端到端任務(wù)是否達(dá)成目標(biāo)這是最貼近業(yè)務(wù)的指標(biāo)工具調(diào)用成功率我建議按tool_name做維度拆分因?yàn)椴煌ぞ叩姆€(wěn)定性差異很大。有一次線上問(wèn)題整體成功率 97% 看著正常但拆開(kāi)看某個(gè)查詢工具成功率只有 60%被其他穩(wěn)定工具的平均值掩蓋了。3.3 埋點(diǎn)代碼實(shí)操以 Python 生態(tài)為例用 OTel 的 SDK 做埋點(diǎn)核心是給 LLM 調(diào)用和工具調(diào)用各包一層 span。下面是我常用的埋點(diǎn)骨架。from opentelemetry import trace from opentelemetry.trace import Status, StatusCode tracer trace.get_tracer(agent.ops) def traced_llm_call(model, messages, **kwargs): with tracer.start_as_current_span(llm.call) as span: span.set_attribute(llm.model, model) span.set_attribute(llm.input_tokens, count_tokens(messages)) span.set_attribute(llm.request.messages, truncate(messages, 2000)) try: resp call_model(model, messages, **kwargs) span.set_attribute(llm.output_tokens, resp.usage.output_tokens) span.set_attribute(llm.finish_reason, resp.finish_reason) span.set_attribute(llm.cost, calc_cost(model, resp.usage)) span.set_attribute(llm.response, truncate(resp.text, 2000)) return resp except Exception as e: span.set_status(Status(StatusCode.ERROR, str(e))) span.record_exception(e) raise工具調(diào)用的埋點(diǎn)類似但要額外記錄工具名、入?yún)?、出參、耗時(shí)。def traced_tool_call(tool_name, tool_fn, args): with tracer.start_as_current_span(agent.tool) as span: span.set_attribute(tool.name, tool_name) span.set_attribute(tool.args, truncate(str(args), 1000)) try: result tool_fn(**args) span.set_attribute(tool.success, True) span.set_attribute(tool.result, truncate(str(result), 1000)) return result except Exception as e: span.set_attribute(tool.success, False) span.set_status(Status(StatusCode.ERROR, str(e))) raise注意prompt 和 completion 里極可能包含用戶隱私和密鑰信息埋點(diǎn)前必須做脫敏。熱詞里有人問(wèn)使用 llm 時(shí)如何防止密鑰等鑒權(quán)信息泄露在可觀測(cè)這一環(huán)最直接的做法是在傳輸層加脫敏規(guī)則把疑似密鑰、手機(jī)號(hào)、身份證號(hào)的模式統(tǒng)一替換掉而不是指望每個(gè)埋點(diǎn)的人都記得手動(dòng)處理。3.4 會(huì)話與上下文追蹤Agent 的多輪對(duì)話必須用統(tǒng)一的session_id串起來(lái)否則你看到的是一堆孤立的 span沒(méi)法還原完整會(huì)話。我的做法是在會(huì)話入口生成一個(gè) session_id透?jìng)鞯矫恳淮?LLM 調(diào)用和工具調(diào)用作為 span 的公共屬性。同時(shí)要記錄turn_index也就是當(dāng)前是第幾輪。這樣在儀表盤上可以畫出上下文長(zhǎng)度隨輪次增長(zhǎng)的曲線一旦發(fā)現(xiàn)某類會(huì)話在第 5 輪之后成本陡增就能針對(duì)性優(yōu)化上下文裁剪策略。4. 從采集到告警的完整落地流程4.1 數(shù)據(jù)采集與傳輸配置采集端用 OTel SDK傳輸端用 OTel Collector。Collector 的配置是整個(gè)體系的咽喉我一般會(huì)配三個(gè) processor脫敏 processor、采樣 processor、批處理 processor。脫敏 processor 用正則匹配敏感模式采樣 processor 對(duì)高流量場(chǎng)景做尾部采樣保留錯(cuò)誤和慢請(qǐng)求丟棄正常請(qǐng)求批處理 processor 做批量發(fā)送降低網(wǎng)絡(luò)開(kāi)銷。下面是一個(gè)簡(jiǎn)化的 Collector 配置片段。processors: attributes/redact: actions: - key: llm.request.messages action: update value: [REDACTED] tail_sampling: policies: - name: errors type: status_code status_code: {status_codes: [ERROR]} - name: slow type: latency latency: {threshold_ms: 5000} batch: send_batch_size: 512 timeout: 5s提示采樣策略要謹(jǐn)慎。LLM 場(chǎng)景下正常請(qǐng)求也很有分析價(jià)值如果采樣率設(shè)得太低做質(zhì)量分析時(shí)樣本不夠。我的經(jīng)驗(yàn)是錯(cuò)誤和慢請(qǐng)求 100% 保留正常請(qǐng)求按 10% 到 20% 采樣既能控制成本又不丟關(guān)鍵信息。4.2 指標(biāo)聚合與儀表盤搭建數(shù)據(jù)進(jìn)到觀測(cè)云之后要建幾塊核心儀表盤。我通常分四塊健康度大盤、成本大盤、質(zhì)量大盤、會(huì)話分析大盤。健康度大盤放 QPS、錯(cuò)誤率、TTFT、端到端延遲分位、工具調(diào)用成功率。成本大盤放 Token 消耗趨勢(shì)、按模型/按業(yè)務(wù)線/按用戶的成本拆分。質(zhì)量大盤放 finish_reason 分布、重試率、任務(wù)完成率。會(huì)話分析大盤放步數(shù)分布、上下文增長(zhǎng)曲線、循環(huán)檢測(cè)命中數(shù)。這里有個(gè)建模技巧成本一定要做多維歸因。只統(tǒng)計(jì)總成本沒(méi)用要能回答哪個(gè)業(yè)務(wù)線最燒錢哪個(gè)用戶最燒錢哪個(gè)模型性價(jià)比最低。做法是在埋點(diǎn)時(shí)給每次調(diào)用打上business_line、user_id、model_name標(biāo)簽聚合時(shí)按這些維度下鉆。4.3 告警規(guī)則設(shè)計(jì)告警規(guī)則不能照搬傳統(tǒng)服務(wù)那套閾值。LLM 場(chǎng)景的告警要分兩類硬性故障和軟性劣化。硬性故障包括錯(cuò)誤率突增、工具調(diào)用連續(xù)失敗、模型 API 返回鑒權(quán)錯(cuò)誤這類直接觸發(fā)高優(yōu)先級(jí)告警。軟性劣化包括 TTFT 分位緩慢上升、平均步數(shù)逐漸增加、單會(huì)話成本異常偏高這類用同比環(huán)比和基線偏離來(lái)觸發(fā)優(yōu)先級(jí)低一些但要持續(xù)關(guān)注。我特別推薦配一條循環(huán)檢測(cè)告警當(dāng)某個(gè) session 內(nèi)相同工具 相同參數(shù)連續(xù)調(diào)用超過(guò) 5 次立即告警。Agent 陷入死循環(huán)是線上最常見(jiàn)也最燒錢的問(wèn)題早發(fā)現(xiàn)早止損。4.4 根因分析視圖告警觸發(fā)之后排查效率取決于數(shù)據(jù)關(guān)聯(lián)能力。觀測(cè)云的好處是可以從一條異常 trace 直接下鉆。我的排查路徑通常是告警指向某個(gè)指標(biāo)異常點(diǎn)進(jìn)去看是哪些 trace 貢獻(xiàn)了異常打開(kāi)具體 trace 看是哪一步出的問(wèn)題再關(guān)聯(lián)這一步的日志和當(dāng)時(shí)的系統(tǒng)指標(biāo)。舉個(gè)真實(shí)例子。有次告警顯示某業(yè)務(wù)線成本突然翻倍從成本大盤下鉆到 trace發(fā)現(xiàn)是某個(gè)工具返回的數(shù)據(jù)格式變了導(dǎo)致 Agent 反復(fù)重試同一個(gè)工具步數(shù)從平均 3 步漲到 12 步。如果沒(méi)有鏈路追蹤你只能看到成本漲了根本不知道漲在哪。5. 常見(jiàn)問(wèn)題與排查技巧實(shí)錄5.1 高頻問(wèn)題速查表現(xiàn)象可能原因排查方向接口成功但用戶投訴答非所問(wèn)模型幻覺(jué)或 prompt 問(wèn)題看質(zhì)量指標(biāo)和實(shí)際輸入輸出成本突然上漲上下文膨脹或循環(huán)調(diào)用看步數(shù)分布和上下文增長(zhǎng)曲線工具調(diào)用頻繁失敗工具本身故障或參數(shù)錯(cuò)誤按 tool_name 拆分成功率響應(yīng)變慢但錯(cuò)誤率為零模型側(cè)限流或 TTFT 上升看 TTFT 分位和重試次數(shù)多輪對(duì)話后期質(zhì)量下降上下文超限被截?cái)嗫?finish_reason 和上下文長(zhǎng)度某類請(qǐng)求全部超時(shí)特定模型或工具不可用按 model_name 和 tool_name 下鉆5.2 幾個(gè)踩過(guò)的坑第一個(gè)坑是只監(jiān)控了 LLM 沒(méi)監(jiān)控 Agent。早期我們只埋了模型調(diào)用結(jié)果 Agent 層面的循環(huán)、工具選擇錯(cuò)誤完全看不見(jiàn)。后來(lái)補(bǔ)上 Agent 鏈路埋點(diǎn)才發(fā)現(xiàn)很多問(wèn)題出在決策層而不是模型層。第二個(gè)坑是采樣策略太激進(jìn)。為了省成本把采樣率設(shè)到 1%結(jié)果做質(zhì)量分析時(shí)樣本嚴(yán)重不足很多偶發(fā)問(wèn)題根本抓不到。后來(lái)改成錯(cuò)誤全留、正常采樣問(wèn)題就解決了。第三個(gè)坑是脫敏做在采集端。一開(kāi)始讓每個(gè)埋點(diǎn)的人自己脫敏結(jié)果總有人漏。后來(lái)統(tǒng)一挪到 Collector 層做規(guī)則集中管理再?zèng)]出過(guò)泄露。第四個(gè)坑是告警閾值照搬傳統(tǒng)服務(wù)。LLM 的延遲天然比普通接口高用傳統(tǒng)閾值會(huì)瘋狂誤報(bào)。后來(lái)改成基于歷史基線做動(dòng)態(tài)閾值誤報(bào)率大幅下降。5.3 獨(dú)家避坑技巧給每次調(diào)用打上 trace_id 并透?jìng)鞯綐I(yè)務(wù)日志這樣業(yè)務(wù)側(cè)出問(wèn)題時(shí)能直接關(guān)聯(lián)到可觀測(cè)數(shù)據(jù)對(duì) prompt 做版本管理把 prompt 版本號(hào)作為標(biāo)簽上報(bào)這樣能對(duì)比不同 prompt 版本的效果差異建立成本預(yù)算告警按業(yè)務(wù)線設(shè)日預(yù)算超了立即通知避免月底才發(fā)現(xiàn)賬單爆炸定期做 trace 抽樣人工評(píng)審機(jī)器指標(biāo)看不出的語(yǔ)義問(wèn)題靠人工抽查補(bǔ)位工具調(diào)用加超時(shí)和熔斷別讓一個(gè)慢工具拖垮整個(gè) Agent6. 體系擴(kuò)展與長(zhǎng)期演進(jìn)的一些個(gè)人體會(huì)這套體系搭起來(lái)之后最明顯的變化是排查問(wèn)題的思路變了。以前遇到 LLM 應(yīng)用出問(wèn)題第一反應(yīng)是重啟試試或者換個(gè)模型試試現(xiàn)在能精確定位到是 prompt 問(wèn)題、工具問(wèn)題還是模型問(wèn)題處理效率完全不是一個(gè)量級(jí)。后續(xù)可以擴(kuò)展的方向我自己在實(shí)踐里試過(guò)幾個(gè)。一是把質(zhì)量評(píng)估自動(dòng)化用另一個(gè)模型做裁判對(duì)回答打分把分?jǐn)?shù)作為指標(biāo)上報(bào)這樣質(zhì)量劣化能自動(dòng)發(fā)現(xiàn)。二是做 A/B 實(shí)驗(yàn)框架把不同 prompt、不同模型、不同參數(shù)的效果差異用數(shù)據(jù)說(shuō)話而不是拍腦袋。三是把 AgentOps 和 CI/CD 打通每次 prompt 或工具變更都跑一遍回歸測(cè)試用可觀測(cè)數(shù)據(jù)做發(fā)布門禁。我個(gè)人在實(shí)際操作中的體會(huì)是AgentOps 這件事最難的不是技術(shù)而是堅(jiān)持把數(shù)據(jù)采全、采準(zhǔn)。很多團(tuán)隊(duì)搭了個(gè)架子埋點(diǎn)埋一半指標(biāo)缺胳膊少腿最后發(fā)現(xiàn)排查問(wèn)題時(shí)數(shù)據(jù)不夠用又回頭補(bǔ)埋點(diǎn)來(lái)回折騰。所以一開(kāi)始就把指標(biāo)模型設(shè)計(jì)清楚比后面反復(fù)返工要省事得多。另外別追求一步到位先把 LLM 調(diào)用層的核心指標(biāo)和成本歸因做扎實(shí)再逐步擴(kuò)展到 Agent 決策鏈路這個(gè)節(jié)奏比較穩(wěn)。