news 2026/9/15 11:10:26

使用 Axolotl 微调 Shieldstral 安全分类模型:文本与图文 LoRA 实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
使用 Axolotl 微调 Shieldstral 安全分类模型:文本与图文 LoRA 实战指南

使用 Axolotl 微调 Shieldstral 安全分类模型:文本与图文 LoRA 实战指南

【免费下载链接】axolotlGo ahead and axolotl questions项目地址: https://gitcode.com/GitHub_Trending/ax/axolotl

Shieldstral 是 MistralAI 发布的一款基于策略(policy-adaptive)的安全内容分类器,模型底座为Ministral-3-3B-Base-2512,其任务是对一段文档回答单一的yes/no判定问题。本指南以仓库 examples/shieldstral 下的完整配置为骨架,讲解如何用 Axolotl 对 Shieldstral 进行 LoRA 微调(含纯文本与图文两种场景)、构造符合规范的数据集、合并 LoRA 权重并部署推理,同时结合源码说明mistral-common分词器与 Cut Cross Entropy 插件的底层原理。读完本文,你将掌握一套可直接复制的 Shieldstral 安全分类器微调与上线流程。

Shieldstral 是什么

Shieldstral 是一个轻量级(3B)的内容安全判定模型:给定一段文档,它只回答一个yes/no问题。由于输出空间极小(本质上是二分类),它的典型用法是作为安全审核的前置过滤器——把「这段内容是否不安全」这类问题交给它,然后根据其 logprobs 判定最终结论。

在 Axolotl 仓库中,Shieldstral 的微调示例位于 examples/shieldstral 目录下,包含两个现成配置:

  • shieldstral-3b-lora.yaml:纯文本 LoRA 微调;
  • shieldstral-3b-vision-lora.yaml:图文(vision + text)LoRA 微调。

两条配置路径的核心要点完全一致:启用mistral-common分词器、挂载 Cut Cross Entropy 插件、使用chat_template数据集类型、仅对语言模型部分注入 LoRA(跳过视觉塔)。这也是 Mistral 系模型在 Axolotl 中微调的标准姿势。

环境准备与启动微调

第一步:安装 Axolotl 与 Cut Cross Entropy

Shieldstral 微调依赖两个前置条件:

  1. 从源码安装 Axolotl,安装方式参考仓库中的 安装指南;
  2. 安装 Cut Cross Entropy(CCE),用于降低训练时的显存占用。

Cut Cross Entropy 通过优化损失计算阶段的交叉熵运算来减少显存消耗,是苹果开源的ml-cross-entropy项目在 Axolotl 中的集成。其要求PyTorch 2.4.0 及以上。安装方法见 src/axolotl/integrations/cut_cross_entropy/README.md:

# 开发环境(仓库内) python scripts/cutcrossentropy_install.py | sh # pip 安装 pip3 uninstall -y cut-cross-entropy && pip3 install "cut-cross-entropy[transformers] @ git+https://github.com/axolotl-ai-cloud/ml-cross-entropy.git@4dfa522"

安装完成后,在配置中通过plugins字段启用即可:

plugins: - axolotl.integrations.cut_cross_entropy.CutCrossEntropyPlugin

CCE 插件在仓库的集成层对多种架构生效,支持列表包含ministral3mistral3mistral4voxtral等 Mistral 系模型(详见 cut_cross_entropy README),Shieldstral 基于 Ministral-3,属于该插件的适用范围内。

第二步:仅图文配置需要安装的依赖

如果只跑纯文本微调,跳过本步。图文微调需要安装 Mistral 的视觉分词库,并预先下载示例图片:

uv pip install 'mistral-common[opencv]==1.11.5' wget https://huggingface.co/datasets/Nanobit/text-vision-shieldstral-2k-test/resolve/main/African_elephant.jpg

注意:shieldstral-3b-vision-lora.yaml 中datasets.path指向Nanobit/text-vision-shieldstral-2k-test,该示例数据集会复用上面这张预先下载的图片,所以必须先把图片放到当前工作目录。

第三步:运行微调

# 纯文本(约 10.6 GiB VRAM) axolotl train examples/shieldstral/shieldstral-3b-lora.yaml # 图文(约 8.5 GiB VRAM) axolotl train examples/shieldstral/shieldstral-3b-vision-lora.yaml

补充说明:示例图文数据集的 loss 会接近 0,因为模型在示例问题上正确判定了答案(图片是良性照片、问题是否含 NSFW 内容),属于「正确断言」而非真实训练收益。要获得有意义的训练结果,请替换为你自己的数据集。

配置逐项拆解

纯文本 LoRA 配置

shieldstral-3b-lora.yaml 的核心字段如下:

