【機器學習深度學習】LLamaFactory微調效果與vllm部署效果不一致如何解決

目錄

前言

一、問題本質

1.1 問題說明

1.2?問題本質示意

二、常見原因

LLaMAFactory對話模板規則定義

模型對話模板定義規則?

三、解決方法

?提取代碼myset.py

創建jinja文件

安裝VLLM

運行VLLM

安裝運行open webui流程

四、流程梳理


前言

本文主要講述的主要內容是關于在LLaMAFactory中微調后加載的模型測試效果和加載到其他推理框架(VLLM,LMDeploy)的測試效果不一致是什么原因導致的?又該如何解決?

主要原因是對話模板不一致所導致的


一、問題本質

1.1 問題說明

LLaMA-Factory 使用內置對話模板(chat_template)來格式化訓練/推理數據,而 vLLMLMDeploy 等推理框架則可能使用自己的模板體系或根本不管模板
這就是導致微調效果與部署效果不一致的核心原因之一。

LLaMA-Factory 的微調過程使用的是 HuggingFace Transformers 格式,而 vLLM 在推理時,依賴精確的:

  • tokenizer 配置

  • 模型 config

  • 權重格式(尤其是 LoRA 或 QLoRA)

  • prompt 模板

如果這些配置在部署時和訓練時不一致,模型生成效果就會發生偏差。


1.2?問題本質示意

在 LLaMA-Factory 中使用的訓練模板(例如 chatml):

<|im_start|>system
你是一個智能助手<|im_end|>
<|im_start|>user
你好<|im_end|>
<|im_start|>assistant

?而 vLLM 默認可能認為只需要:

用戶:你好
助手:

?或者根本不加模板,直接拼接文本。這會讓模型生成完全跑偏。


二、常見原因

2.1 原因匯總

問題類別具體原因解決方案
Tokenizer 不一致tokenizer_config.jsonspecial_tokens_map.json 中信息缺失或被修改? 確保 tokenizer 跟隨微調模型一起保存并部署到 vLLM
Prompt 模板不一致如使用 chatmlalpacabaichuan 模板不同會導致上下文格式變化? 明確使用的 prompt 格式,在 vLLM 推理端加上相同格式的 系統提示 + 用戶輸入 + assistant 結構
LoRA 權重未合并微調后未合并 LoRA 層,推理端加載的是 base 模型? 使用 merge_and_save 合并權重,再加載
Quantization 不一致訓練中使用了 QLoRA 等量化策略,而部署端未支持或解碼異常? 部署前使用 LLaMA-Factoryexport_model.py 導出標準 FP16 或 INT4 GGUF 權重
vLLM 加載錯誤配置vLLM 讀取模型參數時未正確加載 config.jsongeneration_config.json? 檢查是否帶上 --tokenizer--trust-remote-code 等參數


2.2 LLaMAFactory對話模板規則定義

對話模板路徑:LLaMA-Factory/src/llamafactory/data/template.py

在LLaMAFactory文件夾中有個template文件(LLaMA-Factory/src/llamafactory/data/template.py)定義了各個模型的對話模板規則,template.py中定義了大部分主流,通用的模型對話規則。

如下圖展示的是qwen的幾個對話模板

單獨拿出一個對話示例模板,也就是【1.2】所展示的LLaMAFactory對話模板格式示例:

# copied from chatml template
register_template(name="qwen",format_user=StringFormatter(slots=["<|im_start|>user\n{{content}}<|im_end|>\n<|im_start|>assistant\n"]),format_assistant=StringFormatter(slots=["{{content}}<|im_end|>\n"]),format_system=StringFormatter(slots=["<|im_start|>system\n{{content}}<|im_end|>\n"]),format_function=FunctionFormatter(slots=["{{content}}<|im_end|>\n"], tool_format="qwen"),format_observation=StringFormatter(slots=["<|im_start|>user\n<tool_response>\n{{content}}\n</tool_response><|im_end|>\n<|im_start|>assistant\n"]),format_tools=ToolFormatter(tool_format="qwen"),default_system="You are Qwen, created by Alibaba Cloud. You are a helpful assistant.",stop_words=["<|im_end|>"],replace_eos=True,
)

