用架構(gòu)設(shè)計(jì):從核心組件到高并發(fā)Agent實(shí)戰(zhàn))
做AI應(yīng)用架構(gòu)這幾年我收到最多的需求往往不是“該選哪個(gè)模型”而是“整套系統(tǒng)到底怎么串起來(lái)”。圖解AI應(yīng)用架構(gòu)設(shè)計(jì)本質(zhì)是把大模型應(yīng)用里那些看不見的調(diào)用鏈、狀態(tài)流、失敗路徑用一種一眼就能看懂的圖形語(yǔ)言固定下來(lái)。這篇文章不聊空泛的概念直接講怎么把AI應(yīng)用架構(gòu)畫清楚、畫到位包括核心組件怎么拆、架構(gòu)圖從哪一筆開始畫、一套能扛住并發(fā)請(qǐng)求的Agent應(yīng)用實(shí)戰(zhàn)案例以及我在真實(shí)項(xiàng)目里踩過(guò)的坑。適合正在做AI應(yīng)用落地的架構(gòu)師、后端開發(fā)也適合剛開始接觸AI工程化的新手參考。1. 為什么AI應(yīng)用架構(gòu)必須“畫出來(lái)”很多團(tuán)隊(duì)做AI應(yīng)用第一步就陷入“聊方案”的泥潭模型選型、Prompt怎么寫、要不要上Agent、RAG用哪種召回策略每個(gè)人都有自己的看法。但方案聊得再熱鬧一落到“系統(tǒng)到底長(zhǎng)什么樣”往往就卡住了。這個(gè)現(xiàn)象的背后有一個(gè)很現(xiàn)實(shí)的原因——AI應(yīng)用架構(gòu)比傳統(tǒng)后端復(fù)雜得多復(fù)雜到靠文字和腦子根本hold不住。1.1 AI應(yīng)用與傳統(tǒng)后端架構(gòu)的本質(zhì)差異傳統(tǒng)后端架構(gòu)業(yè)務(wù)流程基本是確定性的請(qǐng)求進(jìn)來(lái)經(jīng)過(guò)路由、鑒權(quán)、查庫(kù)、拼裝返回結(jié)果整個(gè)鏈路是可預(yù)測(cè)的。但AI應(yīng)用從第一行設(shè)計(jì)開始就帶著不確定性。大模型的輸出不可預(yù)知同一個(gè)Prompt在不同時(shí)間可能給出完全不同的回答一次Agent任務(wù)可能要循環(huán)調(diào)用多個(gè)工具才能完成一次RAG檢索要經(jīng)過(guò)切分、向量化、召回、重排多個(gè)節(jié)點(diǎn)每個(gè)節(jié)點(diǎn)都可能成為瓶頸。這些不確定性疊加在一起靠腦子記是不可能的。比如一個(gè)智能客服系統(tǒng)用戶問“我的訂單什么時(shí)候到”系統(tǒng)要先判斷意圖再?zèng)Q定是查訂單系統(tǒng)還是查知識(shí)庫(kù)查完之后還要把結(jié)果塞進(jìn)Prompt最后等模型生成回答。如果查訂單接口超時(shí)了怎么辦如果知識(shí)庫(kù)里根本沒有相關(guān)內(nèi)容怎么辦如果模型生成到一半連接斷了怎么辦這些問題如果不在設(shè)計(jì)階段想清楚線上遲早會(huì)炸。畫圖在這里不是畫“架構(gòu)裝飾圖”而是把不確定性攤開攤平。哪個(gè)環(huán)節(jié)可能失敗、哪條路徑會(huì)超時(shí)、哪個(gè)組件的token消耗會(huì)失控只有畫到圖上才能暴露出來(lái)。我們團(tuán)隊(duì)早期做智能客服就吃過(guò)虧架構(gòu)文檔寫了四十多頁(yè)評(píng)審會(huì)開了三個(gè)小時(shí)最后主持人問了一句“如果召回結(jié)果為空鏈路怎么走”全場(chǎng)沉默了半分鐘。后來(lái)把方案改成畫一張鏈路圖五分鐘就發(fā)現(xiàn)整條鏈路上根本沒有兜底分支。1.2 圖解解決的四個(gè)具體問題圖紙真正解決的不是“好看”而是下面這幾件具體的事。溝通對(duì)齊是第一位的。一張架構(gòu)圖放在評(píng)審會(huì)上產(chǎn)品、后端、算法、測(cè)試都能指著同一個(gè)方框?qū)υ挕N淖址桨咐锝?jīng)常出現(xiàn)的“你說(shuō)的A和我理解的A不是同一個(gè)A”在圖上幾乎不會(huì)發(fā)生。因?yàn)榉娇蚝图^是客觀的誰(shuí)也繞不過(guò)去。排查定位同樣依賴圖。線上出問題時(shí)第一件事是定位卡在哪個(gè)環(huán)節(jié)。有了一張準(zhǔn)確的架構(gòu)圖就可以快速縮小范圍是模型調(diào)用超時(shí)、向量庫(kù)響應(yīng)慢、還是工具調(diào)用沒有響應(yīng)。沒有圖就只能順著日志一條一條翻運(yùn)氣不好翻到第二天早上。演進(jìn)設(shè)計(jì)更需要圖。AI應(yīng)用是迭代速度最快的軟件形態(tài)之一Prompt從單輪改成多輪、工具從一個(gè)加到十個(gè)、模型從單一供應(yīng)商改成多家路由每一次改動(dòng)都要評(píng)估影響面。圖就是影響面分析的基礎(chǔ)沒有圖改一個(gè)組件就像蒙著眼睛拆炸彈。新人上手也得靠圖。我習(xí)慣把架構(gòu)圖放在項(xiàng)目README最前面新同學(xué)來(lái)了先對(duì)著圖講五分鐘再去看代碼上手速度能快好幾倍。圖就是系統(tǒng)的“第一本書”。2. AI應(yīng)用架構(gòu)的核心組件拆解圖解視角想把AI應(yīng)用架構(gòu)畫出來(lái)第一步是搞清楚圖上有哪些“方框”。和傳統(tǒng)后端不一樣AI應(yīng)用架構(gòu)的組件有它自己的一套邏輯每個(gè)方框背后都對(duì)應(yīng)一類要專門處理的問題。下面按我畫圖時(shí)的習(xí)慣從入口到出口拆一遍。2.1 模型接入層把不確定性擋在門外任何AI應(yīng)用都會(huì)有一層模型接入圖上這個(gè)方框負(fù)責(zé)處理三件事模型路由、超時(shí)與重試策略、統(tǒng)一的token計(jì)量。模型路由是指不同任務(wù)走不同模型——簡(jiǎn)單問答走小模型省錢復(fù)雜推理走大模型保質(zhì)量這個(gè)決策不應(yīng)該散落在業(yè)務(wù)代碼里而應(yīng)該收斂到這一層。設(shè)計(jì)時(shí)最容易漏的是重試策略。LLM接口偶爾會(huì)返回5xx錯(cuò)誤如果沒有重試機(jī)制用戶體驗(yàn)直接斷崖式下跌。但重試也不能無(wú)腦重試一次請(qǐng)求已經(jīng)跑了3秒失敗后立即重試用戶可能要等6秒甚至更久。我的做法是區(qū)分錯(cuò)誤類型網(wǎng)絡(luò)抖動(dòng)可以快速重試一次模型過(guò)載就要退避等待或者直接降級(jí)。token計(jì)量也很關(guān)鍵沒有統(tǒng)一的計(jì)量層成本就成了一筆糊涂賬等到月底賬單出來(lái)才發(fā)現(xiàn)某個(gè)接口的調(diào)用量已經(jīng)失控。2.2 編排層與Agent把“怎么做”變成執(zhí)行計(jì)劃編排層是AI應(yīng)用架構(gòu)里最有“AI味道”的部分尤其當(dāng)系統(tǒng)里出現(xiàn)Agent的時(shí)候。Agent編排層解決的核心問題是模型怎么調(diào)用工具、怎么決定下一步動(dòng)作。圖上常見的形態(tài)有兩種一種是ReAct式的“思考-行動(dòng)-觀察”循環(huán)模型每走一步都觀察結(jié)果再?zèng)Q定下一步另一種是Plan-and-Execute式的“先規(guī)劃、再執(zhí)行”把一個(gè)大任務(wù)拆成幾個(gè)小步驟然后按計(jì)劃執(zhí)行。我畫圖時(shí)會(huì)在編排層旁邊專門標(biāo)注一個(gè)工具清單因?yàn)檫@是失控風(fēng)險(xiǎn)最高的地方。工具越多Agent越可能調(diào)用不該調(diào)用的工具也可能在某個(gè)工具返回異常時(shí)反復(fù)重試把整個(gè)鏈路拖垮。多Agent協(xié)作的架構(gòu)會(huì)在這個(gè)基礎(chǔ)上更復(fù)雜一層——多個(gè)Agent各自負(fù)責(zé)一塊任務(wù)彼此之間可能需要傳遞結(jié)果、等待對(duì)方完成這時(shí)候圖上就要標(biāo)清楚協(xié)作關(guān)系和交互方式否則就會(huì)出現(xiàn)互相等待的“死鎖”局面。這里有個(gè)經(jīng)驗(yàn)編排層在圖上一定要畫得有邊界感。哪些任務(wù)走Agent循環(huán)、哪些任務(wù)直接走固定流程一開始就要分清楚。不是所有請(qǐng)求都需要Agent的“智能”很多高頻場(chǎng)景用固定流程反而更穩(wěn)定、更省錢。2.3 知識(shí)與記憶層讓輸出有據(jù)可依RAG檢索增強(qiáng)生成幾乎已經(jīng)成為AI應(yīng)用的標(biāo)配。圖上這條鏈路很典型文檔入庫(kù)時(shí)先切分再向量化寫入向量庫(kù)請(qǐng)求進(jìn)來(lái)后先做向量檢索再做精排最后把召回的內(nèi)容塞進(jìn)Prompt讓模型基于這些內(nèi)容生成回答。畫圖時(shí)很多人會(huì)漏掉“重排”這個(gè)環(huán)節(jié)但恰恰是重排決定了知識(shí)質(zhì)量。向量檢索召回的是“語(yǔ)義相似”的內(nèi)容相似不等于正確用戶問的是A問題時(shí)檢索結(jié)果可能混進(jìn)大量看似相關(guān)實(shí)則無(wú)關(guān)的B內(nèi)容。重排環(huán)節(jié)可以把這個(gè)噪聲濾掉保證進(jìn)Prompt的內(nèi)容是真正有用的。沒有重排的RAG回答質(zhì)量波動(dòng)很大時(shí)好時(shí)壞特別難排查。記憶層則分短期和長(zhǎng)期。短期記憶在對(duì)話上下文里模型能直接看到長(zhǎng)期記憶放在外部存儲(chǔ)比如KV存儲(chǔ)或者向量庫(kù)需要時(shí)再檢索出來(lái)。這個(gè)設(shè)計(jì)決定了系統(tǒng)的“有狀態(tài)”程度。畫圖時(shí)我會(huì)單獨(dú)標(biāo)出記憶的存儲(chǔ)位置和讀寫路徑因?yàn)橐坏┫到y(tǒng)變成有狀態(tài)水平擴(kuò)展、并發(fā)控制、數(shù)據(jù)一致性這些問題就全都來(lái)了。2.4 可觀測(cè)性層圖上看不見的“第五層”AI應(yīng)用比傳統(tǒng)架構(gòu)更需要可觀測(cè)性因?yàn)槊看握{(diào)用的輸入輸出都是動(dòng)態(tài)的、不可預(yù)知的。我在圖上會(huì)畫一個(gè)橫跨所有組件的追蹤總線記錄每次請(qǐng)求涉及的模型、Prompt、token消耗、延遲、召回內(nèi)容。這個(gè)層在架構(gòu)圖上往往被畫成貫穿全局的一條帶子它不是“加分項(xiàng)”而是剛需。有一次生產(chǎn)事故用戶反饋“回答牛頭不對(duì)馬嘴”痛苦地排查了很久最后全靠追蹤記錄里的召回內(nèi)容定位到問題——向量庫(kù)索引沒有更新召回的是三周前的舊文檔。如果沒有這層記錄這種問題幾乎不可能定位因?yàn)橛脩舻膯栴}、模型的輸出都是動(dòng)態(tài)的靠日志里的常規(guī)字段根本看不出因果關(guān)系。3. 圖解方法論從需求到架構(gòu)圖的實(shí)操套路理解了組件下一步是知道怎么把圖畫出來(lái)。很多人畫架構(gòu)圖最大的問題是不知道第一筆落在哪里結(jié)果越畫越亂最后變成一張誰(shuí)也不想看的“毛線球”。我這些年總結(jié)出一套順序照著走基本不會(huì)跑偏。3.1 下筆順序先畫鏈路主干第一步不是畫系統(tǒng)邊界也不是畫一堆外圍依賴而是從一次用戶請(qǐng)求開始畫出主干鏈路。比如一個(gè)AI客服系統(tǒng)主干就是用戶 - 入口網(wǎng)關(guān) - 意圖識(shí)別 - 編排中心 - 模型網(wǎng)關(guān) - 外部模型 - 回復(fù)用戶。這條主線先定下來(lái)其他所有組件都變成掛在這條主干上的分支整個(gè)圖的結(jié)構(gòu)感一下子就出來(lái)了。主干畫清楚圖就成功了一半。很多架構(gòu)圖之所以亂就是因?yàn)樯蟻?lái)就把所有模塊平鋪在畫布上沒有主次之分讀者不知道眼睛該往哪里看。有了主干之后再往上面掛分支RAG是掛在編排中心下面的分支工具調(diào)用是掛在編排中心下面的另一條分支緩存和記憶服務(wù)是橫跨多個(gè)環(huán)節(jié)的輔助組件。一步一步加圖始終是清晰的。主干還要標(biāo)注出關(guān)鍵的數(shù)據(jù)流方向標(biāo)注出哪些是同步調(diào)用、哪些是異步消息。我畫圖時(shí)習(xí)慣用實(shí)線箭頭表示同步調(diào)用虛線箭頭表示異步消息這樣一眼就能看出整個(gè)鏈路里哪些環(huán)節(jié)是阻塞的、哪些是可以解耦的。異步邊界往往就是系統(tǒng)的擴(kuò)展點(diǎn)也是將來(lái)做性能優(yōu)化的突破口。3.2 四種視圖各解決一個(gè)問題一張架構(gòu)圖很難同時(shí)表達(dá)所有信息所以畫圖的人要懂得分開畫。我常用的做法是按四種視圖來(lái)組織每種解決不同的問題合在一起才是完整的設(shè)計(jì)。邏輯視圖回答“系統(tǒng)由哪些模塊組成”這是最常畫的一種方框和箭頭為主看的是模塊間的依賴關(guān)系。部署視圖回答“模塊跑在哪里、怎么連接”看的是物理環(huán)境、網(wǎng)絡(luò)邊界、中間件部署主要給運(yùn)維和基礎(chǔ)設(shè)施的同學(xué)看。時(shí)序視圖回答“一次請(qǐng)求的完整交互過(guò)程”把時(shí)間維度畫出來(lái)看的是消息順序和狀態(tài)流轉(zhuǎn)。數(shù)據(jù)流視圖回答“數(shù)據(jù)從哪里來(lái)到哪里去、如何存儲(chǔ)”看的是數(shù)據(jù)的生命周期。這四種視圖的關(guān)系有點(diǎn)像看一個(gè)建筑邏輯視圖是戶型圖部署視圖是施工現(xiàn)場(chǎng)圖時(shí)序視圖是使用場(chǎng)景動(dòng)畫數(shù)據(jù)流視圖是水電線路圖。不同角色關(guān)心不同圖紙但不代表它們可以互相替代。我一般先畫邏輯視圖定大局再根據(jù)實(shí)際需要補(bǔ)其他視圖項(xiàng)目復(fù)雜度越高越要主動(dòng)補(bǔ)全后面的三種。3.3 畫圖規(guī)范與工具選型畫圖工具不用糾結(jié)draw.io、Excalidraw、Lucidchart都?jí)蛴媚軐?dǎo)出PNG、能多人協(xié)作就行。真正重要的是團(tuán)隊(duì)統(tǒng)一的畫圖規(guī)范工具是其次。我常用的規(guī)范是這樣的方框表示系統(tǒng)或模塊圓角矩形表示外部依賴實(shí)線箭頭表示同步調(diào)用虛線箭頭表示異步消息紅色或特殊顏色的連線表示失敗或降級(jí)路徑。顏色控制在三到四色以內(nèi)多了反而失去重點(diǎn)。命名上每個(gè)方框的名稱要能直接對(duì)應(yīng)到真實(shí)的系統(tǒng)或服務(wù)名不能讓圖上的名字和代碼里的名字對(duì)不上否則圖就失去了排查定位的價(jià)值。還有一個(gè)很多人忽略的點(diǎn)圖的繪制語(yǔ)言要統(tǒng)一。我的要求是每張圖都能用一句話講清楚主干流程比如“用戶請(qǐng)求進(jìn)來(lái)網(wǎng)關(guān)鑒權(quán)后發(fā)給編排中心編排中心決定走RAG還是走工具調(diào)用最后統(tǒng)一經(jīng)過(guò)模型網(wǎng)關(guān)返回”。如果一張圖無(wú)法用一句話講清楚說(shuō)明圖畫得還不夠聚焦。3.4 讓架構(gòu)圖“活”起來(lái)架構(gòu)圖最怕畫完就扔進(jìn)文檔庫(kù)里吃灰。我現(xiàn)在的做法是把架構(gòu)圖當(dāng)成代碼一樣管理存到團(tuán)隊(duì)共享的畫圖空間里按日期維護(hù)版本每次架構(gòu)評(píng)審之前先看當(dāng)前圖確認(rèn)改動(dòng)之后立刻更新圖絕不讓圖滯后于系統(tǒng)。把“更新架構(gòu)圖”寫進(jìn)需求的完成定義里這本身就是AI Native研發(fā)范式的一部分。AI應(yīng)用迭代太快圖一旦滯后參考價(jià)值就沒了反而會(huì)誤導(dǎo)人。我們團(tuán)隊(duì)吃過(guò)一次虧圖還停留在“單模型接入”的版本但實(shí)際上系統(tǒng)已經(jīng)接了三家模型做了路由新同學(xué)照著舊圖看不懂代碼折騰了一個(gè)星期才搞清楚現(xiàn)狀。4. 實(shí)戰(zhàn)案例一個(gè)能扛住并發(fā)請(qǐng)求的AI Agent應(yīng)用架構(gòu)理論講完來(lái)一個(gè)完整案例。假設(shè)要設(shè)計(jì)一個(gè)企業(yè)內(nèi)部知識(shí)助手需要集成工具查詢工單、拉取會(huì)議記錄、檢索知識(shí)庫(kù)文檔峰值并發(fā)500 QPS。這個(gè)場(chǎng)景非常典型正好可以回答“AI Agent怎么扛并發(fā)”這個(gè)問題。4.1 場(chǎng)景設(shè)定與約束條件先明確約束峰值500 QPS的并發(fā)請(qǐng)求單次模型調(diào)用平均延遲2秒左右這就意味著同一時(shí)刻系統(tǒng)里可能有上千個(gè)模型請(qǐng)求在途這已經(jīng)是一個(gè)不小的壓力。成本要敏感企業(yè)場(chǎng)景下token開銷不能無(wú)限膨脹每個(gè)請(qǐng)求都要想清楚花多少錢。工具調(diào)用是外部依賴穩(wěn)定性不如模型接口偶爾會(huì)超時(shí)要防止單個(gè)工具故障拖垮整個(gè)主鏈路。這個(gè)約束條件決定了架構(gòu)不可能做成“每個(gè)請(qǐng)求實(shí)時(shí)串聯(lián)一堆服務(wù)”的形態(tài)必須在入口、編排、模型調(diào)用三個(gè)層面都做控制和取舍。500 QPS看起來(lái)不算高但疊加2秒的模型延遲和外部工具的不穩(wěn)定性復(fù)雜度立刻上來(lái)了。4.2 分層架構(gòu)逐層設(shè)計(jì)整個(gè)架構(gòu)按四層來(lái)設(shè)計(jì)接入層、編排層、模型層、數(shù)據(jù)層。接入層是API網(wǎng)關(guān)負(fù)責(zé)鑒權(quán)、限流、參數(shù)校驗(yàn)所有請(qǐng)求先過(guò)這一層編排層是核心由一組無(wú)狀態(tài)的Agent Worker組成負(fù)責(zé)意圖識(shí)別、任務(wù)拆解、工具調(diào)用、結(jié)果聚合模型層是模型網(wǎng)關(guān)負(fù)責(zé)多模型路由、超時(shí)重試、token計(jì)量數(shù)據(jù)層包括向量庫(kù)、Redis緩存、日志存儲(chǔ)為上層提供知識(shí)、記憶和追蹤能力。接入層的限流必須先做。500 QPS是業(yè)務(wù)峰值但系統(tǒng)實(shí)際能承載的容量不一定夠如果超過(guò)容量還繼續(xù)放行所有請(qǐng)求一起變慢最終誰(shuí)也服務(wù)不好。限流策略是在網(wǎng)關(guān)層直接拒絕超量請(qǐng)求返回明確的429狀態(tài)碼讓上游客戶端自己決定是重試還是降級(jí)。這是最粗暴也最有效的保護(hù)手段。編排層的核心數(shù)據(jù)是用戶請(qǐng)求的上下文、任務(wù)狀態(tài)、工具調(diào)用的結(jié)果這些數(shù)據(jù)全部外置到Redis里Agent Worker本身不保存任何狀態(tài)。無(wú)狀態(tài)設(shè)計(jì)是扛并發(fā)的關(guān)鍵前提——只有無(wú)狀態(tài)才能隨意水平擴(kuò)展Pod不夠就擴(kuò)容擴(kuò)容完?duì)顟B(tài)還在Redis里誰(shuí)都能接上繼續(xù)干活。4.3 AI Agent扛并發(fā)限流、無(wú)狀態(tài)、降級(jí)三板斧第一板斧是意圖識(shí)別前置。不是所有請(qǐng)求都需要走完整的Agent循環(huán)流程用戶可能只是問一句“今天周幾”沒必要去調(diào)大模型。在Agent Worker前面加一個(gè)輕量級(jí)的意圖分類器高頻簡(jiǎn)單問題直接走快速通道只有復(fù)雜任務(wù)才進(jìn)入Agent編排循環(huán)這樣能大幅降低模型調(diào)用量和整體延遲。第二板斧是模型調(diào)用的降級(jí)策略。模型網(wǎng)關(guān)在接到編排層的請(qǐng)求時(shí)會(huì)先判斷主模型的負(fù)載狀態(tài)。主模型如果超時(shí)或返回過(guò)載立刻降級(jí)到備用的小模型或更快的模型回答質(zhì)量會(huì)在一定程度上降低但用戶體驗(yàn)不中斷。還有一個(gè)細(xì)節(jié)是給所有模型調(diào)用設(shè)置“全局超時(shí)”這個(gè)超時(shí)值必須比單次模型調(diào)用的超時(shí)更短確保整個(gè)Agent循環(huán)不會(huì)因?yàn)橐淮喂ぞ哒{(diào)用卡死而無(wú)限拖下去。第三板斧是緩存。相似問題的答案可以緩存比如企業(yè)的常見制度問答、高頻知識(shí)庫(kù)內(nèi)容命中緩存的請(qǐng)求連模型都不用調(diào)直接返回。緩存這個(gè)手段在AI應(yīng)用里很容易被忽略但它對(duì)成本和延遲的優(yōu)化效果極其明顯。曾經(jīng)統(tǒng)計(jì)過(guò)一次加了答案緩存之后整體模型調(diào)用量降了將近四成峰值壓力直接下來(lái)了。還有一個(gè)容易踩的坑Agent循環(huán)內(nèi)部的狀態(tài)翻轉(zhuǎn)和工具調(diào)用要設(shè)總步數(shù)上限比如最多迭代5輪超過(guò)就放棄繼續(xù)規(guī)劃、直接基于已有信息生成答案。不設(shè)上限的Agent在極端情況下會(huì)陷入無(wú)限循環(huán)token燒掉不說(shuō)用戶等的時(shí)間也完全沒法接受。4.4 把設(shè)計(jì)整合為一張可讀的架構(gòu)圖把這個(gè)設(shè)計(jì)落成一張圖從左到右看是這樣客戶端在最左邊經(jīng)過(guò)API網(wǎng)關(guān)進(jìn)入系統(tǒng)網(wǎng)關(guān)右邊是Agent Worker池這是整個(gè)架構(gòu)的心臟Worker上方掛著Redis用于存放任務(wù)狀態(tài)和短期記憶Worker下方掛著向量庫(kù)用于知識(shí)檢索Worker右邊是模型網(wǎng)關(guān)模型網(wǎng)關(guān)再往右連接多個(gè)外部大模型服務(wù)整個(gè)系統(tǒng)的底部橫著一條日志追蹤總線把所有環(huán)節(jié)的調(diào)用記錄串起來(lái)。箭頭關(guān)系要標(biāo)清楚API網(wǎng)關(guān)到Worker是同步調(diào)用Worker到模型網(wǎng)關(guān)是同步調(diào)用Worker到向量庫(kù)是同步調(diào)用但Worker到Redis是異步讀寫Worker之間的任務(wù)分發(fā)則是通過(guò)消息隊(duì)列異步解耦。也就是說(shuō)沒有一個(gè)組件是單點(diǎn)綁死的任何一個(gè)組件掛了都有對(duì)應(yīng)的降級(jí)方案模型掛了走降級(jí)模型向量庫(kù)掛了走本地關(guān)鍵詞兜底R(shí)edis掛了就強(qiáng)制所有請(qǐng)求走無(wú)記憶的極簡(jiǎn)模式。這張圖的一個(gè)隱藏重點(diǎn)是“失敗路徑的標(biāo)注”傳統(tǒng)架構(gòu)圖一般只畫正常鏈路但AI應(yīng)用的設(shè)計(jì)必須把失敗鏈路畫出來(lái)。哪里超時(shí)、哪里降級(jí)、哪里兜底全部標(biāo)在圖上。這樣運(yùn)維同學(xué)看著圖就知道線上出故障時(shí)該往哪個(gè)方向處理。5. 常見問題與避坑實(shí)錄最后這部分集中分享實(shí)踐過(guò)程中遇到的典型問題和排查思路可以作為一張速查表來(lái)用。這些坑不是從教科書上看來(lái)的都是在真實(shí)項(xiàng)目里用時(shí)間換來(lái)的教訓(xùn)。5.1 畫圖過(guò)程中的典型誤區(qū)第一個(gè)誤區(qū)是一上來(lái)就把所有細(xì)節(jié)堆上去。畫圖的人恨不得把每個(gè)類的名字、每個(gè)接口的出入?yún)⒍紝戇M(jìn)方框里結(jié)果一張圖密密麻麻主鏈路完全被淹沒。正確的做法是分粒度全局圖只畫系統(tǒng)級(jí)組件局部圖再展開內(nèi)部細(xì)節(jié)。第二個(gè)誤區(qū)是只畫正常路徑、不畫失敗路徑。架構(gòu)圖上全是成功的箭頭找不到任何一處異常處理的分支這種圖在評(píng)審階段看著很順上線以后才知道想得太少。我在評(píng)審時(shí)會(huì)專門找那些畫不出失敗路徑的圖來(lái)提問答不上來(lái)就說(shuō)明設(shè)計(jì)還沒閉環(huán)。第三個(gè)誤區(qū)是圖長(zhǎng)期不更新。很多團(tuán)隊(duì)的架構(gòu)圖都停留在“項(xiàng)目啟動(dòng)第一周畫的版本”系統(tǒng)改了幾輪圖紋絲不動(dòng)。這種圖比沒有圖更危險(xiǎn)因?yàn)樗鼤?huì)給出錯(cuò)誤信息把排查問題的人帶進(jìn)溝里。5.2 架構(gòu)設(shè)計(jì)層面的實(shí)戰(zhàn)踩坑工具調(diào)用沒有全局超時(shí)是我踩過(guò)最重的坑。早期做Agent系統(tǒng)每個(gè)工具都設(shè)了超時(shí)但沒給整個(gè)Agent循環(huán)設(shè)全局超時(shí)結(jié)果某個(gè)工具卡住后Agent還在反復(fù)嘗試整個(gè)鏈路拖了30多秒才失敗用戶早就走了后臺(tái)還堆了一堆積壓請(qǐng)求?,F(xiàn)在的規(guī)矩是全局超時(shí)一定要有而且要比所有單次超時(shí)加起來(lái)還要短。上下文無(wú)限增長(zhǎng)是另一個(gè)隱蔽的坑。多輪對(duì)話里如果不控制上下文長(zhǎng)度每輪都把歷史消息全部塞給模型token消耗會(huì)隨著對(duì)話輪數(shù)線性爆炸。解決方案有三種滑動(dòng)窗口只保留最近幾輪、對(duì)早期對(duì)話做摘要壓縮、超過(guò)一定長(zhǎng)度就強(qiáng)制開啟新會(huì)話。三種方案可以結(jié)合使用核心是給上下文畫一條明確的上限線。多Agent協(xié)作時(shí)容易互相等死鎖本質(zhì)上和分布式系統(tǒng)的死鎖問題一模一樣。A等B的結(jié)果B等C的結(jié)果C又在等A釋放資源一整個(gè)環(huán)就卡住了。現(xiàn)在的解法是每個(gè)Agent的等待都設(shè)總超時(shí)超時(shí)后帶著已有部分結(jié)果返回不讓等待無(wú)限延長(zhǎng)。寧可返回一個(gè)不完整的答案也比無(wú)限掛起強(qiáng)。RAG召回為空時(shí)也必須兜底。很多系統(tǒng)的Prompt模板里寫死了“基于以下知識(shí)回答”但召回結(jié)果為空時(shí)模型只能硬著頭皮編。正確的做法是在代碼層判斷如果召回結(jié)果為空就切換提示詞明確告訴模型“沒有相關(guān)資料”要求它如實(shí)承認(rèn)不知道而不是強(qiáng)行編造。5.3 鏈路問題排查思路在這里整理一套排查鏈路問題的思路。AI應(yīng)用的問題定位不能像傳統(tǒng)后端那樣看幾個(gè)關(guān)鍵報(bào)錯(cuò)就判斷必須從整條鏈路去還原現(xiàn)場(chǎng)。我的排查順序是這樣先看追蹤總線的記錄找到出問題的這次請(qǐng)求確認(rèn)它走的是哪條鏈路、經(jīng)過(guò)哪些組件、每一步的延遲是多少。只看這一步就能把問題的排查范圍縮小一大半。再看模型調(diào)用的輸入輸出確認(rèn)Prompt里到底塞了什么、模型返回了什么這一步可以判斷是提示詞問題、上下文丟失問題還是模型本身的問題。如果是Agent任務(wù)接著看工具調(diào)用記錄確認(rèn)哪個(gè)環(huán)節(jié)返回了異常以及Agent在異常之后做了什么決策。最后回到代碼和配置看是參數(shù)配置問題、依賴組件問題還是自己的邏輯缺陷。這套流程的前提是追蹤記錄必須完整所以回到第2章那個(gè)結(jié)論可觀測(cè)性不是畫在架構(gòu)圖角落里的裝飾而是貫穿全局的必備基礎(chǔ)設(shè)施。沒有它上面的排查流程一步都走不動(dòng)。我個(gè)人這些年的體會(huì)是圖解AI應(yīng)用架構(gòu)設(shè)計(jì)本質(zhì)上是在和時(shí)間賽跑。AI應(yīng)用變化太快一張圖今天畫完可能下周就過(guò)時(shí)了。所以我不把畫圖當(dāng)成交付物而是當(dāng)成推理工具——每次架構(gòu)評(píng)審前先更新圖畫不下去的地方往往就是設(shè)計(jì)還沒想清楚的地方。最后分享一個(gè)小技巧架構(gòu)圖上的每個(gè)方框都問自己一句“如果它掛了會(huì)發(fā)生什么”。答不上來(lái)的方框就是下一次線上事故的埋點(diǎn)。把這句話記在畫圖規(guī)范里能幫你避開大多數(shù)不必要的返工。