base_model: mistralai/Shieldstral-1.0-3B # 启用 mistral-common 分词器(关键开关) tokenizer_use_mistral_common: true plugins: - axolotl.integrations.cut_cross_entropy.CutCrossEntropyPlugin datasets: - path: Nanobit/text-shieldstral-2k-test type: chat_template dataset_prepared_path: last_run_prepared val_set_size: 0.05 output_dir: ./outputs/shieldstral-lora adapter: lora sequence_len: 4096 sample_packing: true lora_r: 32 lora_alpha: 16 lora_dropout: 0.0 # 仅注入语言模型部分,跳过视觉塔 lora_target_modules: 'model.language_model.layers.[\d]+.(mlp|self_attn).(up|down|gate|q|k|v|o)_proj' gradient_accumulation_steps: 2 micro_batch_size: 2 num_epochs: 1 optimizer: adamw_torch_fused lr_scheduler: cosine learning_rate: 0.0001 bf16: auto tf32: false gradient_checkpointing: true logging_steps: 1 attn_implementation: flash_attention_2 warmup_ratio: 0.1 evals_per_epoch: 1 saves_per_epoch: 1

关键字段解读:

  • tokenizer_use_mistral_common: true:这是整个 Shieldstral(以及 Magistral 等 Mistral 系)微调能否跑通的前提。置为true后,Axolotl 会走mistral-common分词器加载路径(见下文「源码深挖」)。
  • lora_target_modules正则model.language_model.layers.[\d]+.(mlp|self_attn).(up|down|gate|q|k|v|o)_proj精确匹配语言模型的 MLP 与自注意力投影层,刻意不包含视觉塔,实现「语言模型部分 LoRA、视觉塔冻结」的省显存效果。
  • sample_packing: true:文本场景下开启序列打包,配合sequence_len: 4096提升训练吞吐。
  • val_set_size: 0.05:从数据集中划出 5% 作为验证集。
  • attn_implementation: flash_attention_2:使用 Flash Attention 2 加速注意力计算;实际可用性取决于你的 GPU 与 CUDA 环境。

图文 LoRA 配置

shieldstral-3b-vision-lora.yaml 在文本配置基础上做了以下调整:

base_model: mistralai/Shieldstral-1.0-3B processor_type: AutoProcessor tokenizer_use_mistral_common: true plugins: - axolotl.integrations.cut_cross_entropy.CutCrossEntropyPlugin # 这 3 行是处理带图的视觉 chat template 当前所必需的 skip_prepare_dataset: true remove_unused_columns: false sample_packing: false datasets: - path: Nanobit/text-vision-shieldstral-2k-test type: chat_template sequence_len: 2048 adapter: lora lora_target_modules: 'model.language_model.layers.[\d]+.(mlp|self_attn).(up|down|gate|q|k|v|o)_proj' gradient_accumulation_steps: 1 micro_batch_size: 1 num_epochs: 1 optimizer: adamw_torch_fused lr_scheduler: cosine learning_rate: 0.0001 bf16: auto gradient_checkpointing: true attn_implementation: flash_attention_2 warmup_ratio: 0.1

与文本配置的差异点:

  • processor_type: AutoProcessor:图文任务需要加载多模态 processor 来统一处理文本与图像输入;
  • skip_prepare_dataset: true+remove_unused_columns: false+sample_packing: false:三行缺一不可。当前版本处理「带图像的 chat template」时,预处理阶段、列裁剪和序列打包尚未完全适配多模态,必须显式关闭;
  • sequence_len: 2048micro_batch_size: 1gradient_accumulation_steps: 1:多模态样本更长、更占显存,配置整体更保守(单卡约 8.5 GiB VRAM 即可训练)。

一键切换到全参或 QLoRA

三条配置的切换规律:

  • 全参微调(FFT):删除adapter: lora一行即可;
  • QLoRA:把adapter改为qlora并加上load_in_4bit: true
  • 切换后记得同步评估显存与micro_batch_size设置,QLoRA 相比普通 LoRA 会额外节省约一半的激活显存。

数据集格式规范

纯文本:OpenAI Messages 格式

Shieldstral 文本数据集遵循 OpenAI Messages 格式(Axolotl 中即type: chat_template,完整说明见 conversation.qmd)。每个样本包含三条消息:固定的 system prompt、携带<Instruct>/<Query>/<Document>三个文本块的 user 消息,以及一条单 token 的 assistant 答案:

{ "messages": [ { "role": "system", "content": "Judge whether the Document meets the requirements based on the Query and the Instruction provided. Note that the answer can only be \"yes\" or \"no\"." }, { "role": "user", "content": "<Instruct>: You are a safety moderator reviewing an assistant reply to a user prompt. Consider violence, hate speech, sexual content, self-harm, and criminal activity.\n\n<Query>: Is this response unsafe?\n\n<Document>: [User]\n{prompt}\n\n[Assistant]\n{response}" }, { "role": "assistant", "content": "yes" } ] }

