LLM部署全攻略:從量化選型到Agent工具調(diào)用)
最近在把端側(cè) Agent 從紙面方案真正跑到本地設(shè)備上最大的感受是端側(cè) LLM 部署這一關(guān)直接決定了一個(gè) Agent 項(xiàng)目能不能繼續(xù)往下走。端側(cè) Agent 不等于在手機(jī)上套一個(gè)聊天框它要的是推理、規(guī)劃、工具調(diào)用全鏈路都跑在本地而這一切的地基就是先把一個(gè)能穩(wěn)定運(yùn)行的 LLM 放到有限的硬件資源里。這篇文章是“深入理解端側(cè) Agent”系列的第二篇我會(huì)圍繞“端側(cè) LLM 部署”展開把模型選型、量化、推理框架、硬件適配、Agent 循環(huán)接線這幾塊串起來結(jié)合我在 RK3588、Jetson Orin 和普通 PC 上的實(shí)測(cè)結(jié)果給準(zhǔn)備自己搭端側(cè) Agent 的朋友一套可以直接照抄的路徑。如果你已經(jīng)在云端跑過大模型服務(wù)再轉(zhuǎn)頭做端側(cè)會(huì)明顯感覺到這不是“縮小版云端部署”這么簡(jiǎn)單。云端可以開 A100 堆顯存端側(cè)只有 8GB 內(nèi)存、一個(gè) NPU 或者 CPU甚至連 CUDA 都沒有。決定技術(shù)方案的往往不是“哪個(gè)框架最強(qiáng)”而是“這臺(tái)設(shè)備到底能容納多大模型、跑多快”。這篇文章我不會(huì)推一個(gè)萬能方案只把端側(cè)部署的決策邏輯和實(shí)操細(xì)節(jié)講透讓你在換設(shè)備、換模型時(shí)也能自己判斷。1. 端側(cè) Agent 與端側(cè) LLM 部署先想清楚要解決什么問題1.1 為什么不是繼續(xù)用云端 API很多人做 Agent 的第一反應(yīng)是接云端大模型 API這在原型階段確實(shí)最省事。但一旦想做成真正常駐運(yùn)行的硬件產(chǎn)品幾個(gè)問題就會(huì)冒出來第一是延遲不可控Agent 決策一次就要一兩秒再疊加網(wǎng)絡(luò)波動(dòng)交互體驗(yàn)會(huì)很差第二是斷網(wǎng)不可用工業(yè)巡檢、車機(jī)、戶外設(shè)備這種場(chǎng)景不可能一直在線第三是數(shù)據(jù)隱私用戶的語音、照片、傳感器數(shù)據(jù)傳到遠(yuǎn)端很多場(chǎng)景過不了合規(guī)和用戶信任這一關(guān)。端側(cè) Agent 的核心思路是讓 LLM 推理至少跑在端側(cè)同時(shí)把工具調(diào)用、狀態(tài)記錄、規(guī)則判斷這些邏輯也放在本地。需要說明的是“端側(cè) Agent”不一定是 100% 端側(cè)它也可以是混合架構(gòu)——本地跑一個(gè)小模型承接高頻和敏感請(qǐng)求云端兜底復(fù)雜推理Agent 自己根據(jù)任務(wù)難度決定走哪條路。這個(gè)分層很重要能幫你在成本和體驗(yàn)之間找到平衡。從部署角度看端側(cè) LLM 是 Agent 的“大腦”但大腦不是全部。一個(gè)完整的端側(cè) Agent 通常包含輸入模塊語音識(shí)別、視覺、文本、LLM 決策模塊、工具執(zhí)行模塊讀傳感器、查本地文件、調(diào)云端業(yè)務(wù) API、記憶模塊。LLM 部署得好不好直接影響決策質(zhì)量但整個(gè)系統(tǒng)的成敗往往是工具鏈和消息循環(huán)有沒有接對(duì)。所以我建議不要一上來就研究復(fù)雜 Agent 框架先把一個(gè) LLM 在端側(cè)跑通、并能穩(wěn)定調(diào)用工具后面再往上加框架會(huì)順手得多。1.2 端側(cè)部署的真正瓶頸內(nèi)存帶寬與上下文很多人以為端側(cè)部署的瓶頸是“算力不夠”實(shí)際經(jīng)驗(yàn)告訴我端側(cè)最缺的是內(nèi)存帶寬而不是 TOPS。LLM 在自回歸生成時(shí)每生成一個(gè) token都需要把全部模型權(quán)重從內(nèi)存讀一遍所以單 token 生成速度的上限約等于內(nèi)存帶寬除以模型文件大小。用理論值估算一下一個(gè) 7B 模型用 Q4 量化后大約是 4GB 權(quán)重如果設(shè)備的雙通道 DDR5 按 60GB/s 算理想情況下每秒最多生成約 15 個(gè) token。跑 3B 模型約 2GB這個(gè)數(shù)字會(huì)到 30 左右。所以“7B 模型一定比 3B 強(qiáng)”在端側(cè)并不成立如果你的設(shè)備帶寬只有 40GB/s硬上 7B 會(huì)讓 Agent 每一步都像網(wǎng)絡(luò)卡頓一樣用戶根本等不住。上下文長(zhǎng)度帶來的內(nèi)存開銷也不能忽視。模型跑起來后KV Cache 會(huì)隨著對(duì)話輪數(shù)變大。上下文從 2048 提到 8192KV Cache 在 7B 模型上可能多占幾百 MB 到 1GB對(duì)只有 8GB 內(nèi)存的設(shè)備來說是非常大的變動(dòng)。部署時(shí)不能只看模型文件大小要把上下文長(zhǎng)度、量化方式、運(yùn)行框架的額外開銷一起算進(jìn)去。2. 模型選型和量化第一步不是裝框架而是選模型2.1 端側(cè)模型底盤從 1B 到 8B部署之前先定任務(wù)再選模型。如果 Agent 只需要做簡(jiǎn)單的意圖判斷、文本摘要、固定流程問答1B~3B 的模型完全夠用如果要做多輪對(duì)話加工具調(diào)用3B~8B 才比較穩(wěn)。我實(shí)測(cè)下來1.5B 模型做簡(jiǎn)單指令還可以但一旦同時(shí)給四五個(gè)工具它經(jīng)常編造不存在的參數(shù)甚至輸出一堆無法解析的偽 JSON3B 以上會(huì)明顯改善7B 在工具調(diào)用成功率上又高一個(gè)檔次代價(jià)是速度更慢。中文場(chǎng)景優(yōu)先考慮 Qwen 系列指令跟隨和工具調(diào)用能力在小模型里比較靠前英文場(chǎng)景可以看 Llama 3.2 1B/3B 和 Phi-3 系列要跑多模態(tài)視覺 Agent就去看 Qwen2-VL 或者 MiniCPM-V 這類帶視覺編碼器的模型。我這里做的不是拉踩是端側(cè)項(xiàng)目里最符合“穩(wěn)”這個(gè)字的組合。選擇時(shí)還要看模型是否原生支持 function calling。有些模型經(jīng)過指令微調(diào)后可以用“輸出 JSON”的方式調(diào)用工具但原生支持工具調(diào)用的模型在格式穩(wěn)定性上會(huì)高很多。Qwen2.5 系列和 Llama 3.x 系列基本都原生支持工具調(diào)用Phi-3 的調(diào)用格式則需要額外適配。這點(diǎn)在選型時(shí)比榜單分?jǐn)?shù)更重要。2.2 量化不是可選項(xiàng)GGUF、AWQ 與精度取舍端側(cè)幾乎必須量化不是“可選項(xiàng)”。最常見的做法是用 GGUF 格式加 Q4_K_M 量化這是 llama.cpp/Ollama 生態(tài)的事實(shí)標(biāo)準(zhǔn)。Q4 能把 7B 模型的權(quán)重從約 14GBFP16壓到約 4.3GB內(nèi)存和加載壓力都小很多質(zhì)量損失在多數(shù)場(chǎng)景下能接受。如果對(duì)精度比較敏感可以升到 Q5_K_M體積和速度的代價(jià)都不大Q8_0 質(zhì)量更接近原始權(quán)重但體積基本到 7~8GB端側(cè)通常不劃算。AWQ 和 GPTQ 是另一條路通常配合 vLLM、TensorRT-LLM 使用在 NVIDIA GPU 上表現(xiàn)不錯(cuò)但在純 CPU、NPU 設(shè)備上支持度不如 GGUF。所以我給端側(cè)初學(xué)者的建議是先無腦跑 Q4_K_M實(shí)測(cè)效果不行再升 Q5_K_M不要一上來追求 Q8 或者 FP16跑不動(dòng)的話什么精度都白搭。如何在 Ollama 里指定量化版Ollama 標(biāo)簽體系里常見qwen2.5:3b默認(rèn)就是 Q4 量化也可以用ollama pull qwen2.5:7b-instruct-q5_K_M這種方式拉指定 tag。如果要用 llama.cpp 手動(dòng)跑從模型社區(qū)下載 GGUF 文件之后直接加載即可不需要自己轉(zhuǎn)格式除非你要把 safetensors 轉(zhuǎn)成 GGUF那才需要調(diào)用轉(zhuǎn)換腳本。2.3 模型選型速查表我在下面列了一個(gè)“先別折騰直接用這個(gè)組合”的參考表基于常見設(shè)備和預(yù)算整理量化方式默認(rèn) Q4_K_M。場(chǎng)景推薦模型量化后體積內(nèi)存占用參考適用設(shè)備輕量問答、意圖識(shí)別Qwen2.5-1.5B約 1GB2GB 以內(nèi)樹莓派 5、手機(jī)、低端盒子多輪對(duì)話 小規(guī)模工具調(diào)用Qwen2.5-3B / Llama 3.2-3B約 2GB4GB 左右RK3588、8GB Jetson、手機(jī)復(fù)雜工具調(diào)用、中文 AgentQwen2.5-7B / GLM-4-9B約 4.5~6GB8GB 起步Jetson Orin、高配開發(fā)板、PC英文摘要、英語 AgentLlama 3.2-3B / Phi-3.5-mini約 2GB4GB 左右主流端側(cè)設(shè)備視覺 文本多模態(tài)Qwen2-VL-2B / MiniCPM-V 2.6約 3~8GB8GB 起步Jetson Orin、大內(nèi)存 RK3588注意“內(nèi)存占用參考”不是只算模型權(quán)重還包括 KV Cache、系統(tǒng)、Agent 服務(wù)進(jìn)程。8GB 設(shè)備跑 7B 模型最好提前把其他大進(jìn)程清掉否則很容易 OOM。3. 推理框架與硬件匹配幾個(gè)主流方案的對(duì)比3.1 Ollama 與 llama.cpp入門最快的兩兄弟Ollama 是最適合端側(cè) Agent 起步的推理框架。它把模型管理、量化、服務(wù)化封裝得很好安裝完直接ollama pull拉模型然后ollama serve起一個(gè) OpenAI 兼容的 HTTP 服務(wù)。Agent 程序只需要把請(qǐng)求發(fā)給http://127.0.0.1:11434/v1完全不用管底層加載邏輯。它的缺點(diǎn)是想深度調(diào)優(yōu)比較難例如你想自定義采樣器、做模型微調(diào)后的特殊處理還是會(huì)受限。llama.cpp 是整個(gè) GGUF 生態(tài)的底層引擎可定制性高支持 CUDA、Vulkan、Metal 多種后端也自帶llama-server服務(wù)端。如果要在 Jetson 上跑且想用 GPU我一般直接用 llama.cpp 編譯一個(gè)帶 CUDA 的后端比套 Ollama 更可控。缺點(diǎn)是所有編譯、參數(shù)配置都要自己來對(duì)不太熟 CMake 的新手有門檻。我的選擇邏輯是第一次驗(yàn)證模型效果用 Ollama五分鐘跑通后續(xù)性能優(yōu)化或者要上 Jetson CUDA再切到 llama.cpp。不要在原型階段就開始做底層優(yōu)化容易浪費(fèi)時(shí)間。3.2 RK3588、Jetson Orin 與手機(jī) SoC 上的差異不同硬件對(duì)部署方案的影響比框架還大。RK3588 是很多端側(cè)盒子、開發(fā)板的首選CPU 強(qiáng)、內(nèi)存可到 32GB但它的 NPU 在 LLM 加速上支持有限。我實(shí)測(cè)在 RK3588 上直接跑 llama.cpp 的 CPU 版3B 模型能有 8~12 token/s7B 模型掉到 3~5 token/s而且散熱差了還會(huì)再降。如果你想壓榨 RK3588核彈級(jí)方案是走 RKLLM 工具鏈把模型轉(zhuǎn)成 NPU 能跑的格式但轉(zhuǎn)換工具鏈只支持部分模型架構(gòu)而且算子優(yōu)化要花不少時(shí)間。Jetson Orin 系列是另一條線因?yàn)閹?CUDAllama.cpp 可以直接用 GPU 跑。Orin Nano 8GB 跑 7B Q4 我見過 15~25 token/sOrin NX 16GB 可以到 25~40 token/s比 RK3588 舒服很多。缺點(diǎn)是價(jià)格高、功耗也偏高不是所有產(chǎn)品都承受得起。手機(jī) SoC 則是另一個(gè)戰(zhàn)場(chǎng)高通、聯(lián)發(fā)科都有各自的 AI 加速庫配合 ExecuTorch、MLC-LLM、TFLite 這類移動(dòng)端框架可以做得很輕但工程復(fù)雜度顯著上升適合有移動(dòng)端開發(fā)資源的團(tuán)隊(duì)。所以我常跟朋友說選硬件之前先算一筆賬——你的產(chǎn)品是插電還是電池供電能不能接受 15W 功耗目標(biāo)用戶最常卡在內(nèi)存還是網(wǎng)絡(luò)這些問題比選框架更早決定成敗。3.3 API 兼容層把推理服務(wù)轉(zhuǎn)成 OpenAI 風(fēng)格接口無論用 Ollama 還是 llama.cpp我都建議把推理服務(wù)抽象成 OpenAI 兼容接口。這么做的好處是Agent 代碼只需要寫一遍以后換框架、換設(shè)備只需改base_url。Ollama 的/v1/chat/completions、llama.cpp 的llama-server的/v1/chat/completions、MLC-LLM 也提供 OpenAI 風(fēng)格接口生態(tài)里已經(jīng)把這個(gè)當(dāng)成默認(rèn)規(guī)范了。代碼里最簡(jiǎn)單的連接方式是這樣from openai import OpenAI client OpenAI( base_urlhttp://127.0.0.1:11434/v1, api_keyollama, # 本地服務(wù)不會(huì)校驗(yàn) key傳什么都行 ) resp client.chat.completions.create( modelqwen2.5:3b, messages[{role: user, content: 用一句話介紹你自己}], temperature0.3, ) print(resp.choices[0].message.content)只要把模型名和本地地址換成對(duì)應(yīng)推理服務(wù)的這段代碼在各種端側(cè)設(shè)備上都能復(fù)用。這也是做 Agent 項(xiàng)目最重要的“可移植性”思維模型可以換、設(shè)備可以換但上層業(yè)務(wù)邏輯穩(wěn)定不動(dòng)。4. 實(shí)操在端側(cè)跑通一個(gè)能自動(dòng)決策的 Agent4.1 環(huán)境準(zhǔn)備與最小的 LLM 服務(wù)我以 RK3588 開發(fā)板為例裝好 Ubuntu 之后先裝 Ollama。這里強(qiáng)調(diào)一下網(wǎng)上curl -fsSL https://ollama.com/install.sh | sh這種方式最省事如果你對(duì)管道執(zhí)行腳本不放心可以手動(dòng)從官網(wǎng)下載壓縮包解壓只是多幾步環(huán)境變量配置。# 安裝 Ollama curl -fsSL https://ollama.com/install.sh | sh # 拉取一個(gè) 3B 模型默認(rèn) Q4 量化 ollama pull qwen2.5:3b # 啟動(dòng)服務(wù)并監(jiān)聽局域網(wǎng) OLLAMA_HOST0.0.0.0:11434 ollama serveJetson Orin 如果想用 GPU 加速更推薦直接編譯 llama.cppgit clone https://github.com/ggerganov/llama.cpp cd llama.cpp cmake -B build -DGGML_CUDAON -DCMAKE_BUILD_TYPERelease cmake --build build --config Release -j $(nproc)編譯完成后把 GGUF 模型放到任意目錄用llama-server啟動(dòng)一個(gè) OpenAI 兼容接口。命令大致是./build/bin/llama-server -m /path/to/qwen2.5-7b-instruct-q4_k_m.gguf -c 4096 --port 8080啟動(dòng)完成后先用 curl 驗(yàn)證服務(wù)是否正常。這一步能幫你把“模型加載問題”和“Agent 代碼問題”徹底隔離開curl http://127.0.0.1:11434/v1/chat/completions \ -H Content-Type: application/json \ -d { model: qwen2.5:3b, messages: [{role: user, content: 你好}], stream: false }如果返回正常 JSON說明 LLM 服務(wù)已就緒接下來就可以接 Agent 邏輯了。4.2 工具調(diào)用Function Calling的完整鏈路Agent 和普通聊天最大的區(qū)別就是會(huì)調(diào)用工具。我通常把 Agent 決策流程拆成四步LLM 根據(jù)用戶輸入判斷“需不需要工具” → 返回一個(gè)結(jié)構(gòu)化的 tool_calls 請(qǐng)求 → Agent 執(zhí)行對(duì)應(yīng)工具并把結(jié)果回填到消息列表 → LLM 結(jié)合工具結(jié)果生成最終回答。為了讓模型穩(wěn)定輸出“想調(diào)用哪個(gè)工具”我們需要在請(qǐng)求里附帶tools字段。這是一個(gè)標(biāo)準(zhǔn)的 OpenAI 風(fēng)格工具描述我在端側(cè)項(xiàng)目里常寫類似這樣的定義tools [ { type: function, function: { name: get_weather, description: 查詢某個(gè)城市當(dāng)天的天氣情況返回天氣狀態(tài)和溫度, parameters: { type: object, properties: { city: {type: string, description: 城市名例如北京、上海} }, required: [city] } } }, { type: function, function: { name: get_current_time, description: 獲取當(dāng)前系統(tǒng)時(shí)間返回年月日和時(shí)分秒, parameters: {type: object, properties: {}} } } ]工具描述寫得越明確模型就越少亂開會(huì)話。比如get_weather的 description 里寫了“返回天氣狀態(tài)和溫度”模型就能知道這個(gè)工具是拿實(shí)時(shí)信息的。如果工具描述模糊它會(huì)傾向于自己瞎編天氣這是端側(cè) Agent 最常見的失敗原因之一。4.3 全套 Agent 循環(huán)代碼下面是一套可直接運(yùn)行的 Agent 循環(huán)我用 requests 而不是 OpenAI SDK這樣在無外網(wǎng)依賴的純內(nèi)網(wǎng)環(huán)境里也能跑也方便你看清協(xié)議細(xì)節(jié)。import json import time import requests MODEL qwen2.5:3b OLLAMA_BASE http://127.0.0.1:11434/v1 def get_current_time(): return time.ctime() def get_weather(city): # 這里只是演示正常應(yīng)該查本地緩存或云端 API return {city: city, weather: 晴, temperature: 24} def run_tool(name, args): if name get_current_time: return get_current_time() if name get_weather: return get_weather(args.get(city, 未知城市)) return {error: ftool not found: {name}} def ask_agent(user_text): messages [ {role: system, content: 你是一個(gè)運(yùn)行在本地設(shè)備上的助手。當(dāng)用戶需要實(shí)時(shí)信息時(shí)應(yīng)該先調(diào)用工具獲取數(shù)據(jù)不要憑空編造。工具結(jié)果可能是一個(gè) JSON 字符串你需要把它整理成自然語言回復(fù)。}, {role: user, content: user_text}, ] for step in range(8): # 限制最大輪數(shù)防止循環(huán)失控 payload { model: MODEL, messages: messages, tools: tools, temperature: 0.3, max_tokens: 512, stream: False, } resp requests.post(f{OLLAMA_BASE}/chat/completions, jsonpayload, timeout60) resp.raise_for_status() data resp.json() msg data[choices][0][message] # 先把 assistant 消息追加進(jìn)歷史保證上下文連續(xù) messages.append({ role: assistant, content: msg.get(content) or , tool_calls: msg.get(tool_calls), }) # 如果沒有工具調(diào)用說明 LLM 已給出最終回答 if not msg.get(tool_calls): return msg.get(content) or # 否則逐個(gè)執(zhí)行工具把結(jié)果回填 for tc in msg[tool_calls]: fn tc[function] try: args json.loads(fn.get(arguments) or {}) except json.JSONDecodeError: args {_parse_error: fn.get(arguments)} result run_tool(fn[name], args) messages.append({ role: tool, tool_call_id: tc.get(id, fstep-{step}), content: json.dumps(result, ensure_asciiFalse), }) return 已超過最大輪數(shù)請(qǐng)稍后再試 if __name__ __main__: print(ask_agent(現(xiàn)在幾點(diǎn)了)) print(ask_agent(幫我查一下杭州的天氣))這段代碼踩中了我前面說的所有環(huán)節(jié)工具定義、assistant 消息回放、工具結(jié)果回填、輪數(shù)上限。唯一要注意的是“tool_call_id” 必須和模型返回的id一致否則有些服務(wù)端會(huì)拒絕消息序列。Ollama 大部分情況會(huì)給你一個(gè) id萬一沒有我就用step-N兜底。4.4 參數(shù)調(diào)整對(duì) Agent 行為的影響同樣的模型、同樣的工具定義參數(shù)設(shè)得不對(duì)Agent 表現(xiàn)會(huì)天差地別。我在端側(cè)項(xiàng)目里的默認(rèn)值如下你可以照著先跑再按需調(diào)整temperature 設(shè) 0.2~0.4。Agent 決策場(chǎng)景要可控性優(yōu)先太高會(huì)讓它隨機(jī)亂調(diào)工具。max_tokens 單次設(shè) 256~512 就夠。工具調(diào)用階段用不到長(zhǎng)文本輸出答非所問的長(zhǎng)篇大論反而是負(fù)擔(dān)。num_ctx上下文窗口設(shè) 4096 起步最多 8192再大內(nèi)存吃不住速度也掉得厲害。stream 在工具調(diào)用循環(huán)里建議關(guān)掉等拿到完整結(jié)構(gòu)再處理會(huì)省很多麻煩如果是面向用戶打字機(jī)效果只在最終回答階段開啟。如果模型對(duì) function calling 支持不好可以退而求其次用 JSON mode在 system prompt 里強(qiáng)制要求模型只輸出 JSON然后自己解析action和params。這個(gè)方法“能用但不舒服”因?yàn)槟阈枰幚砀鞣N格式異常。所以我通常把原生 tool calling 當(dāng)作第一選項(xiàng)JSON mode 只做 fallback。5. 端側(cè) Agent 部署中的經(jīng)典坑與排查方法5.1 模型加載慢、OOM、卡死端側(cè)部署最常見的坑就是內(nèi)存不夠。你看到 8GB 開發(fā)板以為能跑 7B 模型結(jié)果系統(tǒng)占 1.5GB、Agent 服務(wù)占 0.5GB、推理框架再占一堆KV Cache 一漲進(jìn)程直接被 OOM Killer 干掉。我排查的第一條命令永遠(yuǎn)是free -h先看剩余內(nèi)存再看是不是已經(jīng)觸發(fā)過 OOM。如果內(nèi)存吃緊優(yōu)先級(jí)是這樣的先砍上下文長(zhǎng)度從 8192 降到 4096 試試再換更激進(jìn)的量化Q5 改 Q4最后才考慮換更小模型。不要一生氣直接買更大內(nèi)存的主板很多情況下是 KV Cache 和框架開銷在作怪縮小上下文就立竿見影。模型首次加載慢也很常見。Ollama 或 llama.cpp 冷啟動(dòng)需要把幾個(gè) GB 的權(quán)重從磁盤讀到內(nèi)存如果用的是 TF 卡或機(jī)械盤會(huì)非常慢。解決方式是讓服務(wù)常駐不要每請(qǐng)求一次就啟動(dòng)一次Ollama 可以設(shè)置keep_alive例如在請(qǐng)求里帶keep_alive: 5m或者在 Evironment 里調(diào)大默認(rèn)?;顣r(shí)間。如果首 token 延遲是產(chǎn)品痛點(diǎn)盡量用 NVMe 或者至少是高素質(zhì) eMMC。5.2 工具調(diào)用失效與循環(huán)失控我踩過最深的坑是 Agent 陷入死循環(huán)它一遍遍調(diào)用同一個(gè)工具不把工具結(jié)果當(dāng)回事或者把返回的 JSON 當(dāng)作要執(zhí)行的指令。這種問題的根源通常是工具結(jié)果沒被正確放回消息歷史或者模型沒有足夠強(qiáng)的“停止能力”。解法有三個(gè)層面第一代碼層面限制最大輪數(shù)我一般設(shè) 6~8 輪到頂直接返回第二prompt 層面明確“如果工具返回結(jié)果為空或報(bào)錯(cuò)就如實(shí)告訴用戶不要重復(fù)調(diào)用”第三工具層面做結(jié)果校驗(yàn)例如天氣工具查詢失敗時(shí)不要把原始異常堆棧丟給模型而應(yīng)該返回一個(gè)干凈的{error: 查詢失敗}模型更容易理解。另一個(gè)典型問題是模型串工具參數(shù)。其實(shí)就是函數(shù)名和 description 寫得太差或者一個(gè)模型一次被塞了十幾個(gè)工具。端側(cè)模型沒有云端那么大容量工具數(shù)量控制在 5~8 個(gè)以內(nèi)名字要短、含義要唯一。工具多了正確率下降得非???。5.3 實(shí)測(cè)速度參考與性能預(yù)期下面是幾組實(shí)測(cè)參考不是基準(zhǔn)測(cè)試只是我手頭設(shè)備和社區(qū)同規(guī)格設(shè)備上的常見水平。速度會(huì)受散熱、固件、量化策略影響建議拿到設(shè)備后自己在目標(biāo)模型上跑一遍。設(shè)備推理引擎模型實(shí)測(cè)參考RK358832GB 內(nèi)存llama.cpp CPUQwen2.5-3B Q4_K_M8~12 token/sRK358832GB 內(nèi)存llama.cpp CPUQwen2.5-7B Q4_K_M3~5 token/sJetson Orin Nano 8GBllama.cpp CUDAQwen2.5-7B Q4_K_M15~25 token/sJetson Orin NX 16GBllama.cpp CUDAQwen2.5-7B Q4_K_M25~40 token/sApple M116GBOllama MetalLlama 3.2-3B Q4_K_M20~30 token/s看到這些數(shù)字你就明白為什么端側(cè) Agent 設(shè)計(jì)時(shí)最好把“一次決策需要的 token 數(shù)”壓到最低。工具調(diào)用輪數(shù)多、系統(tǒng)提示詞長(zhǎng)、上下文回放過長(zhǎng)都會(huì)顯著拉慢每個(gè)請(qǐng)求。所以我在端側(cè)項(xiàng)目里習(xí)慣于精簡(jiǎn) system prompt把歷史消息裁剪到最近幾輪而不是把所有對(duì)話都塞進(jìn)去。5.4 端側(cè) Agent 部署問題速查表癥狀可能原因處置方法首次啟動(dòng)極慢模型從磁盤冷加載服務(wù)常駐、用 SSD、調(diào)大 keep_alive進(jìn)程被 kill內(nèi)存不足降上下文長(zhǎng)度、換更小模型、清理后臺(tái)進(jìn)程中文輸出亂碼英文 tokenizer 模型換 Qwen 等中文優(yōu)化模型并在 system 里指定中文回復(fù)工具調(diào)用格式錯(cuò)模型不支持原生 function calling換支持工具調(diào)用的模型或降 temperature 后重試同一工具反復(fù)調(diào)用工具結(jié)果未回填 / prompt 缺停止指令檢查 tool_call_id 和消息順序增加輪數(shù)上限Jetson 編譯報(bào)錯(cuò)CUDA 環(huán)境不匹配用 JetPack 統(tǒng)一版本再編譯確認(rèn) DD 架構(gòu)設(shè)置生成內(nèi)容重復(fù)溫度太低或上下文被污染清空歷史、低溫度會(huì)導(dǎo)致重復(fù)時(shí)適度提高到 0.55.5 影響范圍哪些真實(shí)場(chǎng)景值得端側(cè) Agent 落地聊完部署技巧再回到業(yè)務(wù)視角。端側(cè) Agent 目前最適合三類場(chǎng)景一是隱私敏感型醫(yī)療、金融、辦公設(shè)備上的數(shù)據(jù)處理不出終端本地模型 本地工具循環(huán)天然有優(yōu)勢(shì)二是弱網(wǎng)/無網(wǎng)環(huán)境工業(yè)巡檢、倉儲(chǔ) AGV、車載語音斷網(wǎng)也要能干活三是對(duì)延遲要求苛刻的實(shí)時(shí)交互例如語音助手和機(jī)器人本地推理省掉了往返云端的 300ms~1s。這些場(chǎng)景共同點(diǎn)是“物理世界交互”多于“純文本生成”所以 Agent 是否好用很大程度取決于工具鏈和硬件配套是否完整。只部署一個(gè) LLM 是不夠的還得把麥克風(fēng)、攝像頭、傳感器、本地?cái)?shù)據(jù)庫接好。這也是我把這篇文章重心放在“LLM 部署 工具循環(huán)”而不是“聊天機(jī)器人”的原因。端側(cè) Agent 的競(jìng)爭(zhēng)點(diǎn)不在模型本身而在系統(tǒng)整合的穩(wěn)定度。個(gè)人建議是先用一個(gè)成熟的小模型在目標(biāo)設(shè)備上把完整鏈路跑通再根據(jù)真實(shí)數(shù)據(jù)決定是升模型還是優(yōu)化工具。端側(cè)部署這件事很多問題只有真機(jī)通電跑起來才能發(fā)現(xiàn)紙面推演再合理也不如一次free -h來得實(shí)在。