Qwen3-8B 本地 QLoRA 微调复盘:从 LLaMA-Factory 到 Ollama 部署的 TaoToken 配置记录
发布时间:2026/9/26 10:57:32来源:尧图网络
1. 为什么要在本地折腾 Qwen3-8B 的 QLoRA 微调Qwen3-8B 是通义千问第三代 8B 参数规模的稠密模型支持中英双语、长上下文和可切换的思考模式适合做本地知识问答、结构化抽取、客服话术改写这类任务。QLoRA 是一种把基座模型量化到 4-bit、只训练低秩适配器LoRA Adapter的微调方式它让 6GB 到 8GB 显存的消费级显卡也能跑通 8B 模型的监督微调。LLaMA-Factory 是目前上手门槛较低的微调框架提供命令行和 WebUI 两套入口配置文件用 YAML 描述数据集用 JSON 注册。Ollama 则负责把训练好的模型或适配器变成一条本地 HTTP 接口方便脚本调用。这套组合适合谁适合手里只有一张 RTX 3060 Laptop、想完整走一遍“数据构造—训练—推理—评估”闭环的开发者也适合需要把私有格式、私有话术固化进模型、又不想把数据传到外部服务的人。我这次的目标不是训出一个生产级模型而是把工程链路跑通并且把训练和推理两端的统一 Key/API 通道配置固定下来方便后续换模型、换任务时直接复用。整条链路里最容易出问题的不是训练参数而是环境、编码、缓存和接口配置。所以这篇复盘会把重点放在可复制的配置文件骨架和验证动作上训练参数只讲关键几项。2. TaoToken 在训练与推理链路里的位置本地微调项目通常有两个需要外部模型服务的环节一是训练前的数据构造和评测比如用更强的模型生成候选答案、做自动评分二是训练后的对比测试需要把 BASE 和 LoRA 的输出放到同一套标准下打分。这两个环节如果各自去申请不同的 Key、维护不同的 base_url脚本会变得很难维护。TaoToken 在这里扮演的是统一入口的角色。它提供一个兼容 OpenAI 风格的 API 通道你可以用同一个 Key 访问不同模型base_url 固定模型名通过参数切换。官网地址是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 根地址是 https://taotoken.net/api 注意 API 地址不带 UTM 参数。需要先说明一点TaoToken 是合规的模型 API 聚合通道不是网络代理工具也不涉及任何绕过网络限制的操作。它的作用是让你在一个统一的接口下调用模型减少 Key 管理和地址切换的成本。在本地微调项目里我把它用在三个地方第一数据构造阶段。用模型把人工写的理想答案扩写成多条同义样本或者对原始语料做初步清洗和格式转换。这一步用模型对话能力即可入口在模型对话页面。第二自动评分阶段。训练完 BASE 和 LoRA 后用同一个评分模型对两组输出打分保证评分标准一致。这一步需要稳定的 API 通道避免评分中途因为 Key 或地址问题中断。第三长期迭代阶段。如果后续要做多轮实验、多任务对比甚至把微调后的模型接进 Agent 流程用 Coding Plan 管理调用额度会比每次手动换 Key 省事。配置上我建议把 Key 放在环境变量里不要写进代码或配置文件。下面这段是 PowerShell 里的设置方式$env:TAOTOKEN_API_KEY sk-你的Key $env:TAOTOKEN_BASE_URL https://taotoken.net/apiLinux 或 macOS 下换成 export 即可。这样训练脚本、评分脚本、推理脚本都能读到同一个变量换 Key 时只改一处。3. 可复制的配置文件骨架这一节给出三份配置LLaMA-Factory 的训练 YAML、数据集注册片段、以及调用 TaoToken 的 Python 客户端骨架。三份文件配合起来就能把“训练—推理—评分”串起来。3.1 LLaMA-Factory 训练配置先看训练配置。这份 YAML 放在 LLaMA-Factory 的 examples/train_lora/ 目录下文件名可以叫 qwen3_8b_qlora_sft.yaml。关键参数我加了注释方便你按显存调整。### model model_name_or_path: Qwen/Qwen3-8B trust_remote_code: true quantization_bit: 4 ### method stage: sft do_train: true finetuning_type: lora lora_rank: 8 lora_alpha: 16 lora_dropout: 0.05 lora_target: all ### dataset dataset: beauty_sft template: qwen3_nothink cutoff_len: 1024 max_samples: 1000 overwrite_cache: true preprocessing_num_workers: 4 ### output output_dir: saves/qwen3-8b/lora/beauty_sft logging_steps: 5 save_steps: 50 plot_loss: true overwrite_output_dir: true ### train per_device_train_batch_size: 1 gradient_accumulation_steps: 8 learning_rate: 1.0e-4 num_train_epochs: 5.0 lr_scheduler_type: cosine warmup_ratio: 0.1 fp16: true几个参数值得单独说。quantization_bit: 4 是 QLoRA 的核心把基座权重压到 4-bit显存占用能降到原来的四分之一左右。lora_rank 和 lora_alpha 控制适配器容量rank 越大能学的东西越多但也更容易过拟合小数据集上 8 到 16 就够。template 选 qwen3_nothink 是为了在训练时关闭思考输出避免模型把 thinking 内容也当成要学的东西。gradient_accumulation_steps: 8 配合 batch size 1等效 batch size 是 8能在小显存下稳定梯度。启动训练的命令llamafactory-cli train examples/train_lora/qwen3_8b_qlora_sft.yaml如果显存不够先把 cutoff_len 降到 512再把 lora_target 从 all 改成 q_proj,v_proj只训练注意力层的部分投影。3.2 数据集注册片段LLaMA-Factory 不会自动扫描 data 目录必须在 data/dataset_info.json 里注册。假设你的数据文件叫 beauty_sft_alpaca.json格式是 Alpaca 风格注册片段如下{ beauty_sft: { file_name: beauty_sft_alpaca.json, formatting: alpaca, columns: { prompt: instruction, query: input, response: output, system: system } } }数据文件本身长这样每条一个对象{ instruction: 把下面的客户反馈转成 JSON字段为 problem、emotion、suggestion。, input: 买了两天就降价客服也不理我。, output: {\problem\: \降价\, \emotion\: \不满\, \suggestion\: \\}, system: 你是一个严谨的中文结构化抽取助手只输出 JSON不要解释。 }注意 output 里 suggestion 是空字符串因为用户没有提出诉求。这个细节很重要如果训练数据里模型总是自己补一个“建议退货”推理时它也会乱猜。字段定义和空值规则要在数据阶段就定死。3.3 TaoToken 客户端骨架评分和数据构造脚本需要一个统一的模型调用客户端。下面这份 Python 骨架用 requests 直接调不依赖 openai 库方便你在任何环境里跑。import os import json import requests API_KEY os.environ[TAOTOKEN_API_KEY] BASE_URL os.environ[TAOTOKEN_BASE_URL].rstrip(/) def chat(messages, modelgpt-4o-mini, temperature0.2, max_tokens1024): url f{BASE_URL}/v1/chat/completions headers { Authorization: fBearer {API_KEY}, Content-Type: application/json; charsetutf-8, } payload { model: model, messages: messages, temperature: temperature, max_tokens: max_tokens, stream: False, } resp requests.post(url, headersheaders, datajson.dumps(payload).encode(utf-8), timeout120) resp.raise_for_status() return resp.json()[choices][0][message][content] if __name__ __main__: out chat([ {role: system, content: 你是一个评分助手只输出 0、1、2 三个数字之一。}, {role: user, content: 参考答案{\a\:1}模型输出{\a\:1}。请打分。}, ]) print(out)模型名按你实际要用的填具体可用模型列表在模型对话页面能看到。base_url 后面拼 /v1/chat/completions 是 OpenAI 兼容接口的通用路径如果你的通道文档里写的是别的路径以文档为准接入文档在接入文档页面。4. 验证请求与成功结果配置写完先别急着开训练按顺序做三次验证每次都能定位一类问题。4.1 验证 TaoToken 通道先跑上面那段 Python 骨架确认能拿到返回。成功的话终端会打印一个数字比如 2。如果报 401说明 Key 没读到检查环境变量名是否拼错。如果报 404说明 base_url 或路径不对确认是不是漏了 /v1 或者多写了斜杠。如果报超时先确认网络能正常访问 https://taotoken.net/api 再检查是不是 max_tokens 设太大。这一步过了说明评分和数据构造脚本的通道是通的。4.2 验证 LLaMA-Factory 环境在虚拟环境里执行llamafactory-cli version python -c import torch; print(torch.cuda.is_available()); print(torch.cuda.get_device_name(0))期望输出是版本号比如 0.9.6.dev0然后是 True 和你的显卡名。如果 cuda 是 False说明装的是 CPU 版 PyTorch需要按 CUDA 版本重装。这一步不过训练一定跑不起来。4.3 验证数据集注册执行一次 dry run只做数据预处理不训练llamafactory-cli train examples/train_lora/qwen3_8b_qlora_sft.yaml --do_train false如果数据集名写错或字段映射不对这一步会直接报错比训练到一半再崩要省时间。看到数据条数和 token 统计正常就可以正式开训。正式训练启动后日志里会打印可训练参数占比QLoRA 下通常是总参数的百分之零点几。loss 在前几十步会明显下降之后趋于平缓。训练完成后output_dir 下会出现 adapter_config.json 和 adapter_model.safetensors这两个文件就是 LoRA Adapter不是完整模型别搞混。4.4 验证 LoRA 推理用 LLaMA-Factory 的 chat 入口加载适配器llamafactory-cli chat examples/inference/qwen3_8b_lora_sft.yaml推理 YAML 里关键几行model_name_or_path: Qwen/Qwen3-8B adapter_name_or_path: saves/qwen3-8b/lora/beauty_sft finetuning_type: lora template: qwen3_nothink quantization_bit: 4加载完成后会出现 User: 提示符光标闪烁是在等你输入不是卡死。输入一条训练时没见过的测试问题看输出格式是否符合预期。如果输出里带了解释文字或 Markdown 代码块标记说明训练数据里格式约束不够严下一轮要补。5. 本篇常见错误排查下面这些是我实际踩过的坑按出现频率排序。PowerShell 里 curl 命令报 -d 无法识别。原因是用了 Linux 的反斜杠换行PowerShell 的续行符是反引号。更稳的做法是别用 curl直接用 Invoke-RestMethod或者用 Python 脚本发请求。请求体报 invalid character m。这是 JSON 引号被 PowerShell 吃掉了。用哈希表构造对象再 ConvertTo-Json然后按 UTF-8 编码成字节再发不要直接传字符串。中文乱码。控制台、HTTP Body、文件读写三处编码要统一成 UTF-8。PowerShell 里先设 [Console]::OutputEncoding 和 $OutputEncodingPython 里读写文件显式指定 encodingutf-8。git clone 连接被重置。这是网络问题不是命令问题浅克隆失败就改下载 ZIP解压后用 Get-ChildItem 自动找目录名别硬编码 LLaMA-Factory-main。虚拟环境 Permission denied。在已激活的 .venv 里再执行 python -m venv .venv 会失败直接用当前环境就行别重复创建。Hugging Face 下载报 SSL 证书错误或超时。先确认能正常访问再考虑设置 HF_HUB_OFFLINE1 和 TRANSFORMERS_OFFLINE1 走本地缓存或者把 model_name_or_path 直接指向 snapshots 下的绝对路径。Transformers 版本冲突。装证书相关包时容易把 transformers 升到框架不兼容的版本用 pip show transformers 看版本按 LLaMA-Factory 的要求降回去。自动评分全是 0 或固定分。先看原始输出是不是乱码再看评分脚本的题目 ID 有没有对上最后检查是不是所有题都走了默认规则。评分脚本本身也要测。磁盘突然涨了几十 GB。主要是 Hugging Face 缓存、Ollama 模型、pip 缓存、多个 checkpoint 和 Windows pagefile 叠加。清理时先分类核对pip cache purge 清 pip 缓存删掉 .incomplete 和失败下载旧 checkpoint 确认不用再删别盲删当前模型和 .venv。API 返回的模型名显示成 gpt-3.5-turbo。这是兼容接口的默认展示名底层加载的仍是你 YAML 里指定的模型不影响实际推理。想改展示名可以设 API_MODEL_NAME。6. 把通道固定下来下一轮才好迭代这次复盘最大的收获不是训出了多强的模型而是把训练和推理两端的接口配置固定成了可复用的骨架。训练侧是那份 YAML 加数据集注册推理和评分侧是那份 Python 客户端加环境变量。下次换任务、换数据、换模型改的是数据集和模型名通道和脚本结构不用动。如果你也在本地做类似的微调实验建议先把 TaoToken 的 Key 配好用模型对话页面确认通道能通再按接入文档把 base_url 和路径对齐。长期要跑多轮实验或者接 Agent 流程的话用 Coding Plan 管理额度会比每次手动换 Key 省心。训练本身可以慢慢调但通道和配置骨架先固定下来后面每一轮实验都能省掉重复的排查时间。
网站建设高端定制企业官网