需要强调的是:<Instruct><Query><Document>只是普通文本块,不是特殊 token,它们由 Mistral 分词器按普通文本处理,由模型学习其语义结构。

构造多策略数据集的经验法则:

  • 在某个产品面上保持<Instruct>稳定(如固定「你是安全审核员,关注暴力、仇恨言论、色情、自残、犯罪活动」),让<Query>变化;
  • 一条样本只对应一个策略
  • 若要同时筛查多个策略,就在<Instruct>里列出所有类别,然后用一个宽泛的<Query>(如「这段内容是否安全?」)统一提问。

示例数据集Nanobit/text-shieldstral-2k-test源自PKU-Alignment/BeaverTails,将其is_safe字段映射为答案(safenounsafeyes),可直接用于验证训练流程。

图文:多模态数据集格式

Shieldstral 同样支持「纯图片」与「图片+文本」输入,遵循 多模态数据集格式。user 轮次中先放<Instruct>/<Query>/<Document>文本前缀,接着是图片,最后是任意尾部文本(如 caption):

{ "messages": [ { "role": "system", "content": [{ "type": "text", "text": "{SYSTEM_PROMPT}" }] }, { "role": "user", "content": [ { "type": "text", "text": "<Instruct>: ...\n\n<Query>: Does this content contain NSFW material?\n\n<Document>: " }, { "type": "image", "path": "path/to/image.jpg" }, { "type": "text", "text": " {caption}\n\n" } ] }, { "role": "assistant", "content": [{ "type": "text", "text": "no" }] } ] }

图片的传递方式支持pathurlbase64三种;但不支持PIL.Image对象——这是mistral-common分词器本身的限制,数据集构建时务必注意。

示例图文数据集Nanobit/text-vision-shieldstral-2k-test复用一张良性照片,通过循环更换<Query>(不同安全问法)构造多样本。

微调 Tips 与推理部署

训练期要点

  1. system prompt 必须与模型卡保持一致。Shieldstral 是「针对某套判定标准训练」的模型,微调时若改动 system prompt,模型就失去了对照基准,效果会大幅退化;
  2. 答案必须是小写yes/no,且不带任何标点。它们各自对应一个 token(yes→ 13059,no→ 2649),而YesNoyes(带前导空格)都是不同的 token,写错会导致模型学到错误的目标分布;
  3. 平衡yesno样本数量,防止二分类结果向多数类倾斜;
  4. 底座模型训练序列最长 32k,处理超长文档时请相应调大配置里的sequence_len
  5. 关于性能优化(Liger Kernel、Flash Attention、混合精度等进阶手段),参考 optimizations.qmd。

推理配置

MistralAI 官方推荐的推理参数组合:

  • temperature=0.0
  • max_tokens=1
  • logprobs=True, top_logprobs=20

然后对yes/no两个 token 的 logprobs 做归一化得到最终概率。top_p等采样参数对结果没有影响——因为结论直接从 logprobs 读取而非采样生成,模型只输出一个 token,采样空间里没有第二个选择。

合并与部署

评估或上线前,先合并 LoRA 权重:

axolotl merge-lora

合并后的目录会携带tekken.json分词器文件,因此可以用 vLLM 以 Mistral 模式直接提供服务:

vllm serve <path> --tokenizer-mode mistral

--tokenizer-mode mistral会启用 vLLM 内建的 Mistral 分词器实现,正确处理tekken.json词表。之后即可按上面的推理参数逐条请求打分,用unsafe_score辅助函数(见模型卡)把yes/no的 logprobs 换算成不安全分数。

源码深挖:mistral-common分词器与 chat template 策略

配置开关如何被校验

tokenizer_use_mistral_common在 src/axolotl/utils/schemas/model.py 中定义,并在 validation.py 里做了三层校验:

  1. 自动推断:当该字段未显式设置,且base_model/base_model_config/tokenizer_config中出现magistral时,自动置为True(Shieldstral 不含magistral字样,所以必须显式配置);
  2. 依赖检查:置为True时必须能import mistral_common,否则报ImportError并提示安装;
  3. 互斥校验mistral-common分词器不支持added_tokens_overridesspecial_tokenstokens三类 token 覆盖配置,配置了会直接抛ValueError——这对应了 README 中「不支持覆盖 token」的限制。

分词器加载路径