2.3 模型對話模板定義規則?

模型對話模板路徑:模型名稱/tokenizer_config.json

如果LLaMAFactory的內置對話模板中定義了相同的對話模板規則,回復效果自然也就沒有差異,但在大多數情況下,對話模板的規則一致的條件是很難滿足的。


三、解決方法

把在LLaMAFactory微調時的那套對話模板規則模板導出。使用微調時的對話規則,再部署到其它推理框架上就能夠保證模型的輸出效果一致了。?

3.1? 提取代碼myset.py

# mytest.py
import sys
import os# 將項目根目錄添加到 Python 路徑
root_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
sys.path.append(root_dir)from llamafactory.data.template import TEMPLATES
from transformers import AutoTokenizer# 1. 初始化分詞器(任意支持的分詞器均可)
tokenizer = AutoTokenizer.from_pretrained("/mnt/workspace/model/qwen/Qwen2.5-7B-Instruct")# 2. 獲取模板對象
template_name = "qwen"  # 替換為你需要查看的模板名稱
template = TEMPLATES[template_name]# 3. 修復分詞器的 Jinja 模板
template.fix_jinja_template(tokenizer)# 4. 直接輸出模板的 Jinja 格式
print("=" * 40)
print(f"Template [{template_name}] 的 Jinja 格式:")
print("=" * 40)
print(tokenizer.chat_template)

【替換片段】

# 1. 初始化分詞器(任意支持的分詞器均可)
tokenizer = AutoTokenizer.from_pretrained("/mnt/workspace/model/qwen/Qwen2.5-7B-Instruct")

/mnt/workspace/model/qwen/Qwen2.5-7B-Instruct:模型路徑,里面必須包含分詞器tokenizers.json,下載的模型文件會自帶這個文件;

template_name = "qwen"  # 替換為你需要查看的模板名稱

qwen:在LLaMA-Factory/src/llamafactory/data/template.py中的內置對話模板規則,根據需求選擇;

#


?【使用說明】

1、放置位置:LLaMA-Factory/src/llamafactory/data/mytest.py


2、創建虛擬環境配置

#創建虛擬環境llamafactory
conda create -n llamafactory python=3.11#激活虛擬環境
conda activate llamafactory

3、安裝依賴

在虛擬環境內安裝依賴

# 基礎依賴
pip install transformers# 必須安裝的依賴(LLamaFactory 相關)
pip install jinja2
pip install torch  # PyTorch 基礎庫# 安裝 LLamaFactory 及其依賴(推薦從源碼安裝)
git clone https://github.com/hiyouga/LLaMA-Factory.git
cd LLaMA-Factory
pip install -e .  # 可編輯模式安裝# 可選但推薦的依賴(用于完整功能)
pip install datasets accelerate sentencepiece

4、運行提取程序mytest.py

python /mnt/workspace/LLaMA-Factory/src/llamafactory/data/mytest.py

/mnt/workspace/LLaMA-Factory/src/llamafactory/data/mytest.py:表示myset.py路徑


5、運行結果

