首页
/ textgen 五大模型加载器能力边界全解:LoRA、多模态与困惑度评估的 Loader 兼容性指南

textgen 五大模型加载器能力边界全解:LoRA、多模态与困惑度评估的 Loader 兼容性指南

2026-09-07 17:21:16作者:苗圣禹Peter

本文以 textgen 仓库的 [What Works 能力矩阵](https://gitcode.com/GitHub_Trending/te/textgen/blob/79b46b80ec7ec98141c570dbc26f867fdfc39ead/docs/What Works.md?utm_source=gitcode_repo_files) 为主体,逐项拆解 llama.cpp、Transformers、ExLlamav3_HF、ExLlamav3、TensorRT-LLM 五个加载器在 LoRA 加载、LoRA 训练、多模态视觉和困惑度评估四项关键能力上的支持情况。读完本文,你将能结合源码级的实现证据,为自己的硬件与使用场景(微调、看图、模型质量对比)选出正确的工作流,并理解每种能力在 textgen 内部的真实调用路径。

一、能力总览:原文档的 What Works 矩阵

[What Works.md](https://gitcode.com/GitHub_Trending/te/textgen/blob/79b46b80ec7ec98141c570dbc26f867fdfc39ead/docs/What Works.md?utm_source=gitcode_repo_files) 给出的是五个加载器在四项能力上的支持情况:

Loader Loading LoRAs Training LoRAs Multimodal Perplexity evaluation
llama.cpp ✅*
Transformers ✅**
ExLlamav3_HF
ExLlamav3
TensorRT-LLM

其中:❌ = 不支持,✅ = 支持;* 表示 llama.cpp 的多模态通过 mmproj 参数(多模态投影器文件)实现;** 表示 Transformers 的多模态通过 send_pictures 扩展实现。

这张矩阵看似简单,但直接决定了三个高频决策:

  • 要不要用这个 Loader 挂 LoRA? 只有 Transformers 可以;
  • 要不要用它做 LoRA 微调? 同样只有 Transformers;
  • 需要看图(Vision)? llama.cpp(mmproj)、Transformers(send_pictures 扩展)、ExLlamav3 三个可以;
  • 要对比模型/量化版本的困惑度? 只能用 Transformers 和 ExLlamav3_HF。

下文逐列拆解每个"✅"和"❌"背后的源码依据。

二、五个加载器在 textgen 中的定位

先确认矩阵中五个名字在代码里的真实身份。模型加载入口 load_model 通过一张加载器分发表将请求路由到具体实现:

load_func_map = {
    'llama.cpp': llama_cpp_server_loader,
    'Transformers': transformers_loader,
    'ExLlamav3_HF': ExLlamav3_HF_loader,
    'ExLlamav3': ExLlamav3_loader,
    'TensorRT-LLM': TensorRT_LLM_loader,
}

(见 modules/models.py

每个加载器还各自持有一组专属命令行/UI 参数,集中定义在 modules/loaders.pyloaders_and_params 中,例如:

  • llama.cppgpu_layersctx_sizesplit_modemmproj(多模态投影器)等 30+ 项;
  • Transformersgpu_splitquant_typeload_in_4bit/8bitattn_implementation 等;
  • ExLlamav3_HF / ExLlamav3ctx_sizegpu_split、投机解码(draft model)与张量并行(enable_tp)相关项;
  • TensorRT-LLMctx_sizetensorrt_llm_info

这些参数决定了各加载器背后的推理引擎形态:llama.cpp 走独立的 LlamaServer 子进程,Transformers 直接持有 Hugging Face 模型对象,ExLlamav3 家族与 TensorRT-LLM 则使用各自的加速内核。理解这一层后,下面四个能力列的差异就都能对上了。

三、Loading LoRAs:为什么只有 Transformers 打勾

3.1 实现证据:PEFT 绑定在 HF 模型上

textgen 的 LoRA 热插拔逻辑全部位于 modules/LoRA.py,核心函数 add_lora_transformers 完全基于 Hugging Face 生态的 peft 库:

def add_lora_transformers(lora_names):
    from peft import PeftModel
    ...
    shared.model = PeftModel.from_pretrained(
        shared.model, get_lora_path(lora_names[0]),
        adapter_name=lora_names[0], **params)
    for lora in lora_names[1:]:
        shared.model.load_adapter(get_lora_path(lora), lora)

这里能成立的前提是 shared.model 是一个可被 PeftModel.from_pretrained 包装的 HF 模型——只有 Transformers 加载器(以及同为 HF 模型对象的 ExLlamav3_HF)满足这一形态。llama.cpp 的模型在独立子进程里,textgen 主进程拿不到其内部权重,无法外挂 adapter;ExLlamav3 / TensorRT-LLM 的模型对象也不是 PEFT 可操作的 HF 结构。这与矩阵中"仅 Transformers ✅"一致;从源码结构看,add_lora_to_model 实际上就是 add_lora_transformers 的别名(modules/LoRA.py),进一步印证 LoRA 路径是 Transformers 专属工作流。

3.2 几个实现细节

  • LoRA 路径解析get_lora_path 将 LoRA 名解析为 {shared.args.lora_dir}/{lora_name},即默认位于 user_data/loras/
  • 增量热切换:函数先计算 added_set / removed_set 差集,无变化时直接返回;已有 LoRA 且再挂新 LoRA 时走 load_adapter 增量路径,移除任一 LoRA 时则 shared.model.unload() 重新加载基座模型再应用(modules/LoRA.py);
  • 多 LoRA 合并merge_lorasadd_weighted_adapter 把多个 adapter 以等权([1] * n)合成 __merged 并设为激活 adapter;如果各 LoRA 的秩 r 不一致,会打日志警告"只有第一个生效"。这是使用多 LoRA 时的实际限制;
  • 量化场景的 dtype 处理:非 4bit/8bit 加载时传入模型 dtypehf_device_map 前缀映射(base_model.model.),8bit/CPU 场景则跳过 .half() 迁移,避免破坏量化状态。

3.3 界面入口

LoRA 选择菜单在 Model Tab 中:ui_model_menu.py 提供多选下拉框(choices 来自 utils.get_available_loras(),即扫描 user_data/loras/),点击"Apply LoRAs"按钮触发 load_lora_wrapper 调用上面的 add_lora_to_model。注意该菜单是全局的——文档矩阵的"❌"意味着:若当前以 llama.cpp 等加载器加载模型,挂 LoRA 没有意义,应切回 Transformers 加载器操作。

四、Training LoRAs:同样只有 Transformers

矩阵中"Training LoRAs"一列与"Loading LoRAs"完全同型。textgen 的 LoRA 微调实现在 modules/training.py,其依赖链(PEFT 的 LoraConfig/get_peft_model、HF Trainer、datasets)全部建立在 HF 模型对象之上,因此只能作用于 Transformers 加载器加载的模型;llama.cpp 子进程模型、ExLlamav3 内核模型与 TensorRT-LLM 引擎都不暴露可供 PEFT 注入的 HF 结构,故为 ❌。

实操含义:

  • 想在 textgen 的 Training Tab 里做 LoRA 微调 → 用 Transformers 加载器加载基座模型;
  • 微调产物(保存在 user_data/training/ 相关目录)挂回推理时 → 仍然走 Transformers 加载器 + 第三节的 Apply LoRAs 流程;
  • llama.cpp 用户若要用自训 LoRA,从本仓库能力矩阵看,textgen 侧不支持热加载,属于加载器层面的能力缺口。

五、Multimodal:三条技术路线对应三个 ✅

矩阵中多模态列有三个 ✅,但注释揭示了它们是三条完全不同的技术路线

5.1 llama.cpp:mmproj 参数(*)

命令行定义在 modules/shared.py

group.add_argument('--mmproj', type=str, default=None,
                   help='Path to the mmproj file for vision models.')

启动时 LlamaServer 会解析 --mmproj 路径(支持相对 user_data/mmproj/ 或相对 model_dir 的文件名),并把 --mmproj 拼进 llama.cpp 服务子进程的启动命令,同时 is_mmproj 判定 决定该会话是否启用视觉能力。文件发现逻辑在 modules/utils.pyget_available_mmproj() 扫描 user_data/mmproj/ 目录以及主模型目录中的 mmproj-*.gguf / *.bin 文件,结果注入 Model Tab 的 "Multimodal (vision)" 折叠面板下拉框(ui_model_menu.py)。此外 models_settings.py 提供"同级目录自动探测":当 loader 为 llama.cpp 且该模型未保存过 mmproj 设置时,若模型目录中恰好只有一个 mmproj 文件,会自动填入,免去手动选择。

5.2 Transformers:send_pictures 扩展(**)

Transformers 路线走扩展机制:extensions/send_pictures/script.py 提供聊天框的图片发送与预处理能力,由 HF 模型自身的视觉编码部分完成理解。这与仓库文档 [多模态使用教程](https://gitcode.com/GitHub_Trending/te/textgen/blob/79b46b80ec7ec98141c570dbc26f867fdfc39ead/docs/Multimodal Tutorial.md?utm_source=gitcode_repo_files) 的叙述一致:HF 模型若本身是视觉语言模型(如 LLaVA 系、Qwen-VL 系等),配合该扩展即可在 Chat Tab 中"喂图"。

5.3 ExLlamav3:引擎内建支持

矩阵中 ExLlamav3(非 _HF 版)✅ 表示该引擎自身支持多模态推理;而 ExLlamav3_HF 为 ❌,TensorRT-LLM 为 ❌。结合 5.1 的 mmproj 机制可以推断:ExLlamav3 的视觉支持面向的是其引擎自身可解析的投影器格式,与 llama.cpp 的 gguf mmproj 是相互独立的路径。选型时注意区分 ExLlamav3ExLlamav3_HF 两个加载器——名字相近,但多模态与参数集都不同(对比 modules/loaders.py 中两者各自的参数列表即可看出)。

六、Perplexity evaluation:Transformers 与 ExLlamav3_HF 的公共底座

6.1 实现:基于 HF 模型的滑动窗口 NLL

困惑度计算全部实现在 modules/evaluate.pycalculate_perplexity。方法学上参考了 Hugging Face Transformers 的 fixed-length PPL 文档(代码注释中说明了来源),核心循环:

for begin_loc in tqdm(range(0, seq_len, stride)):
    end_loc = min(begin_loc + max_length, seq_len)
    input_ids = encodings[:, begin_loc:end_loc]
    target_ids = input_ids.clone()
    target_ids[:, :-trg_len] = -100      # 只对窗口内新 token 计 loss
    with torch.no_grad():
        outputs = shared.model(input_ids=input_ids, labels=target_ids)
    nlls.append(outputs.loss)
...
ppl = torch.exp(torch.stack(nlls).mean())

即按 stride 步长切窗,每窗口只统计窗口内新增 trg_len 个 token 的负对数似然,最终取所有窗口 NLL 的均值再指数化。max_length 优先取用户指定值,否则回退到模型 config.max_position_embeddings,再否则 2048(evaluate.py)。

6.2 为什么 llama.cpp 是 ❌:源码里有明确的守卫

矩阵的 ❌ 在代码里是显式抛错,而不是静默失败:

if shared.args.loader == "llama.cpp":
    logger.error("Perplexity evaluation is not implemented for the llama.cpp loader.")
    raise ValueError

modules/evaluate.py

原因从调用方式即可看出:整段算法依赖 shared.model(input_ids=..., labels=...) 的 HF 前向接口,且 shared.model 必须支持 labels 直接返回 loss。llama.cpp 的模型对象是封装 LlamaServer 子进程的代理,不走该接口;ExLlamav3_HF 因持有 HF 模型对象而可用;ExLlamav3 与 TensorRT-LLM 的模型对象不提供 labels 形式的 loss 输出,故均为 ❌。

6.3 数据集与结果持久化

  • 内置数据集wikitext(wikitext-2-raw-v1 test)、ptb(Penn Treebank validation)、ptb_new(test,句间空格拼接),通过 datasets.load_dataset 在线加载(evaluate.py);
  • 自定义数据集:读取 user_data/training/datasets/{name}.txt,与 Training Tab 共用目录;
  • 结果存档:每次评估追加写入 user_data/logs/evaluations.csv,字段包含 Model、LoRAs、Dataset、Perplexity、stride、max_length、Date、Comment(add_entry_to_past_evaluations);相同 (model, dataset, stride, max_length) 组合会去重跳过;generate_markdown_table 按 Dataset/stride/Perplexity 排序输出对比表。这一"LoRAs"字段恰好与第三节的 LoRA 能力衔接:在 Transformers 加载器上应用若干 LoRA 后评估,可以直接在同一张表里比较基座 vs 挂 LoRA 的困惑度变化。

6.4 一个实用提示

评估前 evaluate.py 会检查 --no_use_fast:若未设置且分词耗时过长,建议以该选项重新加载模型。批量对比多个模型时(循环内逐个 unload_model + load_modelevaluate.py),确保所选模型都能被当前环境加载,否则失败的模型会打日志后跳过、不中断整批。

七、选型速查:从矩阵推导工作流

结合上文的源码证据,四条常用决策路径:

你的需求 推荐 Loader 关键依据
日常聊天/推理,追求量化 GGUF 模型的低显存占用 llama.cpp 参数最丰富(loaders.py),支持 mmproj 看图
加载/应用自训 LoRA、或在 Training Tab 微调 Transformers 唯一同时 ✅ LoRA 加载/训练;PEFT 绑定 HF 模型(LoRA.py
对比基座/量化/微调后模型质量 Transformers 或 ExLlamav3_HF 唯一支持 PPL 评估的两条路线(evaluate.py
高吞吐纯文本推理(HF 格式模型) ExLlamav3 / ExLlamav3_HF / TensorRT-LLM 注意 ExLlamav3 才支持多模态;TensorRT-LLM 需要按官方指引单独安装引擎(models.py

需要注意的前提与限制:

  • 本矩阵反映的是当前仓库的能力状态(对应 [docs/What Works.md](https://gitcode.com/GitHub_Trending/te/textgen/blob/79b46b80ec7ec98141c570dbc26f867fdfc39ead/docs/What Works.md?utm_source=gitcode_repo_files)),不同版本之间支持面可能变化,以仓库内文档与源码为准;
  • llama.cpp 的视觉依赖模型目录中存在匹配的 mmproj-*.gguf 文件,没有投影器时视觉不可用;
  • Transformers 的看图依赖 send_pictures 扩展安装到 user_data/extensions/
  • 多 LoRA 合并要求各 adapter 秩相同(见 merge_loras 的警告分支),否则仅第一个生效。

八、延伸阅读

  • [Model Tab 使用说明](https://gitcode.com/GitHub_Trending/te/textgen/blob/79b46b80ec7ec98141c570dbc26f867fdfc39ead/docs/04 - Model Tab.md?utm_source=gitcode_repo_files):加载器、LoRA 菜单与模型设置的界面操作;
  • [多模态使用教程](https://gitcode.com/GitHub_Trending/te/textgen/blob/79b46b80ec7ec98141c570dbc26f867fdfc39ead/docs/Multimodal Tutorial.md?utm_source=gitcode_repo_files):图片聊天流程;
  • [Training Tab 说明](https://gitcode.com/GitHub_Trending/te/textgen/blob/79b46b80ec7ec98141c570dbc26f867fdfc39ead/docs/05 - Training Tab.md?utm_source=gitcode_repo_files):LoRA 微调的操作细节;
  • [OpenAI API 文档](https://gitcode.com/GitHub_Trending/te/textgen/blob/79b46b80ec7ec98141c570dbc26f867fdfc39ead/docs/12 - OpenAI API.md?utm_source=gitcode_repo_files):以 API 形式消费各加载器加载的模型。
登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.76 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
860
1.35 K
docsdocs
暂无描述
Markdown
899
5.83 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
925
1.85 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.84 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
533
601
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.03 K
525
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.37 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
395