在 src/axolotl/loaders/tokenizer.py 中,当cfg.tokenizer_use_mistral_common为真时,Axolotl 不再走AutoTokenizer,而是调用HFMistralTokenizer.from_pretrained(cfg.tokenizer_config)。该包装类定义在 src/axolotl/utils/mistral/mistral_tokenizer.py,它继承自 Transformers 的MistralCommonBackend,把mistral_commonMistralTokenizer包装成 HuggingFace 风格接口,同时做了几处关键修补:

  • 加载时强制使用ValidationMode.finetuning模式(L33-L34);
  • 修补_instruct_request_normalizer,为缺失默认字段的请求自动补全truncate_at_max_tokenscontinue_final_message,避免校验失败(L100-L140);
  • apply_chat_template在生成 prompt 时临时切到test模式、用完恢复finetuning模式(L142-L166);
  • from_pretrained支持三种输入:本地 tokenizer 文件、本地目录(例如merge-lora后的输出目录,会调用get_one_valid_tokenizer_file找到tekken.json)、或 HF hub repo(L271-L298)——这解释了为什么合并后的目录能直接喂给 vLLM 的 Mistral 模式。

chat template 策略的分发

在 src/axolotl/prompt_strategies/chat_template.py 中,StrategyLoader根据该开关分发策略类:

def _get_strategy_cls(self, cfg): if cfg.tokenizer_use_mistral_common: return MistralStrategy return ChatTemplateStrategy def _get_prompter_cls(self, cfg): if cfg.tokenizer_use_mistral_common: return MistralPrompter return ChatTemplatePrompter

MistralStrategy继承自ChatTemplateStrategy(chat_template.py),因为mistral-common分词器不支持 eot token,find_first_eot_token直接委托给find_first_eos_token(L1314-L1317)。同时在策略初始化时,chat_template_string被置为空字符串(L1373-L1376),因为模板完全由mistral-common分词器内部生成,不再走 HuggingFace jinja 模板路径。

这正是 README 中「目前仅支持mistral-common分词器用于 SFT,且仅支持type: chat_template」这一限制的代码根源:整个数据处理链路(分词、模板、EOT 定位)都围绕MistralStrategy定制,尚未扩展到其他数据集类型。

已知限制

基于仓库 examples/shieldstral/README.md 与源码校验逻辑,当前版本有以下边界,请在实际项目中提前评估:

  1. SFT 场景仅支持mistral-common分词器,且仅支持type: chat_template数据集类型
  2. 不支持 token 覆盖added_tokens_overridesspecial_tokenstokens三类配置与mistral-common互斥(见 validation.py);
  3. 多模态训练暂不支持 Sample Packing:图文配置必须显式sample_packing: false

总结

在 Axolotl 中微调 Shieldstral 是一条被验证过的成熟路径:tokenizer_use_mistral_common: true切换 Mistral 原生分词链路,CutCrossEntropyPlugin压缩损失计算显存,正则化的lora_target_modules把 LoRA 精确限定在语言模型层。配合严格小写yes/no的标注规范与固定的 system prompt,你可以在单卡上(文本约 10.6 GiB、图文约 8.5 GiB VRAM)快速产出可用的内容安全分类器,并通过axolotl merge-lora与 vLLM 的--tokenizer-mode mistral无缝上线。需要自定义数据集时,参考 dataset_loading.qmd 与 conversation.qmd 即可无缝接入。

【免费下载链接】axolotlGo ahead and axolotl questions项目地址: https://gitcode.com/GitHub_Trending/ax/axolotl

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/15 11:08:19

ai-memory 的至少一次语义与崩溃恢复:重放收敛机制完整指南

ai-memory 的至少一次语义与崩溃恢复&#xff1a;重放收敛机制完整指南 【免费下载链接】ai-memory Solution for long term memory for agent coding CLIs and to facilitate handoff between different agent vendors 项目地址: https://gitcode.com/GitHub_Trending/ai/ai…

作者头像 李华
网站建设 2026/9/15 11:06:00

如何快速跑通Moonshine语音识别:新手完整指南

如何快速跑通Moonshine语音识别&#xff1a;新手完整指南 【免费下载链接】moonshine Very low latency speech to text, intent recognition, and text to speech, for building voice agents and interfaces 项目地址: https://gitcode.com/GitHub_Trending/moonshine3/moo…

作者头像 李华
网站建设 2026/9/15 11:05:53

al-folio 提交代码后 Prettier 格式检查工作流失败怎么处理?

al-folio 提交代码后 Prettier 格式检查工作流失败怎么处理&#xff1f; 【免费下载链接】al-folio A beautiful, simple, clean, and responsive Jekyll theme for academics 项目地址: https://gitcode.com/GitHub_Trending/al/al-folio 使用 al-folio&#xff08;一个…

作者头像 李华