========================================
Template [qwen] 的 Jinja 格式:
========================================
{%- if tools %}{{- '<|im_start|>system\n' }}{%- if messages[0]['role'] == 'system' %}{{- messages[0]['content'] }}{%- else %}{{- 'You are Qwen, created by Alibaba Cloud. You are a helpful assistant.' }}{%- endif %}{{- "\n\n# Tools\n\nYou may call one or more functions to assist with the user query.\n\nYou are provided with function signatures within <tools></tools> XML tags:\n<tools>" }}{%- for tool in tools %}{{- "\n" }}{{- tool | tojson }}{%- endfor %}{{- "\n</tools>\n\nFor each function call, return a json object with function name and arguments within <tool_call></tool_call> XML tags:\n<tool_call>\n{\"name\": <function-name>, \"arguments\": <args-json-object>}\n</tool_call><|im_end|>\n" }}
{%- else %}{%- if messages[0]['role'] == 'system' %}{{- '<|im_start|>system\n' + messages[0]['content'] + '<|im_end|>\n' }}{%- else %}{{- '<|im_start|>system\nYou are Qwen, created by Alibaba Cloud. You are a helpful assistant.<|im_end|>\n' }}{%- endif %}
{%- endif %}
{%- for message in messages %}{%- if (message.role == "user") or (message.role == "system" and not loop.first) or (message.role == "assistant" and not message.tool_calls) %}{{- '<|im_start|>' + message.role + '\n' + message.content + '<|im_end|>' + '\n' }}{%- elif message.role == "assistant" %}{{- '<|im_start|>' + message.role }}{%- if message.content %}{{- '\n' + message.content }}{%- endif %}{%- for tool_call in message.tool_calls %}{%- if tool_call.function is defined %}{%- set tool_call = tool_call.function %}{%- endif %}{{- '\n<tool_call>\n{"name": "' }}{{- tool_call.name }}{{- '", "arguments": ' }}{{- tool_call.arguments | tojson }}{{- '}\n</tool_call>' }}{%- endfor %}{{- '<|im_end|>\n' }}{%- elif message.role == "tool" %}{%- if (loop.index0 == 0) or (messages[loop.index0 - 1].role != "tool") %}{{- '<|im_start|>user' }}{%- endif %}{{- '\n<tool_response>\n' }}{{- message.content }}{{- '\n</tool_response>' }}{%- if loop.last or (messages[loop.index0 + 1].role != "tool") %}{{- '<|im_end|>\n' }}{%- endif %}{%- endif %}
{%- endfor %}
{%- if add_generation_prompt %}{{- '<|im_start|>assistant\n' }}
{%- endif %}


3.2 創建jinja文件

創建一個jinja文件,將執行結果復制進去


3.3 安裝VLLM

參考文章:【VLLM】大模型本地化部署_vllm部署大模型-CSDN博客

直接看這篇文章的【三、部署VLLM】即可


3.4 運行VLLM

vllm serve <model> --chat-template ./path-to-chat-template.jinja

<model>:表示訓練模型路徑;

./path-to-chat-template.jinja:表示jinja文件的路徑;

示例

vllm serve /mnt/workspace/model/qwen_7b --chat-template /mnt/workspace/model/jinja2/qwen.jinja


3.5 安裝運行open webui流程

#創建一個open-webui的conda環境
conda activate open-webui
# 安裝open-webui
pip install -U open-webui torch transformers# 切換到新建的環境
conda activate open-webui
#配置
export HF_ENDPOINT=https://hf-mirror.com
#因為open-webui默認為ollama框架,所以使用vllm框架啟動大模型的話需要將這里改為false
export ENABLE_OLLAMA_API=false
#調用大模型的地址,vllm的默認啟動端口為8000
export OPENAI_API_BASE_URL=http://127.0.0.1:8000/v1#啟動openwebui
open-webui serve

四、流程梳理

具體部署流程可看:【VLLM】open-webui部署模型全流程-CSDN博客

1、下載模型到本地(可選):根據業務場景選擇合適的模型即可;

3、安裝vllm:用虛擬環境隔離安裝,安裝教程:【VLLM】大模型本地化部署_vllm部署大模型-CSDN博客;

4、安裝open-webui:用虛擬環境隔離安裝;

5、運行vllm和open-webui

方法1:vllm環境中啟動下載的本地模型

vllm serve <模型存放路徑>

方法2:vllm環境中啟動微調后導出的本地模型

vllm serve /mnt/workspace/model/qwen_7b --chat-template /mnt/workspace/model/jinja2/qwen.jinja

/mnt/workspace/model/qwen_7b:表示微調后導出的模型的存放路徑;

/mnt/workspace/model/jinja2/qwen.jinja:LLaMAFactory中提取的內置對話模板規則路徑

加上LLaMAFactory導出的內置對話模板規則,隨后開啟open-webui服務,在vllm框架下,模型的回復效果就和在LLaMAFactory上測試的效果是一樣的啦;

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/93100.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/93100.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/93100.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Python入門構建網頁

