
為了使得通用的預訓練大模型能夠滿足專業領域的需求,我們往往會對通用的大模型進行微調。實際上透過微調框架或技術對大模型進行微調之後可能會發現,微調之後的模型其實並沒有達到預定的效果。當然這個原因是多方面的,有時候取決於微調的資料集,微調時對模型進行的一些列最佳化處理等等,但是另外一個不容忽視的問題則是需要在微調之前向預訓練 LLM 的分詞器增加一些專業領域的 token,以幫助 LLM 在微調過程中提高對資料集的理解能力。
本文的主要目的是介紹往 LLM 分詞器中新增 token 的原因和基本方法,同時也會介紹在雲原生的場景下如何將該操作整合到 LLM 微調的流程當中。
在對預訓練 LLM 進行微調之前,通常會在預訓練 LLM 分詞器中新增額外的新 token。這樣做有以下幾個目的:
如果需要在特定領域(例如醫學、法律、金融)進行微調,則需要引入一些基礎模型無法識別的新術語、縮寫或技術術語。新增新 token 有助於模型更好地理解和生成與該領域相關的文字。
預訓練 LLM 使用分詞演算法(如 BPE 或 WordPiece),然而有些詞可能會被分解為低效的子詞。因此新增額外的標記可以提高文字生成的效率和準確性。例如,`ChatGPT` 可能會拆分為 Chat 和 GPT,從而導致語義碎片化。
如果針對原始訓練資料中沒有很好覆蓋的新語言進行微調,則為唯一的單詞或字元新增額外的標記可以提高 LLM 的微調效能。
如果需要在微調資料中引入特定結構(例如,markdown 格式、XML 標籤或對話角色的佔位符),新 token 可以幫助預訓練 LLM 更有效地學習所需的結構。除此之外,一些預訓練 LLM 使用特殊標記(如、或)來指導推理響應。這些額外的 token 有助於根據結構化輸入調節模型。在這些情況下,最好引入特殊 token,而不是通用 token。本文中的示例只包含了新增通用 token 的例子。
綜上所述,新增額外的 token 有助於預訓練的 LLM 在微調過程中更有效地適應特定領域的要求,從而減少對大量訓練資料的需求。這也是平衡微調效果和計算成本的關鍵技術。
基本上,透過 transformers 包實現額外 token 的新增有如下 4 個步驟:
a) 載入分詞器 (例如從 Hugging Face’s transformers 庫中載入);
b) 新增新的 token 到分詞器的詞彙表中;
有關向分詞器新增新 token 的更多詳細資訊,請參閱 new_tokens 和 special_tokens;
c) 調整模型中嵌入層的大小以適應新的 token。
需要呼叫 resize_token_embeddings 來調整模型的嵌入矩陣的大小以匹配其分詞器。此外,請參閱此處瞭解更多詳細資訊。
新的 token 被新增到分詞器中,其索引從當前詞彙表的長度開始,並且在應用分詞演算法之前將被隔離,因此這些新的 token 和來自分詞演算法詞彙表的 token 不會以相同的方式處理。除此以外,預設情況下,模型嵌入層中新 token 的嵌入權重是隨機初始化的,這可能會導致最初的訓練不穩定或效能不佳。因此,一般在每加入一個新的 token 之前,事先計算當前模型嵌入層中所有 token 的平均嵌入權重(average embedding weight),以此作為當前新加入 token 的嵌入權重。
新增新 token 後,儲存更新的分詞器和模型以供將來使用。當然,後面需要載入分詞器和模型的時候需要與儲存時候的路徑相對應地載入。
如果新 token 代表專業領域的概念,則在相關資料集上微調模型至關重要。使用包含這些新 token 例項的資料集並訓練模型以正確理解其用法。
根據以上描述,我完成在 GitHub 完成了一個示例程式 AddExtraTokens2LLM。讀者克隆該例子後可直接在您的裝置上啟動執行,歡迎嘗試並提出寶貴意見。
無論我們選擇何總微調技術或者框架,預訓練 LLM 微調的流程大致如下圖所示。紅色虛線框的內容包含的就是特定領域的 token 表,我們均需要在正式微調模型前將其加入到模型的分詞器詞庫和模型的 embedding 層中,並且該操作應該在微調模型載入前,更靠前於匯入 LLM 微調的資料集。

