評(píng)測(cè)與Agent容錯(cuò)全路線)
我現(xiàn)在刷信息流的時(shí)候滿屏都是“LLM是什么”“大模型框架”“本地跑 GGUF”“LLM as Judge”“Agent 出錯(cuò)怎么排查”這類熱搜詞??聪聛?lái)最大的感受是想學(xué) LLM 的人很多但真正能一條線走通的人很少。大部分人卡在同一個(gè)路口——概念看了不少真到自己動(dòng)手做一個(gè)能用、能評(píng)、能穩(wěn)定上線的應(yīng)用又不知道從哪里下手。這個(gè)系列我就打算按一條完整的路線來(lái)寫《深入學(xué)習(xí) LLM(一)》先解決“地基”問(wèn)題——模型到底是什么、工具鏈怎么選、本地怎么跑、數(shù)據(jù)怎么微調(diào)、效果怎么評(píng)測(cè)、Agent 怎么做可靠。后面再逐步展開更深的內(nèi)容。內(nèi)容偏工程實(shí)踐適合三類人剛?cè)腴T的開發(fā)者、準(zhǔn)備在業(yè)務(wù)里落地大模型應(yīng)用的工程師、以及想搞明白“大模型項(xiàng)目為什么總在最后一步翻車”的產(chǎn)品和技術(shù)負(fù)責(zé)人。這一篇的信息量會(huì)比較大我會(huì)盡量少講空話多放可以直接抄走的判斷標(biāo)準(zhǔn)、參數(shù)和踩坑記錄。1. 先把基礎(chǔ)打?qū)LM 到底是什么1.1 從“預(yù)測(cè)下一個(gè)詞”到“能力涌現(xiàn)”很多人對(duì) LLM 的第一印象是“特別聰明、什么都會(huì)”。但如果只保留一句準(zhǔn)確的話來(lái)描述它應(yīng)當(dāng)是LLM 是一個(gè)做“下一個(gè)詞預(yù)測(cè)”的概率模型。給定一段上文它計(jì)算下一個(gè)最可能出現(xiàn)的詞嚴(yán)格來(lái)說(shuō)是 token是什么然后不斷重復(fù)這個(gè)過(guò)程生成整段內(nèi)容。這個(gè)本質(zhì)決定了它的很多脾氣。比如它會(huì)一本正經(jīng)地編造不存在的引用因?yàn)閷?duì)它來(lái)說(shuō)“編一個(gè)像樣的引用”和“說(shuō)出真實(shí)引用”在概率上都是合法的延續(xù)它也不擅長(zhǎng)算術(shù)因?yàn)榘褦?shù)字拆成 token 之后計(jì)算路徑并不穩(wěn)定。理解這一點(diǎn)能避免你對(duì)模型產(chǎn)生不切實(shí)際的期待。支撐這一能力的基礎(chǔ)架構(gòu)是 Transformer。它最關(guān)鍵的設(shè)計(jì)是自注意力機(jī)制Self-Attention簡(jiǎn)單理解就是模型在處理某個(gè)詞的時(shí)候會(huì)動(dòng)態(tài)計(jì)算它和序列中其他詞的相關(guān)程度從而決定“該重點(diǎn)參考哪些上下文”。這也是為什么 LLM 能做“根據(jù)前文理解后文”而不是像老式 n-gram 模型那樣只看緊鄰的幾個(gè)詞。在訓(xùn)練流程上主流模型基本都走“三段式”預(yù)訓(xùn)練在海量文本上做自監(jiān)督學(xué)習(xí)目標(biāo)是預(yù)測(cè)下一個(gè)詞。這一步讓模型獲得語(yǔ)言能力和世界知識(shí)。指令微調(diào)SFT用大量“用戶問(wèn)題 標(biāo)準(zhǔn)回答”對(duì)模型做監(jiān)督訓(xùn)練讓它學(xué)會(huì)服從指令、用對(duì)話形式回答。對(duì)齊RLHF / DPO 等讓模型輸出更符合人類偏好比如更有幫助、更安全、更簡(jiǎn)潔。到了指令微調(diào)之后模型才表現(xiàn)出大家熟知的指令跟隨Instruction Following、**上下文學(xué)習(xí)In-Context Learning和一定程度的思維鏈Chain-of-Thought**能力。這些能力被統(tǒng)稱為“涌現(xiàn)能力”聽起來(lái)很玄但從工程視角看你可以把它們理解為“模型在語(yǔ)料中見過(guò)足夠多類似模式后產(chǎn)生的一種復(fù)雜模式匹配”。不需要把它當(dāng)成魔法只需要知道這是一把雙刃劍——模式匹配既讓它靈活也讓它容易“幻覺(jué)”。1.2 為什么大模型這么“聽話”指令對(duì)齊與提示工程“聽話”這個(gè)詞很形象。一個(gè) Base 模型只有預(yù)訓(xùn)練階段的模型你問(wèn)它問(wèn)題它大概率會(huì)續(xù)寫一段百科式文本而不是正經(jīng)回答你。真正讓它“變成對(duì)話助手”的是對(duì)齊階段的數(shù)據(jù)和訓(xùn)練方式。所以你在寫 Prompt 時(shí)本質(zhì)上是在和“對(duì)齊后的默認(rèn)行為”打交道。常用 Prompt 結(jié)構(gòu)包括三部分System 指令定義模型角色、任務(wù)目標(biāo)、輸出格式。User 輸入具體請(qǐng)求。Assistant 輸出模型回答。實(shí)操中我強(qiáng)烈建議你對(duì)任何生產(chǎn)級(jí) Prompt 都顯式寫 System 指令哪怕很簡(jiǎn)單。這能明顯減少模型“自由發(fā)揮”的概率。舉個(gè)最簡(jiǎn)單的例子你讓它“總結(jié)會(huì)議紀(jì)要”如果只給一句原文它可能輸出一個(gè)帶小標(biāo)題的長(zhǎng)篇總結(jié)如果 System 里寫明“只輸出 5 條結(jié)論每條不超過(guò) 20 字不要解釋”輸出就會(huì)穩(wěn)定得多。幾個(gè)經(jīng)常被忽略但很重要的參數(shù)意識(shí)Temperature控制隨機(jī)性。做抽取、分類、代碼生成時(shí)建議調(diào)到 0~0.2做創(chuàng)意寫作、頭腦風(fēng)暴可以 0.7~1.0。上下文窗口窗口越大不等于效果越好。模型對(duì)中間內(nèi)容的關(guān)注度往往弱于開頭和結(jié)尾這在技術(shù)上稱為“l(fā)ost in the middle”。需要長(zhǎng)上下文時(shí)把關(guān)鍵指令放在 System 或末尾比堆在中間更有效。輸出長(zhǎng)度限制 max_tokens 能顯著避免模型啰嗦也可以降低成本。提示入門階段做一個(gè)“溫度對(duì)比實(shí)驗(yàn)”特別有幫助。用同一個(gè)高質(zhì)量 Prompttemperature 分別設(shè)為 0.2 和 0.9各生成 10 次觀察輸出的穩(wěn)定程度。你會(huì)發(fā)現(xiàn)不少業(yè)務(wù)場(chǎng)景里低 temperature 的穩(wěn)定性遠(yuǎn)比你想象的重要。2. 學(xué)習(xí)路線與工具鏈選型框架不是萬(wàn)能的2.1 先跑通 API再碰本地模型我發(fā)現(xiàn)很多新人一上來(lái)就想本地部署大模型理由通常是“不想花錢”“有隱私需求”或“聽起來(lái)很酷”。這些理由可以理解但從學(xué)習(xí)效率看第一條路徑應(yīng)該是調(diào)用 API。原因很簡(jiǎn)單API 讓你把精力集中在 Prompt、邏輯、評(píng)估這些真正重要的工程問(wèn)題上而不是被 CUDA 版本、內(nèi)存不足、量化效果這些環(huán)境問(wèn)題勸退。等你用 API 跑通一個(gè)完整小應(yīng)用比如“文檔問(wèn)答”或“角色扮演機(jī)器人”之后再回到本地部署你會(huì)更明白本地模型該調(diào)什么、不該調(diào)什么。否則你會(huì)在模型下載和依賴安裝上花掉一周卻連“這個(gè)模型的效果到底好不好”都判斷不了。什么時(shí)候需要用 LangChain 這類框架我認(rèn)為有清晰判斷標(biāo)準(zhǔn)需要串聯(lián)多個(gè)模型調(diào)用或工具調(diào)用時(shí)比如“先判斷意圖 → 再查數(shù)據(jù)庫(kù) → 再生成回答”的工作流框架的 Chain / Graph 能力確實(shí)省事。需要多種模型切換時(shí)LiteLLM 這類工具能統(tǒng)一 API 格式切換到不同供應(yīng)商不修代碼。需要成熟組件時(shí)比如文檔切分、向量檢索的封裝LlamaIndex 比你自己寫更穩(wěn)。什么時(shí)候不適合用框架當(dāng)你的邏輯只有“一個(gè) Prompt 進(jìn)去一個(gè)輸出出來(lái)”時(shí)別用框架。直接調(diào)用 SDK 更簡(jiǎn)單、更好排查、依賴更少??蚣艿膬?yōu)勢(shì)在抽象和編排但代價(jià)是隱藏細(xì)節(jié)。一旦輸出不符合預(yù)期你得先判斷是模型的問(wèn)題、Prompt 的問(wèn)題、還是框架內(nèi)部做了你不知道的變換。這會(huì)浪費(fèi)大量時(shí)間。我自己的項(xiàng)目里大概 70% 的調(diào)用是直接寫 SDK 完成的只有 30% 涉及多步編排才引入框架。這個(gè)比例供你參考。2.2 主流框架和個(gè)人“LLM Wiki”給還沒(méi)接觸過(guò)框架的讀者列一個(gè)快速對(duì)比工具/框架定位適合場(chǎng)景注意點(diǎn)LangChain通用編排框架多步驟 Agent、工具調(diào)用、復(fù)雜工作流版本升級(jí)快API 變動(dòng)頻繁鎖定版本LlamaIndex數(shù)據(jù)檢索與知識(shí)庫(kù)文檔問(wèn)答、RAG 場(chǎng)景對(duì)結(jié)構(gòu)化數(shù)據(jù)的索引能力較強(qiáng)LiteLLM統(tǒng)一 API 網(wǎng)關(guān)多模型切換、成本管理簡(jiǎn)單場(chǎng)景沒(méi)必要引入LM Studio本地 GUI 推理工具本地快速體驗(yàn)?zāi)P托Чm合調(diào)試不適合生產(chǎn)服務(wù)Ollama本地推理服務(wù)一鍵跑 GGUF 模型部署極簡(jiǎn)單但精細(xì)控制偏弱這里多提一句熱詞里的“LLM Wiki”。我認(rèn)識(shí)不少高質(zhì)量從業(yè)者幾乎每個(gè)人都有自己的“LLM 筆記庫(kù)”內(nèi)容不是概念抄錄而是項(xiàng)目記錄模型名字和版本、Prompt 版本、參數(shù)配置、評(píng)測(cè)結(jié)果、失敗樣例、成本記錄。這種做法非常重要因?yàn)?LLM 應(yīng)用的調(diào)試是高度實(shí)驗(yàn)性的沒(méi)有記錄你等于沒(méi)有積累。我建議你也建一個(gè)個(gè)人 LLM Wiki核心字段至少包括任務(wù)目標(biāo)、數(shù)據(jù)來(lái)源、模型與參數(shù)、Prompt 全文、評(píng)測(cè)指標(biāo)、失敗案例。每次實(shí)驗(yàn)都記錄一個(gè)月后回看你會(huì)發(fā)現(xiàn)自己避開了大量重復(fù)的坑。3. 本地部署實(shí)戰(zhàn)GGUF 量化和安卓手機(jī)運(yùn)行3.1 為什么選 GGUF 格式本地部署繞不開一件事怎么把動(dòng)輒幾十 GB 的模型塞進(jìn)你的顯卡或者內(nèi)存里。這時(shí)候 GGUF 格式就派上用場(chǎng)了。GGUF 是 llama.cpp 項(xiàng)目推出的模型格式核心特點(diǎn)是把所有東西打包成一個(gè)文件模型的權(quán)重、tokenizer 配置、特殊 token、元信息都包含在內(nèi)。相比傳統(tǒng)的 safetensors 格式GGUF 更適合 CPU 推理和邊緣設(shè)備因?yàn)樗鼘?duì)權(quán)重的編碼方式做了量化優(yōu)化。量化這個(gè)詞如果你第一次見可以用圖片來(lái)類比一張 4K 照片原圖很大壓成 JPEG 后變很小肉眼看差別不大。模型的量化也類似把原本用 16 位浮點(diǎn)數(shù)表示的權(quán)重轉(zhuǎn)成 4 位或 8 位表示模型體積大幅縮小推理時(shí)占用的內(nèi)存或顯存也降低很多質(zhì)量略有損失但通??山邮堋3R姷牧炕燃?jí)和取舍我放在表里量化等級(jí)位數(shù)模型體積7B 模型參照質(zhì)量損耗適用場(chǎng)景Q4_K_M4bit約 4.1G低消費(fèi)級(jí)顯卡/內(nèi)存的均衡選擇Q5_K_M5bit約 4.8G較低內(nèi)存稍充足時(shí)優(yōu)先Q6_K6bit約 5.7G很低質(zhì)量敏感場(chǎng)景Q8_08bit約 7.2G接近無(wú)損顯存足夠時(shí)的首選選型口訣顯存/內(nèi)存決定上限質(zhì)量敏感度決定檔位。8GB 顯存跑 7B 模型選 Q4_K_M 是最穩(wěn)的如果你確定模型質(zhì)量下降明顯再考慮降低模型規(guī)模比如換成 3B 或 1.5B而不是硬上高量化。3.2 在電腦上快速跑起來(lái)本地推理我建議從 Ollama 開始它是我試過(guò)對(duì)新手最友好的工具。安裝后拉模型即可# 拉取一個(gè)量化好的 7B 模型 ollama pull qwen2.5:7b-instruct-q4_K_M # 運(yùn)行并進(jìn)入交互式對(duì)話 ollama run qwen2.5:7b-instruct-q4_K_MOllama 支持通過(guò) Modelfile 自定義參數(shù)例如設(shè)置 temperatureFROM qwen2.5:7b-instruct-q4_K_M PARAMETER temperature 0.2如果你更愿意用底層一點(diǎn)的 llama.cpp流程也簡(jiǎn)單從 GitHub 克隆源碼編譯后直接用命令行推理。編譯前確認(rèn)架構(gòu)N 卡用 CUDA 加速純 CPU 則用原生版本git clone https://github.com/ggerganov/llama.cpp cd llama.cpp cmake -B build -DGGML_CUDAON cmake --build build --config Release -j 4實(shí)測(cè)下來(lái)影響推理速度的最大因素是內(nèi)存帶寬而不只是 CPU 算力。筆記本在純 CPU 情況下跑 7B Q4大約能到 5~8 token/秒能接受但不算流暢桌面高性能 CPU 能到 10 token/秒。如果你的預(yù)期是“像 ChatGPT 一樣秒回”本地小模型目前很難滿足這一點(diǎn)務(wù)必提前想清楚。提示跑本地模型時(shí)一定要確認(rèn)你使用的是量化版模型文件。很多人下載了一個(gè) 14GB 的原版 7B 模型還在抱怨內(nèi)存爆掉——量化和非量化的差別跑之前先看清楚。3.3 安卓本地運(yùn)行支持 Android 8 的方案熱詞里有“安卓本地運(yùn)行 GGUF 格式 LLM支持安卓 8”這個(gè)我專門驗(yàn)證過(guò)答案是可行但需要管理預(yù)期。最穩(wěn)的方案是 Termux。Termux 是安卓上的終端模擬器可以把它理解成手機(jī)上的一臺(tái) Linux 小機(jī)器。在 Termux 里編譯 llama.cpp 的 Android 版本然后加載你下載好的 GGUF 模型文件。步驟大致如下# 在 Termux 中 pkg update pkg install git cmake build-essential git clone https://github.com/ggerganov/llama.cpp cd llama.cpp # 在安卓上編譯 CPU 版本即可不需要 CUDA cmake -B build cmake --build build --config Release -j 4之后把 GGUF 文件放到手機(jī)存儲(chǔ)中運(yùn)行./build/bin/llama-cli -m /sdcard/Download/your-model.Q4_K_M.gguf -p 你好介紹一下你自己針對(duì) Android 8 的兼容性有幾點(diǎn)實(shí)測(cè)經(jīng)驗(yàn)盡量選擇aarch64 體系的手機(jī)也就是近幾年的主流 arm64 機(jī)型不要用老舊的 32 位系統(tǒng)。模型體積控制在2GB 以內(nèi)推薦 1.5B~3B 的 Q4 量化版本。7B 在手機(jī)上體驗(yàn)很差每生成一個(gè) token 都要等很久。手機(jī)內(nèi)存至少4GB 起步低于這個(gè)值建議放棄本地運(yùn)行的念頭。使用過(guò)程中手機(jī)會(huì)明顯發(fā)熱這是 CPU 滿載導(dǎo)致的正常現(xiàn)象長(zhǎng)時(shí)間運(yùn)行注意散熱。這類方案適合你“在通勤時(shí)研究一下 prompt 邏輯”但把手機(jī)當(dāng)成正經(jīng)推理服務(wù)器目前還不太現(xiàn)實(shí)。4. 用聊天記錄精調(diào) LLM從數(shù)據(jù)到 LoRA 的一條線4.1 為什么聊天記錄是好數(shù)據(jù)如果你想做一個(gè)特定風(fēng)格的對(duì)話機(jī)器人比如客服助手、特定人設(shè)的聊天機(jī)器人拿真實(shí)聊天記錄做微調(diào)是性價(jià)比很高的方案。理由很直接聊天記錄就是用戶和助手互動(dòng)的真實(shí)樣本里面包含你想要的語(yǔ)氣、問(wèn)題類型、回答風(fēng)格比人工編造的數(shù)據(jù)要自然得多。但聊天記錄不能直接用原因有三隱私風(fēng)險(xiǎn)大聊天記錄可能包含姓名、手機(jī)號(hào)、地址等敏感信息必須先脫敏。噪聲多大量消息是“嗯”“好的”“收到”這類無(wú)效內(nèi)容需要過(guò)濾。格式不統(tǒng)一不同來(lái)源的記錄字段都不一樣要整理成模型訓(xùn)練需要的結(jié)構(gòu)。一個(gè)簡(jiǎn)單的數(shù)據(jù)轉(zhuǎn)換思路是把原始記錄格式化成統(tǒng)一的 JSONL。假設(shè)原始聊天日志長(zhǎng)這樣[ {from: user, text: 你們發(fā)貨用哪家快遞}, {from: assistant, text: 默認(rèn)用順豐您下單后我會(huì)把單號(hào)發(fā)給您。} ]轉(zhuǎn)換成訓(xùn)練格式后每行是一條完整對(duì)話樣本符合 System/User/Assistant 結(jié)構(gòu){messages: [{role: system, content: 你是某店鋪的售后客服回答簡(jiǎn)短友好。}, {role: user, content: 你們發(fā)貨用哪家快遞}, {role: assistant, content: 默認(rèn)用順豐您下單后我會(huì)把單號(hào)發(fā)給您。}]}做數(shù)據(jù)清洗時(shí)我建議按這四步走去重同一條消息反復(fù)出現(xiàn)會(huì)放大模型對(duì)該內(nèi)容的過(guò)擬合。過(guò)濾刪除過(guò)短的、無(wú)意義的、純表情的對(duì)話。脫敏用規(guī)則或正則把手機(jī)號(hào)、郵箱、地址替換為占位符。重組把多輪對(duì)話切成不超過(guò)目標(biāo)上下文長(zhǎng)度的獨(dú)立樣本。注意任何來(lái)源的聊天記錄只要不是你自己生產(chǎn)的都要確認(rèn)數(shù)據(jù)合規(guī)性。清洗完數(shù)據(jù)再拿給模型訓(xùn)練是個(gè)人和團(tuán)隊(duì)都應(yīng)該養(yǎng)成的習(xí)慣。4.2 LoRA 微調(diào)實(shí)操注意點(diǎn)全量微調(diào)一個(gè)大模型對(duì)于個(gè)人開發(fā)者來(lái)說(shuō)不現(xiàn)實(shí)顯存不夠是一個(gè)方面另一個(gè)方面是你也不需要。用LoRALow-Rank Adaptation是目前的主流做法。它的思路是凍結(jié)原有模型參數(shù)只額外訓(xùn)練一小部分“旁路”參數(shù)。你可以把它想象成給模型加了一個(gè)“可拆卸的適配器”效果只影響你訓(xùn)練過(guò)的領(lǐng)域還會(huì)保留原有模型的通用能力。實(shí)際操作中我會(huì)優(yōu)先用這兩個(gè)訓(xùn)練方案LLaMA-Factory界面友好內(nèi)置了大量數(shù)據(jù)集格式支持適合快速實(shí)驗(yàn)。HuggingFace PEFT TRL更底層適合需要定制訓(xùn)練邏輯的團(tuán)隊(duì)。LoRA 的幾個(gè)關(guān)鍵參數(shù)直接給結(jié)論rank秩通常 8~32 之間。rank 越大可學(xué)習(xí)的參數(shù)越多但也更容易過(guò)擬合。對(duì)話風(fēng)格類任務(wù)8~16 夠用。alpha一般為 rank 的 2 倍是 LoRA 輸出的縮放因子。學(xué)習(xí)率1e-4 到 2e-4 是常見區(qū)間不要太大否則容易崩。epochs對(duì)話數(shù)據(jù)量幾千到幾萬(wàn)條時(shí)2~3 輪即可更多的輪次很容易過(guò)擬合。另外一個(gè)特別容易被忽略的細(xì)節(jié)是訓(xùn)練數(shù)據(jù)的對(duì)話格式必須與模型自帶的 chat template 完全一致。很多模型微調(diào)后出現(xiàn)“回答前言不搭后語(yǔ)”的詭異現(xiàn)象原因不是模型沒(méi)學(xué)會(huì)而是訓(xùn)練時(shí)用的格式和模型原本的格式不一致導(dǎo)致模型在推理時(shí)不知道該按什么規(guī)則生成。訓(xùn)練前先確認(rèn)對(duì)應(yīng)模型的 chat template 長(zhǎng)什么樣再把你的數(shù)據(jù)傳成同樣的格式。驗(yàn)證階段我強(qiáng)烈建議單獨(dú)留出一批“模型在訓(xùn)練時(shí)沒(méi)見過(guò)的聊天記錄”做測(cè)試。微調(diào)前后的同一個(gè)問(wèn)題各跑一遍對(duì)比回答風(fēng)格、信息準(zhǔn)確性、是否產(chǎn)生“記憶錯(cuò)亂”。如果在測(cè)試集上回答質(zhì)量明顯提升、但常識(shí)能力下降說(shuō)明過(guò)擬合了這時(shí)候可以混入 20%~30% 的通用指令數(shù)據(jù)一起訓(xùn)練能有效緩解。5. 評(píng)測(cè)、LLM as Judge 和基于 LLM 的自動(dòng)化單元測(cè)試5.1 怎么客觀評(píng)估一個(gè) LLM 應(yīng)用大多數(shù)團(tuán)隊(duì)在大模型項(xiàng)目上翻車不是模型選錯(cuò)了而是沒(méi)有一套評(píng)測(cè)方法。大家往往靠“肉眼看看回答怎么樣”來(lái)判斷效果這種感性判斷在 Demo 階段可以但一旦要上線會(huì)變得非常不可靠——因?yàn)橥粋€(gè) Prompt 換一次輸入輸出質(zhì)量波動(dòng)可能非常大。我建議哪怕是小項(xiàng)目也先建一個(gè)基礎(chǔ)評(píng)測(cè)集包含三類樣本標(biāo)準(zhǔn)正確樣本輸入明確了預(yù)期答案可以用字符串匹配或模型判斷對(duì)錯(cuò)。邊界樣本比如空輸入、超長(zhǎng)輸入、包含錯(cuò)誤信息的輸入。對(duì)抗樣本故意誘導(dǎo)模型輸出不安全內(nèi)容、幻覺(jué)內(nèi)容。評(píng)測(cè)指標(biāo)可以分成四類指標(biāo)類型例子說(shuō)明準(zhǔn)確性抽取結(jié)果的 F1、分類準(zhǔn)確率有標(biāo)準(zhǔn)答案時(shí)使用內(nèi)容質(zhì)量完整性、相關(guān)性、可讀性需要人評(píng)或 LLM 評(píng)穩(wěn)定性同一輸入多次輸出的方差越低越穩(wěn)生產(chǎn)環(huán)境重點(diǎn)看成本性能延遲、tokens 數(shù)、失敗率直接決定可持續(xù)性其中“穩(wěn)定性”我特別想強(qiáng)調(diào)很多項(xiàng)目的 Prompt 在評(píng)測(cè)集上效果不錯(cuò)但日志顯示用戶反饋時(shí)好時(shí)壞。原因通常就是 temperature 偏高且沒(méi)有做多輪抽樣測(cè)試。穩(wěn)定性測(cè)試方法很簡(jiǎn)單固定輸入和參數(shù)重復(fù)調(diào)用 10 次計(jì)算輸出的差異程度。5.2 LLM as Judge 的正確用法人工評(píng)測(cè)樣本量一大就吃不消于是“用強(qiáng)模型評(píng)價(jià)弱模型輸出”的思路被廣泛應(yīng)用這就是 LLM as Judge。它在主觀任務(wù)上很有用比如摘要質(zhì)量、文案吸引度、代碼風(fēng)格這類沒(méi)有唯一正確答案的場(chǎng)景人工打分又貴又慢LLM 反而能給出相對(duì)一致的評(píng)分。但 LLM as Judge 有三個(gè)已知偏差使用前務(wù)必了解自偏好偏差它對(duì)“和自己風(fēng)格相似的輸出”打分會(huì)偏高。長(zhǎng)度偏差更長(zhǎng)的回答往往得到更高分哪怕內(nèi)容啰嗦。位置偏差兩個(gè)回答放在前還是放后會(huì)影響裁判的判斷。緩解手段也很明確用Rubric 評(píng)分細(xì)則在 Prompt 里寫清楚每個(gè)分?jǐn)?shù)檔位對(duì)應(yīng)的標(biāo)準(zhǔn)。多次交換候選回答順序取平均分。使用多個(gè)不同模型交叉打分消除單一模型偏好。引入少量人類標(biāo)注做校準(zhǔn)發(fā)現(xiàn) Judge 偏移時(shí)及時(shí)調(diào)整 Prompt。實(shí)際用的時(shí)候比如評(píng)價(jià)一個(gè)摘要模型Judge 的 Prompt 可以長(zhǎng)這樣請(qǐng)根據(jù)以下評(píng)分標(biāo)準(zhǔn)為摘要打分1-5分 - 5分信息完整、語(yǔ)言流暢、沒(méi)有冗余 - 3分核心信息保留但有明顯冗余或遺漏 - 1分關(guān)鍵信息丟失或內(nèi)容錯(cuò)誤 【原文】 {original_text} 【候選摘要】 {candidate_summary} 只輸出分?jǐn)?shù)和一句簡(jiǎn)短理由。注意Judge 本身也會(huì)受到溫度影響建議 temperature 設(shè)為 0并且同一對(duì)輸出跑多次取均值。5.3 用 LLM 生成單元測(cè)試編程方向的讀者應(yīng)該對(duì)“基于 LLM 的單元測(cè)試”這個(gè)熱搜詞很感興趣。思路是用 LLM 自動(dòng)生成測(cè)試用例輔助工程師提升覆蓋率。比如你寫了一個(gè)函數(shù)自己懶得枚舉邊界條件可以讓模型先看代碼再生成測(cè)試計(jì)劃和用例。我的實(shí)踐是先讓模型做兩步輸出而不是直接讓它寫完整測(cè)試文件第一步生成測(cè)試計(jì)劃下面是函數(shù)代碼請(qǐng)列出 5 個(gè)最有價(jià)值的測(cè)試場(chǎng)景包含正常輸入、空輸入、邊界值、異常輸入并說(shuō)明每個(gè)場(chǎng)景的預(yù)期行為。 {code}第二步再根據(jù)測(cè)試計(jì)劃生成測(cè)試代碼。這樣生成出來(lái)的代碼可理解性遠(yuǎn)高于一步到位生成。如果你用的是 Python pytest生成的測(cè)試大致長(zhǎng)這樣import pytest def test_normal_input(): assert my_function(10) 20 def test_empty_input(): with pytest.raises(ValueError): my_function() def test_boundary_value(): assert my_function(0) 0但 LLM 生成單測(cè)有幾個(gè)繞不開的坑我踩過(guò)之后總結(jié)如下幻覺(jué)斷言模型會(huì)生成“看起來(lái)很有道理但實(shí)際是編的”預(yù)期值。這種用例跑起來(lái)可能因?yàn)閿嘌藻e(cuò)誤而失敗反而誤導(dǎo)你去改正確的代碼。邊界遺漏模型更習(xí)慣生成常見輸入對(duì)極端類型比如超大整數(shù)、None、嵌套結(jié)構(gòu)經(jīng)常漏掉。代碼與測(cè)試不匹配如果函數(shù)簽名或行為發(fā)生變化舊測(cè)試不會(huì)自動(dòng)更新容易累積成問(wèn)題。排查這類問(wèn)題的方法就是先審測(cè)試計(jì)劃再生成測(cè)試代碼最后跑測(cè)試看失敗原因。不要讓 LLM 生成的測(cè)試用例直接進(jìn)入 CI一旦出現(xiàn)“紅了一片”先判斷是測(cè)試錯(cuò)了還是代碼錯(cuò)了。另外一個(gè)很常見的工程報(bào)錯(cuò)是LLM request failed: provider rejected the request schema or tool payload.這個(gè)報(bào)錯(cuò)通常出現(xiàn)在給函數(shù)傳入工具定義時(shí)。原因是工具調(diào)用function calling的 JSON Schema 不符合模型 API 的要求比如缺少 required 字段、參數(shù)類型寫錯(cuò)、或者附加了 API 不支持的字段。排查思路很簡(jiǎn)單把發(fā)送給 API 的完整工具定義打出來(lái)用 JSON Schema 的校驗(yàn)器查一圈再對(duì)照 API 文檔逐一核對(duì)字段名。大多數(shù)情況下問(wèn)題出在“你以為的字段名”和“API 真正要求的字段名”不一致。6. LLM 智能體、容錯(cuò)控制與安全紅線6.1 從“聊”到“做”Agent 的基本骨架LLM 本身只能“說(shuō)”不能“做”。Agent 的出現(xiàn)本質(zhì)上是把 LLM 放到一個(gè)循環(huán)里讓它能調(diào)用外部工具、觀察結(jié)果、再?zèng)Q定下一步動(dòng)作。目前業(yè)界最常見的一種骨架是 ReAct 模式流程如下思考Thought模型分析當(dāng)前狀態(tài)決定該做什么。行動(dòng)Action模型輸出一個(gè)工具調(diào)用請(qǐng)求比如“查詢天氣 API參數(shù) city北京”。觀察Observation系統(tǒng)執(zhí)行工具把結(jié)果返回給模型。循環(huán)模型根據(jù)觀察結(jié)果繼續(xù)思考直到達(dá)到終止條件。工程實(shí)現(xiàn)時(shí)你需要維護(hù)一個(gè)“工具集”和一個(gè)“循環(huán)控制器”。工具集是 JSON Schema 描述的函數(shù)列表循環(huán)控制器負(fù)責(zé)調(diào)用模型、解析輸出、執(zhí)行工具、拼接歷史。這個(gè)看似簡(jiǎn)單的循環(huán)實(shí)際在生產(chǎn)環(huán)境里會(huì)遇到大量問(wèn)題。最常見的幾類包括模型輸出了格式錯(cuò)誤的工具參數(shù)導(dǎo)致解析失敗。模型陷入了循環(huán)反復(fù)調(diào)用同一個(gè)工具而不推進(jìn)任務(wù)。工具執(zhí)行超時(shí)但模型還在等待結(jié)果。模型給出的下一步動(dòng)作明顯不合理但系統(tǒng)沒(méi)有攔截機(jī)制。6.2 構(gòu)建可靠的容錯(cuò)控制系統(tǒng)要構(gòu)建真正可用的 Agent關(guān)鍵是容錯(cuò)控制。我看熱詞里那篇論文標(biāo)題講的就是“LLM 智能體自主容錯(cuò)控制構(gòu)建可靠 AI 系統(tǒng)的工程實(shí)踐”這一類問(wèn)題在真實(shí)業(yè)務(wù)里非常值得重視。我的建議是給 Agent 加上五道防護(hù)超時(shí)與重試每次工具調(diào)用設(shè)置超時(shí)時(shí)間建議根據(jù)工具平均耗時(shí)動(dòng)態(tài)調(diào)整超時(shí)后重試一次再失敗則讓模型換路徑。最大步數(shù)限制防止模型失控地?zé)o限循環(huán)。一般任務(wù)不要超過(guò) 10 步。循環(huán)檢測(cè)記錄最近的工具調(diào)用序列如果同一工具、同一參數(shù)重復(fù)出現(xiàn)多次直接終止或切入人工提示。格式校驗(yàn)在模型輸出傳給工具之前用 JSON Schema 做一次校驗(yàn)格式不對(duì)就返回錯(cuò)誤信息讓模型自己修正。輸出護(hù)欄對(duì)模型最終輸出做敏感詞過(guò)濾或規(guī)則校驗(yàn)避免錯(cuò)誤信息直接給用戶。這里特別想提一下“記憶與知識(shí)庫(kù)投毒”的安全風(fēng)險(xiǎn)。業(yè)界已經(jīng)出現(xiàn)類似 AgentPoison 的研究攻擊者通過(guò)在 Agent 的記憶庫(kù)或知識(shí)庫(kù)中注入惡意內(nèi)容誘導(dǎo) Agent 在后續(xù)決策時(shí)輸出攻擊者想要的結(jié)果。通俗來(lái)說(shuō)Agent 會(huì)“讀什么信什么”如果你直接讓它檢索外部知識(shí)庫(kù)或長(zhǎng)期記憶而沒(méi)做來(lái)源可信度校驗(yàn)它很可能把注入的假信息當(dāng)成事實(shí)用于決策。防御思路不是不用知識(shí)庫(kù)而是做幾件事檢索結(jié)果白名單只允許 Agent 讀取可信來(lái)源的內(nèi)容。來(lái)源標(biāo)注讓檢索結(jié)果帶上來(lái)源 IDAgent 輸出時(shí)標(biāo)注引用。最小權(quán)限Agent 調(diào)用的工具只給完成任務(wù)所需的最小權(quán)限不要把數(shù)據(jù)庫(kù)寫權(quán)限也交付給模型。輸入輸出過(guò)濾對(duì)寫入記憶庫(kù)的內(nèi)容先做一遍敏感詞和格式審查。注意安全不是上線前才考慮的事。只要你的 Agent 涉及外部數(shù)據(jù)或用戶數(shù)據(jù)就應(yīng)該在架構(gòu)設(shè)計(jì)階段把這些防護(hù)加進(jìn)去。后期補(bǔ)防護(hù)成本會(huì)高很多。最后再分享一個(gè)我的經(jīng)驗(yàn)這個(gè)系列的第一篇我從模型原理寫到了工具鏈、本地部署、微調(diào)、評(píng)測(cè)和 Agent 容錯(cuò)內(nèi)容跨度很大。但我最想讓你帶走的一句話是大模型項(xiàng)目真正的難點(diǎn)從來(lái)不是模型本身而是模型之外的數(shù)據(jù)、評(píng)測(cè)和工程邊界。我自己早期做項(xiàng)目時(shí)把大量時(shí)間花在“換更強(qiáng)的模型”上結(jié)果效果不穩(wěn)定問(wèn)題根本不是模型不夠強(qiáng)而是評(píng)測(cè)集太隨意、Prompt 沒(méi)版本管理、Agent 沒(méi)有容錯(cuò)設(shè)計(jì)。后來(lái)一點(diǎn)點(diǎn)把“LLM Wiki”建起來(lái)每一個(gè)實(shí)驗(yàn)都記錄、每一次失敗都?xì)w因項(xiàng)目的進(jìn)展反而變快了。建議你從今天開始做一件很小的事建一個(gè)文檔把你下一個(gè) LLM 實(shí)驗(yàn)的任務(wù)目標(biāo)、數(shù)據(jù)、模型、參數(shù)、測(cè)評(píng)結(jié)果和失敗案例記錄下來(lái)。等這個(gè)系列寫到后面幾篇你再回頭看這份記錄會(huì)發(fā)現(xiàn)它比任何教程都有價(jià)值。