用純 Python 構建 Web 應用 本教程將帶你從零開始&#xff0c;構建一個交互式的待辦事項清單。 fasthtml 的核心哲學是“回歸初心&#xff0c;大道至簡”。在當今復雜的前后端分離技術棧中 &#xff0c;它提供了一條返璞歸真的路徑&#xff0c;旨在讓你能用純粹的 Python 構建從…

開源 Arkts 鴻蒙應用 開發(九)通訊--tcp客戶端

文章的目的為了記錄使用Arkts 進行Harmony app 開發學習的經歷。本職為嵌入式軟件開發&#xff0c;公司安排開發app&#xff0c;臨時學習&#xff0c;完成app的開發。開發流程和要點有些記憶模糊&#xff0c;趕緊記錄&#xff0c;防止忘記。 相關鏈接&#xff1a; 開源 Arkts …

Go的defer和recover

在 Go 語言中&#xff0c;defer 和 recover 是兩個緊密相關的關鍵字&#xff0c;主要用于錯誤處理和資源清理。它們通常一起使用&#xff0c;特別是在處理panic&#xff08;運行時崩潰&#xff09;時&#xff0c;確保程序不會直接崩潰&#xff0c;而是能夠優雅地恢復并繼續執行…

Spring Boot 配置文件常用配置屬性詳解(application.properties / application.yml)

前言 Spring Boot 的一大優勢就是通過簡單的配置文件即可快速定制應用行為&#xff0c;而無需編寫大量 XML 配置或 Java 代碼。Spring Boot 使用 application.properties 或 application.yml 作為核心配置文件&#xff0c;支持豐富的配置屬性。 本文將詳細介紹 Spring Boot 常用…

uni-appDay02

1.首頁-通用輪播組件 輪播圖組件需要再首頁和分類頁使用&#xff0c;封裝成通用組件 準備組件自動導入組件 <script setup lang"ts"> import XtxSwiper from /components/XtxSwiper.vue import CustomNavbar from ./components/CustomNavbar.vue </scrip…

FastAPI入門:請求體、查詢參數和字符串校驗、路徑參數和數值校驗

請求體 FastAPI 使用請求體從客戶端&#xff08;例如瀏覽器&#xff09;向 API 發送數據。請求體是客戶端發送給 API 的數據。響應體是 API 發送給客戶端的數據。 使用 Pydantic 模型聲明請求體&#xff0c;能充分利用它的功能和優點 from fastapi import FastAPI from pydanti…

Docker的docker-compose類比Spring的ApplicationContext

總一句話是&#xff1a;Docker Compose&#xff1a;集中化管理多個容器及其依賴的資源環境&#xff1b;ApplicationContext&#xff1a;集中化管理 多個Bean 及其運行所需的資源和依賴關系。 1. 整體概念 Docker Compose&#xff1a;用于定義和運行多容器 Docker 應用程序&…

Reason-before-Retrieve(CVPR 2025)

研究方向&#xff1a;Image Captioning論文全名&#xff1a;《Reason-before-Retrieve: One-Stage Reflective Chain-of-Thoughts for Training-Free Zero-Shot Composed Image Retrieval》1. 論文介紹組合圖像檢索&#xff08;CIR&#xff09;旨在檢索與參考圖像密切相似的目標…

Idefics2:構建視覺-語言模型時,什么是重要的

溫馨提示&#xff1a; 本篇文章已同步至"AI專題精講" Idefics2&#xff1a;構建視覺-語言模型時&#xff0c;什么是重要的 摘要 隨著large language models和vision transformers的進步&#xff0c;視覺-語言模型&#xff08;VLMs&#xff09;受到了越來越多的關注…

再談fpga開發(fpga調試方法)

【 聲明&#xff1a;版權所有&#xff0c;歡迎轉載&#xff0c;請勿用于商業用途。 聯系信箱&#xff1a;feixiaoxing 163.com】我們之前在學校學習c、c的時候&#xff0c;其實學校漏掉了很重要的一個教學環節&#xff0c;那就是調試、測試。很多時候我們代碼寫出來了&#xff…

C語言中的數據結構--棧和隊列(1)