結合雲原生的場景下,在預訓練 LLM 微調前該如何為其模型新增新的 token?對於這個問題其答案取決於多個方面的考量,比如用什麼技術框架對模型進行微調,微調的叢集是單叢集還是多叢集等。筆者綜合遇到的大部分場景,將這此整合過程抽象成如下三種情況:Pod Level 的模型微調,Node Level 的模型微調和 Cluster Level 的模型微調。
對於 Pod Level 的模型微調,這是所有情況中最簡單的場景,一般情況下其微調的時間不會太長,技術也不會太複雜。筆者對此的解決方案是可以將微調的任務放到 Pod 的常規 containers 中去實現,然後將新增新的 token 的任務放入 Pod 的 Init Containers 中。熟悉 Kubernetes Init Containers 機制的讀者應該明白,Init Containers 可以保證其任務在所有常規的 containers 啟動之前完成。
對於 Node Level 的模型微調,這種場景通常情況下會涉及各種分散式微調框架技術的使用,比如基於 Ray 的大語言模型微調。除此以外,Node Level 也可以出現多叢集微調的場景,為了簡單起見,筆者只考慮單叢集的 Node Level 的模型微調。而對此的解決方案基本上會定義微調模型的流程,此目的自然是為了實現對微調過程的控制干預。對於使用 Ray 等框架來說可能相對比較簡單,因為使用者只需要將給模型新增 token 的工作封裝成 Ray script (Driver),然後再微調之前透過 Ray Job API 事先提交一個 Ray Job 即可。如果想要做得更通用靈活,筆者的建議則是為模型的微調實現一個 Kubernetes Operator,透過定義 Kubernetes CRD 來實現模型微調流程的扭轉。這些流程節點筆者總結如下:1. 從模型下載。2. 為模型新增新 token 並儲存模型。3. 重新載入處理後的模型。4. 匯入微調資料集(可能包含微調資料集的處理,可以新增子流程)。5. 模型微調(需要包含排程,自動擴縮容和斷點續訓等處理機制)。6. 微調後模型儲存。
對於 Cluster Level 的模型微調,這種場景基本上屬於很大規模的模型微調,需要多叢集的協作是不可避免的,因此多叢集的解決方案是必不可少的。事實上筆者到目前為止並沒有遇到這種場景,所以也只能提出一些理論的解決方案。首先需要選擇合適的多叢集解決方案方。其次要實現多叢集 Task Discovery(任務發現)的能力。此能力應該是實現各種關鍵任務的基礎,包括本文主要提及的為模型新增 token 的任務。最後,需要把各種任務及其輸出串聯起來,形成完整的流程拓撲。鑑於筆者沒有實踐過,因此不再贅述。
雖然寫本文的主要目的是為了介紹“如何為預訓練 LLM 新增新 token?”,但是筆者拋磚引玉,也相信讀者能從這一隅之地出發,為基於雲原生場景下,解決大語言模型服務推理部署,微調,訓練等場景提出更加通用優秀的解決方案,為業界分享更多的實踐經驗。
張懷龍,曾就職於阿爾卡特朗訊、百度、IBM、英特爾等知名公司擔任高階開發職位,擁有 16 年的技術研發經驗。作為 Istio 社群的維護者,他專注於雲原生微服務,並在雲原生與 LLM 技術的交叉領域進行創新。他為 OpenVINO、Kserve 等社群做出貢獻,致力於雲原生場景下的 LLM 推理,是 OPEA(企業 AI 開放平臺)社群的開發者和維護者。作者還曾在 KubeCon、ServiceMeshCon、IstioCon、GOTC、InfoQ/Qcon 和 GOSIM 等會議上發表演講。
AICon 2025 強勢來襲,5 月上海站、6 月北京站,雙城聯動,全覽 AI 技術前沿和行業落地。大會聚焦技術與應用深度融合,匯聚 AI Agent、多模態、場景應用、大模型架構創新、智慧資料基建、AI 產品設計和出海策略等話題。即刻掃碼購票,一同探索 AI 應用邊界!

今日薦文
