進(jìn)化:Sidecar架構(gòu)與LoRA后訓(xùn)練實(shí)戰(zhàn))
很多人把大模型跑在本地覺(jué)得“能離線推理、不傳數(shù)據(jù)出去”就算成功了。但我一直覺(jué)得這還不夠如果模型部署之后就不再更新那它只是一個(gè)會(huì)說(shuō)話的靜態(tài)詞典。模型的價(jià)值在于它能不能跟上你的知識(shí)變化、術(shù)語(yǔ)變化和使用習(xí)慣。為了折騰這個(gè)問(wèn)題我給自己維護(hù)的這套本地模型迭代流水線起了個(gè)代號(hào)叫 YoungAi核心思路就兩條用 Sidecar 把推理服務(wù)和訓(xùn)練流水線拆開(kāi)用后訓(xùn)練讓模型能持續(xù)吸收新知識(shí)。這篇文章把我這段時(shí)間的完整實(shí)驗(yàn)記錄整理出來(lái)包括架構(gòu)取舍、數(shù)據(jù)閉環(huán)、訓(xùn)練參數(shù)和踩坑修復(fù)給已經(jīng)在本地部署過(guò)模型、想讓模型越用越聰明的朋友一條可以直接照搬的路徑。1. 為什么本地模型也需要“持續(xù)進(jìn)化”而不只是一次性微調(diào)1.1 本地部署的真正優(yōu)勢(shì)不是“跑得動(dòng)”而是“留得住”聊本地部署的時(shí)候大家關(guān)心最多的永遠(yuǎn)是顯存、速度、模型尺寸仿佛只要能把模型塞進(jìn)顯卡就是勝利。但這些討論忽略了一個(gè)更本質(zhì)的問(wèn)題本地和云端最大的區(qū)別到底是什么我的答案是本地部署讓數(shù)據(jù)不需要離開(kāi)你的硬盤(pán)這比推理速度值錢(qián)得多。企業(yè)內(nèi)部的知識(shí)庫(kù)、個(gè)人的筆記和偏好、行業(yè)里的黑話和術(shù)語(yǔ)這些數(shù)據(jù)在合規(guī)和隱私的限制下根本不適合傳到云端 API。你想讓模型真正理解這些內(nèi)容就必須在本地給模型“補(bǔ)課”。并不是模型本身不夠聰明而是它還不知道你所在領(lǐng)域的上下文。比如一個(gè)模型可以寫(xiě)出漂亮的財(cái)務(wù)分析但如果沒(méi)見(jiàn)過(guò)你們公司的報(bào)銷(xiāo)流程和項(xiàng)目代號(hào)它就很難回答員工的具體提問(wèn)。問(wèn)題是大多數(shù)人補(bǔ)課的方式是“一次性微調(diào)”整理一批語(yǔ)料訓(xùn)完部署然后忘掉。這種做法的問(wèn)題在于知識(shí)是變化的。你上個(gè)月整理的內(nèi)部流程文檔這個(gè)月就改版了用戶(hù)反復(fù)問(wèn)的問(wèn)題可能集中在你完全沒(méi)預(yù)料到的方向。如果訓(xùn)練是一條只做一次的死流程模型就會(huì)在部署的那一刻開(kāi)始變得過(guò)時(shí)。換句話說(shuō)部署到本地這個(gè)動(dòng)作本身只是起點(diǎn)。模型能不能持續(xù)跟上環(huán)境的變化才是本地 AI 真正要解決的難題。我給這個(gè)難題的答案是把“訓(xùn)練”從一次性行為變成一條自動(dòng)運(yùn)轉(zhuǎn)的基礎(chǔ)設(shè)施。這也是 YoungAi 這個(gè)項(xiàng)目存在的理由。1.2 “一次性微調(diào)”為什么撐不起持續(xù)變化的需求舉個(gè)實(shí)際例子你就明白了。假設(shè)你維護(hù)一個(gè)面向內(nèi)部員工的問(wèn)答機(jī)器人模型剛上線時(shí)效果不錯(cuò)但三個(gè)月后業(yè)務(wù)系統(tǒng)升級(jí)舊文檔全部作廢模型還在按舊邏輯回答。這時(shí)候你想更新它常規(guī)做法是重新整理語(yǔ)料、重新微調(diào)、重新部署。這個(gè)流程要幾個(gè)小時(shí)甚至幾天期間模型一直處于“錯(cuò)誤狀態(tài)”。更麻煩的是如果你三個(gè)月才更新一次中間積累的大量真實(shí)交互反饋——用戶(hù)覺(jué)得哪些回答有用、哪些回答被打回重寫(xiě)——就全部浪費(fèi)了。這些反饋其實(shí)是訓(xùn)練數(shù)據(jù)里最值錢(qián)的部分因?yàn)樗鼈兎从车氖钦鎸?shí)需求而不是你腦補(bǔ)出來(lái)的需求。你辛辛苦苦手寫(xiě)一百條標(biāo)準(zhǔn)問(wèn)答可能都不如用戶(hù)真實(shí)問(wèn)過(guò)的五十個(gè)問(wèn)題更貼合業(yè)務(wù)。所以要支持“持續(xù)進(jìn)化”第一步不是選什么模型而是改掉“一次訓(xùn)練定終身”的心態(tài)。你的目標(biāo)應(yīng)該是讓每一次有價(jià)值的交互都能以較低的成本沉淀回模型里。這個(gè)沉淀過(guò)程如果靠人肉跑腳本肯定堅(jiān)持不下來(lái)你很快就會(huì)被重復(fù)勞動(dòng)耗盡耐心。于是就有了自動(dòng)化架構(gòu)的需求。這就是后面要說(shuō)的 Sidecar 和后訓(xùn)練流水線。2. 用 Sidecar 把“推理服務(wù)”和“訓(xùn)練流水線”拆開(kāi)的設(shè)計(jì)邏輯2.1 Sidecar 模式從云原生搬到本地模型到底拆了什么Sidecar 這個(gè)詞來(lái)自云原生里的“邊車(chē)”模式主容器旁邊掛一個(gè)輔助容器幫主容器完成日志收集、監(jiān)控上報(bào)、網(wǎng)絡(luò)代理這些旁路任務(wù)主容器自己保持干凈。我把這個(gè)思路搬到本地 AI 場(chǎng)景基于一個(gè)很樸素的擔(dān)心推理進(jìn)程和訓(xùn)練任務(wù)混在一起會(huì)互相傷害。推理服務(wù)要求穩(wěn)定、低延遲、隨時(shí)在線訓(xùn)練任務(wù)則相反它吃滿(mǎn)顯存、間歇性運(yùn)行、運(yùn)行過(guò)程中的失敗和抖動(dòng)都很正常。如果這兩件事放在同一個(gè)進(jìn)程里訓(xùn)練一跑推理就卡訓(xùn)練崩了推理也跟著死。這就像讓同一個(gè)廚師既站在前臺(tái)招呼客人又跑去后廚顛勺兩頭都做不好。所以我讓架構(gòu)上分成兩個(gè)角色一個(gè)主服務(wù)負(fù)責(zé)模型推理只處理 generate 和對(duì)話補(bǔ)全一個(gè) Sidecar 進(jìn)程負(fù)責(zé)訓(xùn)練流水線監(jiān)聽(tīng)數(shù)據(jù)、清洗樣本、啟動(dòng)后訓(xùn)練、評(píng)估模型、發(fā)布新權(quán)重。Sidecar 掛了不影響主服務(wù)繼續(xù)回答問(wèn)題主服務(wù)升級(jí)也不影響 Sidecar 里正在跑的訓(xùn)練。這個(gè)拆分帶來(lái)的另一個(gè)好處是升級(jí)路徑清晰。推理主服務(wù)更新時(shí)不需要把整個(gè)訓(xùn)練流水線一起重跑訓(xùn)練邏輯調(diào)整時(shí)也不需要重啟常駐的推理服務(wù)。兩個(gè)進(jìn)程各自迭代故障域完全隔離這對(duì)于個(gè)人維護(hù)的項(xiàng)目來(lái)說(shuō)省掉了大量“改一處崩全局”的痛苦。2.2 一條數(shù)據(jù)從進(jìn)來(lái)到變成權(quán)重的完整路徑Y(jié)oungAi 的數(shù)據(jù)流我可以用一張文字圖說(shuō)清楚它不算復(fù)雜但每一步都有自己的角色推理主服務(wù)每次處理用戶(hù)請(qǐng)求會(huì)把交互日志寫(xiě)到本地?cái)?shù)據(jù)目錄Sidecar 進(jìn)程定時(shí)或按事件監(jiān)聽(tīng)這個(gè)目錄讀取新產(chǎn)生的交互日志Sidecar 對(duì)日志做清洗去重剔除壞樣本組裝成標(biāo)準(zhǔn)訓(xùn)練格式當(dāng)有效樣本累積到設(shè)定閾值Sidecar 啟動(dòng)一輪后訓(xùn)練任務(wù)先用低秩適配訓(xùn)練產(chǎn)出增量權(quán)重任務(wù)完成后進(jìn)入離線評(píng)估用預(yù)留的評(píng)測(cè)集打分通過(guò)門(mén)禁的版本被發(fā)布到模型倉(cāng)庫(kù)未通過(guò)的自動(dòng)丟棄Sidecar 通知推理主服務(wù)重新加載新權(quán)重新請(qǐng)求開(kāi)始使用新版本。這條鏈路里最容易被忽略的是最后一步推理主服務(wù)要支持熱重載。很多本地推理引擎默認(rèn)啟動(dòng)時(shí)一次性加載權(quán)重不會(huì)自己去看磁盤(pán)上的新文件。所以我會(huì)在主服務(wù)里留一個(gè) reload 端點(diǎn)Sidecar 在發(fā)布新版本后主動(dòng)調(diào)用它。如果 reload 失敗主服務(wù)繼續(xù)用舊權(quán)重用戶(hù)無(wú)感知。部署上我建議把兩個(gè)服務(wù)分別跑成獨(dú)立進(jìn)程用 systemd 或者容器編排管理。它們共享兩個(gè)目錄日志交換目錄和模型權(quán)重目錄。這樣設(shè)計(jì)之后Sidecar 即使整晚訓(xùn)練推理服務(wù)的延遲也一點(diǎn)不受影響。對(duì)于大多數(shù)自托管場(chǎng)景這個(gè)方案比在一個(gè)框架里硬塞所有功能要可靠得多。2.3 為什么本地場(chǎng)景不需要引入消息中間件一開(kāi)始我習(xí)慣性地想在上游加一個(gè)消息隊(duì)列把交互日志推過(guò)去。后來(lái)發(fā)現(xiàn)在單人或者小團(tuán)隊(duì)維護(hù)的本地場(chǎng)景這套東西純粹是給自己添負(fù)擔(dān)。本地?cái)?shù)據(jù)量不大直接用文件目錄加輪詢(xún)就能滿(mǎn)足需求引入隊(duì)列還得多維護(hù)一個(gè)組件數(shù)據(jù)鏈路長(zhǎng)了反而更難排查。設(shè)計(jì)原則也要跟著場(chǎng)景走單機(jī)本地場(chǎng)景的 Sidecar 要的是簡(jiǎn)單和穩(wěn)定不是分布式擴(kuò)展。只要日志目錄寫(xiě)入和模型倉(cāng)庫(kù)發(fā)布這兩個(gè)環(huán)節(jié)做好原子性保護(hù)整條流水線已經(jīng)足夠可靠。這也算是我在設(shè)計(jì)過(guò)程中做過(guò)的一個(gè)減法減掉了一堆不必要的外部依賴(lài)。3. 后訓(xùn)練不是一句口號(hào)LoRA、增量預(yù)訓(xùn)練與偏好對(duì)齊怎么落地3.1 為什么選 LoRA / QLoRA 而不是全參微調(diào)想讓模型持續(xù)吸收新知識(shí)第一個(gè)要解決的問(wèn)題是本地顯存扛不住全參微調(diào)。一個(gè) 7B 量級(jí)的模型全參微調(diào)需要保存優(yōu)化器狀態(tài)和完整梯度通常要 8 張以上大顯存顯卡才舒服個(gè)人開(kāi)發(fā)者手里通常只有一兩張顯卡這條路根本走不通。LoRA 的思路很直接不修改原來(lái)的大權(quán)重矩陣而是在權(quán)重旁邊掛兩個(gè)小矩陣用它們的乘積來(lái)模擬權(quán)重的變化。模型推理時(shí)原始權(quán)重 W 和低秩增量 BA 一起參與計(jì)算訓(xùn)練時(shí)只更新 B 和 A 這兩個(gè)小矩陣。由于矩陣的秩 r 壓得比隱藏維度小一個(gè)數(shù)量級(jí)可訓(xùn)練參數(shù)往往只有全模型的 0.1%~1%顯存和訓(xùn)練時(shí)間都能降一個(gè)量級(jí)。QLoRA 再把底座參數(shù)量化到 4bit進(jìn)一步壓縮基座模型占用的顯存。這樣在 24GB 顯存的單卡上訓(xùn) 7B 模型是可行的。實(shí)測(cè)跑一輪一兩千條樣本的指令微調(diào)普通消費(fèi)級(jí)顯卡也能在幾小時(shí)內(nèi)完成。全參微調(diào)每一步都要?jiǎng)诱麄€(gè)模型本地進(jìn)化這件事根本做不起來(lái)低秩適配才讓“隔幾天訓(xùn)一次”變得現(xiàn)實(shí)。為什么不把 adapter 合并回一個(gè)大模型文件合并之后推理時(shí)少一步低秩計(jì)算速度略快部署也更簡(jiǎn)單不合并則可以在同一個(gè)基座上掛多個(gè)能力適配器按場(chǎng)景切換。我自己的選擇是發(fā)布到對(duì)外服務(wù)用的版本會(huì)合并成一個(gè)完整權(quán)重但訓(xùn)練產(chǎn)出的 adapter 文件也會(huì)存檔。這樣既有部署便利又保留了多個(gè)能力包。3.2 三條訓(xùn)練支路分別在什么時(shí)候用后訓(xùn)練不是一個(gè)筐什么都能裝。YoungAi 里我主要走三條支路按目標(biāo)選用。第一條是監(jiān)督微調(diào) SFT。它的作用是讓模型學(xué)會(huì)“怎么回答”適合整理出高質(zhì)量的問(wèn)答對(duì)把回答格式、語(yǔ)氣、內(nèi)部規(guī)范灌進(jìn)模型。數(shù)據(jù)格式通常是 system / user / assistant 三段式對(duì)話樣本。比如你希望模型在回答前先說(shuō)明“根據(jù)最新文檔”或者讓它在不確定時(shí)直接說(shuō)“我不確定”這些規(guī)范都能通過(guò) SFT 灌進(jìn)去。第二條是增量預(yù)訓(xùn)練。它針對(duì)的是“模型不知道的新知識(shí)”——專(zhuān)業(yè)術(shù)語(yǔ)、最新文檔、內(nèi)部產(chǎn)品介紹。做法是把領(lǐng)域語(yǔ)料喂給模型讓它繼續(xù)學(xué)習(xí)文本里的知識(shí)分布。注意增量預(yù)訓(xùn)練不是為了學(xué)會(huì)對(duì)話格式而是為了擴(kuò)充詞匯和知識(shí)所以語(yǔ)料要盡量貼近真實(shí)業(yè)務(wù)文本而不是問(wèn)答對(duì)。第三條是偏好對(duì)齊比如用 DPO 這類(lèi)不需要單獨(dú)訓(xùn)練獎(jiǎng)勵(lì)模型的方法。它的輸入是“好回答/差回答”這樣的成對(duì)樣本。用戶(hù)對(duì)某條回答點(diǎn)了贊但沒(méi)有手動(dòng)修改可以當(dāng)成 chosen被用戶(hù)明確改寫(xiě)或吐槽的可以作為 rejected。DPO 的訓(xùn)練目標(biāo)是提高模型輸出好答案的概率更適合利用交互反饋這類(lèi)信號(hào)。三種手段的適用場(chǎng)景我用一個(gè)對(duì)比表歸納訓(xùn)練方式解決什么問(wèn)題典型數(shù)據(jù)訓(xùn)練成本SFT對(duì)話風(fēng)格、回答結(jié)構(gòu)、指令遵循手工整理的問(wèn)答對(duì)低增量預(yù)訓(xùn)練注入新的領(lǐng)域知識(shí)與術(shù)語(yǔ)最新文檔、知識(shí)庫(kù)文本中DPO對(duì)齊用戶(hù)偏好減少糟糕回答成對(duì)的好/差回答樣本低訓(xùn)練超參上我建議以小步快跑為主學(xué)習(xí)率 1e-4 到 5e-5訓(xùn)練 1 到 3 個(gè) epoch上下文長(zhǎng)度根據(jù)實(shí)際數(shù)據(jù)設(shè) 2048 或 4096。單輪樣本控制在 500 到 2000 條之間比攢一堆數(shù)據(jù)一口氣訓(xùn)練更可控。工具鏈用常見(jiàn)開(kāi)源大模型訓(xùn)練棧就行不需要自己造輪子。3.3 一份可以被直接復(fù)用的訓(xùn)練數(shù)據(jù)樣例給一個(gè)實(shí)用的數(shù)據(jù)格式方便直接上手{instruction: 用一句話解釋什么是增量預(yù)訓(xùn)練。, output: 增量預(yù)訓(xùn)練是在已有模型基礎(chǔ)上繼續(xù)學(xué)習(xí)新領(lǐng)域文本以擴(kuò)充知識(shí)和術(shù)語(yǔ)覆蓋。, category: concept}實(shí)際訓(xùn)練時(shí)很多訓(xùn)練框架更習(xí)慣 chat template 格式把 system、user、assistant 的輪次組織好。我的經(jīng)驗(yàn)是多輪對(duì)話必須帶上下文不要只給最后一輪否則模型在真實(shí)使用中會(huì)忘記歷史會(huì)話。你可以在每條樣本里把前兩三輪對(duì)話作為前綴保留。4. “進(jìn)化”的閉環(huán)從交互日志到新模型權(quán)重的完整流水線4.1 訓(xùn)練數(shù)據(jù)從哪里來(lái)把交互反饋當(dāng)成礦脈持續(xù)進(jìn)化的前提是持續(xù)有新數(shù)據(jù)。YoungAi 采集數(shù)據(jù)主要有幾個(gè)來(lái)源用戶(hù)與模型的真實(shí)對(duì)話日志用戶(hù)對(duì)回答點(diǎn)贊、點(diǎn)踩、改寫(xiě)后的最終答案知識(shí)庫(kù)和幫助文檔的更新內(nèi)容人工整理的高質(zhì)量問(wèn)題。但原始日志不能直接拿來(lái)訓(xùn)練。一個(gè)最典型的坑是用戶(hù)對(duì)某條回答不滿(mǎn)意改寫(xiě)了一版更好的答案這個(gè)改寫(xiě)后的版本應(yīng)該作為訓(xùn)練樣本但如果采集邏輯沒(méi)做對(duì)齊把用戶(hù)抱怨的話也當(dāng)成了 assistant 回復(fù)模型就會(huì)學(xué)到非常奇怪的東西。所以清洗是必須的。我用的清洗流程包含四步格式過(guò)濾把過(guò)短、亂碼、純 URL 的樣本扔掉精確和模糊去重避免大量重復(fù)樣本讓模型反復(fù)背同一句話噪聲檢測(cè)剔除與業(yè)務(wù)無(wú)關(guān)的閑聊質(zhì)量打分用一些啟發(fā)式規(guī)則加模型打分給每條樣本一個(gè)質(zhì)量分低于閾值的不用。一句話總結(jié)處理原則訓(xùn)練數(shù)據(jù)的價(jià)值密度比數(shù)量重要得多100 條干凈的高質(zhì)量樣本勝過(guò) 1000 條噪聲數(shù)據(jù)。這條原則我是在踩了幾個(gè)坑之后才真正認(rèn)同的后面會(huì)專(zhuān)門(mén)說(shuō)那個(gè)“復(fù)讀機(jī)”事故。4.2 評(píng)估門(mén)禁和版本回滾不能讓模型越進(jìn)化越退化持續(xù)進(jìn)化最怕什么怕模型學(xué)完新數(shù)據(jù)舊能力崩了更怕訓(xùn)練集太偏練完之后模型看起來(lái) loss 很低實(shí)際業(yè)務(wù)反而更差。所以我給流水線加了一道評(píng)估門(mén)禁。做法是每周從真實(shí)交互中留出約 300 條新樣本單獨(dú)保存不進(jìn)訓(xùn)練集。每次訓(xùn)練完Sidecar 先在這套評(píng)估集上跑一遍和當(dāng)前線上版本對(duì)比。指標(biāo)可以看正確率、回答長(zhǎng)度、拒答率、和參考答案的語(yǔ)義相似度也可以混入幾個(gè)固定的人工檢查點(diǎn)。只有綜合分不低于當(dāng)前版本新版本才允許發(fā)布否則自動(dòng)回滾保留舊權(quán)重。對(duì)應(yīng)的模型倉(cāng)庫(kù)我按版本目錄管理models/ base_7b/ train_v010/ merged/ lora/ manifest.json train_v011/ merged/ lora/ manifest.json current - train_v011current 是一個(gè)符號(hào)鏈接指向當(dāng)前線上版本。Sidecar 發(fā)布新版本時(shí)不會(huì)直接覆蓋正在使用的文件目錄而是先寫(xiě)一個(gè)新目錄全部寫(xiě)完、校驗(yàn)通過(guò)后再切換符號(hào)鏈接并觸發(fā)主服務(wù) reload。這樣即使 reload 前主服務(wù)還在讀取也不會(huì)有半份權(quán)重文件的問(wèn)題。熱重載之后我還會(huì)讓主服務(wù)跑一次固定的健康檢查請(qǐng)求比如問(wèn)幾個(gè)固定 prompt對(duì)比輸出簽名。輸出預(yù)期的版本號(hào)的才認(rèn)為發(fā)布成功。這一步雖然簡(jiǎn)單但能避免“訓(xùn)練成功但加載的其實(shí)還是舊文件”這種烏龍。5. 實(shí)測(cè)中踩過(guò)的坑災(zāi)難性遺忘、樣本污染、熱切換失靈5.1 災(zāi)難性遺忘比想象中來(lái)得快我第一次嘗試持續(xù)進(jìn)化時(shí)喂了大約 2000 條內(nèi)部問(wèn)答結(jié)果模型對(duì)新領(lǐng)域問(wèn)題答得像模像樣但日常閑聊和通用知識(shí)明顯變笨了甚至偶爾回答格式都變形。復(fù)盤(pán)下來(lái)原因很清晰訓(xùn)練樣本太偏全是新領(lǐng)域數(shù)據(jù)學(xué)習(xí)率給得偏高訓(xùn)練輪數(shù)也偏多。解法是給訓(xùn)練集加入 10%~20% 的歷史通用樣本做“重放”學(xué)習(xí)率降到 5e-5 左右epoch 不超過(guò) 3。另外不要試圖一輪吃成胖子把一次大訓(xùn)練拆成多次小訓(xùn)練每次只針對(duì)最近累積的幾百條有效樣本反而更穩(wěn)。這個(gè)調(diào)整之后災(zāi)難性遺忘基本被控制住了。注意重放樣本不是隨便找一些通用 QA 就行最好是從過(guò)去幾輪訓(xùn)練數(shù)據(jù)里均勻抽樣這樣能覆蓋模型已經(jīng)學(xué)會(huì)的舊知識(shí)防止新的權(quán)重覆蓋舊能力。5.2 樣本污染模型學(xué)會(huì)“復(fù)讀機(jī)”的教訓(xùn)有段時(shí)間我的模型出現(xiàn)一種很迷惑的行為同一個(gè)問(wèn)題問(wèn)兩次第一次回答還行第二次開(kāi)始復(fù)讀第一次的答案。查了很久才發(fā)現(xiàn)訓(xùn)練數(shù)據(jù)里有大量重復(fù)問(wèn)題而且有些樣本把“用戶(hù)改寫(xiě)后的最終答案”錯(cuò)誤地拼進(jìn) assistant 輪次導(dǎo)致模型把“重復(fù)”當(dāng)成了規(guī)律。這個(gè)坑給我的教訓(xùn)是訓(xùn)練數(shù)據(jù)必須做會(huì)話輪次對(duì)齊和去重。去重不能只看完全相同的字符串還要用相似度計(jì)算把語(yǔ)義重復(fù)的樣本也去掉。清洗腳本里我會(huì)給每條樣本計(jì)算一個(gè)內(nèi)容哈希再用 embedding 距離做近重復(fù)檢測(cè)超過(guò)相似度閾值的直接丟棄。更重要的是一句提醒不要迷信“數(shù)據(jù)越多越好”。如果自動(dòng)化流水線把用戶(hù)產(chǎn)生的壞回答也當(dāng)成正確答案采集進(jìn)來(lái)模型會(huì)穩(wěn)定地學(xué)會(huì)那些壞回答。數(shù)據(jù)來(lái)源的質(zhì)量信號(hào)比清洗算法本身更能決定訓(xùn)練效果。我現(xiàn)在寧可把采集門(mén)檻調(diào)高一點(diǎn)只吸收有明確正向反饋的樣本。5.3 熱切換不生效與權(quán)重文件競(jìng)爭(zhēng)有個(gè)問(wèn)題我調(diào)試了一整個(gè)下午訓(xùn)練完成新版權(quán)重也發(fā)布了推理服務(wù) reload 成功但回答內(nèi)容沒(méi)有任何變化。后來(lái)發(fā)現(xiàn)是推理進(jìn)程把模型權(quán)重映射到內(nèi)存后不會(huì)去重新讀取磁盤(pán)的符號(hào)鏈接目標(biāo)我修改的是鏈接指向的目標(biāo)進(jìn)程卻還在用舊的緩存文件。解決辦法是發(fā)布新版本時(shí)使用全新的目錄名并且在 reload 接口里顯式指定新的模型路徑不依賴(lài)符號(hào)鏈接原地更新reload 完成后必須跑一輪健康檢查。另一種常見(jiàn)問(wèn)題是訓(xùn)練還在往模型目錄里寫(xiě)權(quán)重推理進(jìn)程就已經(jīng)開(kāi)始加載導(dǎo)致讀到一半的文件。所以寫(xiě)入過(guò)程要先寫(xiě)臨時(shí)目錄全部寫(xiě)完再做原子切換這是必須養(yǎng)成的習(xí)慣。5.4 訓(xùn)練和推理爭(zhēng)搶 GPU本地場(chǎng)景往往只有一塊 GPU。訓(xùn)練任務(wù)一旦跑起來(lái)推理服務(wù)立刻變慢經(jīng)常 OOM。我的解決辦法是給訓(xùn)練任務(wù)加了一個(gè)簡(jiǎn)單的調(diào)度策略只在推理服務(wù)低峰時(shí)段啟動(dòng)訓(xùn)練比如深夜如果訓(xùn)練過(guò)程中推理服務(wù)檢測(cè)到顯存吃緊也可以主動(dòng)暫停訓(xùn)練任務(wù)等空閑時(shí)再恢復(fù)。這個(gè)機(jī)制不需要很復(fù)雜一個(gè)鎖文件加一個(gè)定時(shí)檢查就夠用了。整條流水線跑順之后我最大的體會(huì)是不要把持續(xù)進(jìn)化想成一次兩次微調(diào)它本質(zhì)上是把訓(xùn)練變成和推理一樣平常的基礎(chǔ)設(shè)施。YoungAi 到現(xiàn)在已經(jīng)自動(dòng)迭代了好幾輪每次只進(jìn)步一點(diǎn)點(diǎn)但累計(jì)起來(lái)的變化非??捎^。如果再給我一次機(jī)會(huì)我會(huì)更早地引入評(píng)估門(mén)禁——自動(dòng)訓(xùn)練的每一步都值得被檢驗(yàn)。最后再分享一個(gè)實(shí)用建議在你開(kāi)始做全自動(dòng)閉環(huán)之前先把數(shù)據(jù)采集、訓(xùn)練、發(fā)布、回滾這四個(gè)環(huán)節(jié)手工跑通一遍。確認(rèn)每一步都有重啟能力和人工介入手段再把它們自動(dòng)化串聯(lián)。任何自動(dòng)進(jìn)化系統(tǒng)都要留一個(gè)緊急停止開(kāi)關(guān)這可能是整個(gè)設(shè)計(jì)里最重要的一句話。