前言本屆開始我們將對數據結構中棧的內容進行講解,那么廢話不多說,我們正式進入今天的學習棧棧是一種很特殊的線性表&#xff0c;它只能在固定的一端進行插入和刪除操作&#xff0c;進行數據的插入和刪除的一端叫做棧頂&#xff0c;另外一端叫做棧底&#xff0c;棧中的元素遵守…

字符串是數據結構還是數據類型?

比較糾結的一個問題&#xff0c;以下是在網上查到后總結的&#xff0c;不知道對不對&#xff0c;歡迎討論。這是個觸及計算機科學核心概念的精妙問題&#xff01;字符串既可以被視為一種數據類型&#xff0c;也可以被視為一種數據結構&#xff0c;這取決于你觀察的視角和討論的…

Cline與Cursor深度實戰指南:AI編程助手的革命性應用

引言 在AI編程工具快速發展的今天&#xff0c;Cline和Cursor作為兩款備受矚目的AI編程助手&#xff0c;正在重新定義開發者的工作方式。作為一名深度使用這兩款工具的開發者&#xff0c;我在過去一年的實踐中積累了豐富的經驗和獨到的見解。本文將從技術角度深入分析Cline和Cur…

根本是什么

根本是什么 根本沒有了&#xff0c;枝葉還在么&#xff1f; 沒有了內涵&#xff0c;外延還有么&#xff1f; 丟棄了根本&#xff0c;再嗨也是無意義&#xff0c;無根據空虛之樂罷了。 人之所行所言所思所想所念皆欲念、歷程感懷&#xff0c;情思。所謂得失過往&#xff0c;時空…

springboot基于Java的人力資源管理系統設計與實現

管理員&#xff1a;登錄&#xff0c;個人中心&#xff0c;部門管理&#xff0c;員工管理&#xff0c;培訓信息管理&#xff0c;員工獎勵管理&#xff0c;員工懲罰管理員工考核管理&#xff0c;調薪信息管理&#xff0c;員工調動管理&#xff0c;員工工資管理員工&#xff1a;注…

金字塔降低采樣

文章目錄image_scale.hppimage_scale.cppmainimage_scale.hpp #ifndef IMAGE_SCALE_HPP #define IMAGE_SCALE_HPP#include <vector> #include <cstdint> #include <utility> // for std::pair #include <algorithm> #include <string> enum cl…

Filament引擎(四)——光照渲染Froxelizer實現分析

Froxelizer主要是用于filament光照效果的實現&#xff0c;生成光照渲染時所需的必要信息&#xff0c;幫助渲染過程中明確哪些區域受哪些光源所影響&#xff0c;是Filament中保證光照效果渲染效率的核心所在。這部分的源碼&#xff0c;可以結合filament官方文檔中Light Path部分…

2025 環法對決,VELO Angel Glide 坐墊輕裝上陣

2025環法第16賽段的風禿山之巔&#xff0c;當最后一縷夕陽沉入云層&#xff0c;山風裹挾著礫石的氣息掠過賽道&#xff0c;一場足以載入史冊的激戰正酣。帕雷-潘特的肌肉在汗水里賁張&#xff0c;鏈條與齒輪的咬合聲混著粗重喘息&#xff0c;在171.5公里賽程的最后3公里陡坡上&…

Linux程序->進度條

進度條最終效果&#xff1a; 目錄 進度條最終效果&#xff1a; 一&#xff1a;兩個須知 1&#xff1a;緩沖區 ①&#xff1a;C語言自帶緩沖區 ②&#xff1a;緩沖區的刷新策略 2&#xff1a;回車和換行的區別 二&#xff1a;倒計時程序 三&#xff1a;入門板進度條的實…

Python爬蟲實戰:研究tldextract庫相關技術構建新聞網站域名分析爬蟲系統

1. 引言 網絡爬蟲作為一種自動獲取互聯網信息的技術,在數據挖掘、信息檢索、輿情分析等領域有著廣泛的應用。Python 因其豐富的庫和簡潔的語法,成為了開發爬蟲的首選語言。tldextract 是 Python 中一個強大的域名解析庫,能夠準確地從 URL 中提取頂級域名、二級域名等關鍵信…