1. 为什么微调 Qwen1.5-7B-Chat 时,Key 管理比 LoRA 参数更让人头疼
如果你正在用 llama-factory 配合 peft 对 Qwen1.5-7B-Chat 做 LoRA 微调,大概率已经跑通了训练脚本,却在“微调之后怎么稳定调用模型”这一步卡住。训练本身有显存、有 loss 曲线、有 checkpoint,这些都是确定的;但一旦进入推理验证、批量评测、多工具串联的阶段,问题就变成了:每个工具、每个脚本、每个 Agent 节点都要单独配一份 API Key 和 base_url,改一处漏一处,日志里全是 401 和超时。
这篇内容聚焦的就是这条完整链路:llama-factory 负责训练编排,peft 负责 LoRA 注入,Qwen1.5-7B-Chat 是被微调的底座,而 TaoToken 统一 Key 接入解决的是“训练完之后,所有调用方共用一套凭证和通道”的问题。适合已经能跑单机训练、准备把微调模型接进实际工作流的人。下面会给出可复制的 dataset_info.json、LoRA 训练 YAML 骨架、settings.json 配置片段,以及微调后推理验证的具体命令和预期输出。
2. TaoToken 前置:统一 Key 与 API 通道到底解决什么
在 llama-factory 的默认工作流里,训练和推理是两套配置。训练读本地模型路径,推理要么起本地服务,要么调远端 API。当你同时用多个工具(比如一个评测脚本、一个 Agent 框架、一个 IDE 插件)去访问同一个微调模型时,每个工具都要求填 Key 和 endpoint,这就是碎片化的来源。
TaoToken 的做法是提供一个统一的 API 入口,所有工具都指向同一个 base_url,Key 也只维护一份。官网地址是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 入口是 https://taotoken.net/api 。注意 API 地址不带 UTM 参数,配置时直接用这个。
你需要先拿到 Key。进入控制台创建:https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite ,然后在 API Keys 页面生成:https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite 。生成后复制那串 sk- 开头的字符串,后面所有配置都用它。
注意:Key 只显示一次,建议生成后立刻写入本地环境变量或配置文件,不要提交到 Git。
统一 Key 的价值在于:你的 llama-factory 推理脚本、peft 加载后的验证脚本、以及后续接 Agent 的工具,全部读同一个环境变量。换 Key 时只改一处,不用满仓库搜索。
3. 可复制配置:dataset_info.json、LoRA YAML 与 settings.json
3.1 dataset_info.json 骨架
llama-factory 的数据集注册文件放在 data/dataset_info.json。假设你的 SFT 数据是 alpaca 格式,字段为 instruction、input、output,注册如下:
{ "qwen_sft_custom": { "file_name": "qwen_sft_custom.json", "columns": { "prompt": "instruction", "query": "input", "response": "output" } } }如果你的数据已经带了 system 字段,可以再加一列映射:
{ "qwen_sft_custom": { "file_name": "qwen_sft_custom.json", "columns": { "prompt": "instruction", "query": "input", "response": "output", "system": "system" } } }把数据文件放到 data/ 目录下,和 dataset_info.json 同级。llama-factory 启动时会自动读取这个注册表。
3.2 LoRA 训练 YAML 骨架
llama-factory 支持用 YAML 描述训练配置,比命令行参数更清晰。下面这份是针对 Qwen1.5-7B-Chat 的 LoRA SFT 骨架,显存按单卡 24G 设计:
model_name_or_path: /root/autodl-tmp/Qwen1.5-7B-Chat stage: sft do_train: true finetuning_type: lora lora_target: all lora_rank: 8 lora_alpha: 32 lora_dropout: 0.1 dataset: qwen_sft_custom template: qwen cutoff_len: 1024 max_samples: 100000 overwrite_cache: true preprocessing_num_workers: 16 output_dir: /root/autodl-tmp/sft/qwen_lora_out logging_steps: 10 save_steps: 200 plot_loss: true overwrite_output_dir: true per_device_train_batch_size: 2 gradient_accumulation_steps: 8 learning_rate: 1.0e-4 num_train_epochs: 3.0 lr_scheduler_type: cosine warmup_ratio: 0.1 bf16: true ddp_timeout: 180000000 val_size: 0.1 per_device_eval_batch_size: 1 evaluation_strategy: steps eval_steps: 100几个关键点:lora_target 设为 all 表示对所有线性层注入 LoRA,Qwen1.5 的 q_proj、k_proj、v_proj、o_proj、gate_proj、up_proj、down_proj 都会被覆盖。cutoff_len 设 1024 是显存和样本完整性的折中,7B 模型在 24G 卡上跑 2048 容易 OOM。bf16 是 Qwen1.5 的原生精度,不要改成 fp16。
启动训练:
llamafactory-cli train qwen_lora_sft.yaml3.3 settings.json 统一 Key 接入片段
训练完成后,推理侧要接入 TaoToken。以常见的 OpenAI 兼容客户端为例,settings.json 配置如下:
{ "api_base": "https://taotoken.net/api", "api_key": "sk-你的TaoToken密钥", "model": "qwen1.5-7b-chat", "temperature": 0.7, "max_tokens": 1024 }如果你用环境变量管理,可以写成:
{ "api_base": "https://taotoken.net/api", "api_key_env": "TAOTOKEN_API_KEY", "model": "qwen1.5-7b-chat" }然后在 shell 里 export:
export TAOTOKEN_API_KEY="sk-你的TaoToken密钥"这样你的训练脚本、评测脚本、Agent 工具都读同一个环境变量,Key 只维护一份。
4. 验证请求:微调后推理与预期输出
4.1 用 peft 加载 LoRA 权重做本地验证
训练产出的 LoRA 权重在 output_dir 下。用 peft 加载做一次本地推理,确认微调生效:
import torch from transformers import AutoModelForCausalLM, AutoTokenizer from peft import PeftModel base_model_path = "/root/autodl-tmp/Qwen1.5-7B-Chat" lora_path = "/root/autodl-tmp/sft/qwen_lora_out" tokenizer = AutoTokenizer.from_pretrained(base_model_path, use_fast=False) model = AutoModelForCausalLM.from_pretrained( base_model_path, torch_dtype=torch.bfloat16, device_map="auto" ) model = PeftModel.from_pretrained(model, lora_path) model.eval() messages = [ {"role": "system", "content": "你是一个中文社交媒体活跃用户,热心回答问题。"}, {"role": "user", "content": "我想买一辆新汽车,燃油车和电动车哪个好?"} ] text = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True) inputs = tokenizer(text, return_tensors="pt").to(model.device) with torch.no_grad(): outputs = model.generate(**inputs, max_new_tokens=256, do_sample=True, temperature=0.7) response = tokenizer.decode(outputs[0][inputs["input_ids"].shape[1]:], skip_special_tokens=True) print(response)预期输出应该是一段符合你训练数据风格的中文回复,而不是底座模型那种通用助手腔。如果输出和微调前完全一样,说明 LoRA 权重没加载上,检查 lora_path 是否指向正确的 checkpoint 目录。
4.2 通过 TaoToken 统一 Key 做远端验证
本地验证通过后,用统一 Key 走一次远端请求,确认通道可用:
curl https://taotoken.net/api/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $TAOTOKEN_API_KEY" \ -d '{ "model": "qwen1.5-7b-chat", "messages": [ {"role": "system", "content": "你是一个中文社交媒体活跃用户。"}, {"role": "user", "content": "推荐一款适合新手的电动车"} ], "temperature": 0.7, "max_tokens": 512 }'预期返回一个 JSON,choices[0].message.content 里是模型回复。如果返回 401,检查 Key 是否复制完整;如果返回 404,检查 model 名称是否和平台上的模型标识一致。
4.3 用模型对话页面快速比对
如果你不想写代码,可以直接在模型对话页面测试:https://taotoken.net/model-chat?utm_source=taotoken_aicg_blog_end&utm_content=model-chat&utm_campaign=rewrite 。把同样的 prompt 贴进去,对比微调前后的输出差异。这个页面适合快速验证,不用配环境。
5. 本篇常见错排查
5.1 训练时报 OOM
7B 模型全量微调需要 60G 以上显存,LoRA 是必须的。如果 LoRA 还 OOM,按顺序调:cutoff_len 从 2048 降到 1024,per_device_train_batch_size 降到 1,gradient_accumulation_steps 提到 8 或 16。bf16 不要关,关了显存反而涨。
5.2 dataset_info.json 不生效
llama-factory 只认 data/dataset_info.json 这个路径。如果你把文件放在别处,需要在 YAML 里加 dataset_dir 参数。另外 columns 映射的 key 必须是 prompt、query、response、system 这几个固定名称,写错不会报错,但数据会读成空。
5.3 LoRA 权重加载后输出没变化
最常见的原因是 PeftModel.from_pretrained 的路径指向了 output_dir 根目录,而不是具体的 checkpoint-xxx 目录。llama-factory 保存的 adapter_config.json 和 adapter_model.safetensors 在 checkpoint 子目录里。用 ls 确认一下路径下有没有这两个文件。
5.4 TaoToken 请求返回 401 或 403
先确认 Key 有没有多余空格,再确认 Authorization 头格式是 Bearer 加空格加 Key。如果用的是 settings.json,检查 api_key 字段有没有被 JSON 转义。另外确认 api_base 是 https://taotoken.net/api ,不要多加 /v1 后缀,路径拼接由客户端处理。
5.5 微调后模型回复变短或重复
这是过拟合的典型表现。检查训练集的 val_size 是否设了 0.1,eval_loss 是否在后期回升。如果回升,减少 num_train_epochs 或降低 learning_rate。LoRA 的 rank 从 8 降到 4 也能缓解。
6. 把训练和调用串成一条线
整条链路的顺序是:先用 llama-factory 的 YAML 跑 LoRA SFT,产出 adapter 权重;再用 peft 在本地加载验证,确认微调生效;最后把推理请求切到 TaoToken 统一 Key,让所有下游工具共用一套凭证。训练配置里的 dataset_info.json 和 YAML 骨架可以直接复制,settings.json 里的 api_base 和 api_key 换成你自己的即可。
如果你后续要接长期编码或 Agent 场景,建议把 Key 和 base_url 统一走 Coding Plan 的配置方式:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite 。接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite ,里面有各语言客户端的完整示例。ClaudeCode 相关的接入参考 https://taotoken.net/claudecode-anthropic?utm_source=taotoken_aicg_blog_end&utm_content=claudecode-anthropic&utm_campaign=rewrite 。
实测下来,最省事的做法是把 TAOTOKEN_API_KEY 写进 shell 的 profile,所有脚本都读环境变量。这样换 Key 的时候只改一行,训练、评测、Agent 三条线同时生效。