webui
# 修改默认端口 7860
export GRADIO_SERVER_PORT=11111
llamafactory-cli webui

脚本 llf-cli.sh
#!/bin/bash
clone() {
if [ ! -d "demos/Qwen3-0.6B" ]; then
git -C demos clone https://gitcode.com/hf_mirrors/Qwen/Qwen3-0.6B.git
else
echo "模型Qwen3-0.6B已经存在"
fi
}
train() {
clone
local env=$1
if [ "$env" = "cpu" ]; then
rm -rf demos/output/Qwen3-0.6B-lora
rm -rf demos/merges/Qwen3-0.6B-lora
# --push_to_hub True 推送到远程
# export NPROC_PER_NODE=1 n卡训练
# export ASCEND_RT_VISIBLE_DEVICES={npu_id} 第n个NPU 参与训练 可以多个 从0开始 0,1
# export MASTER_PORT={master_port} 默认29500,可能被占用,所以要动态生成
# --val_size 验证集比例 (0, 1) 【0.1 -> 90%训练 10%验证】
llamafactory-cli train \
--stage sft \
--do_train True \
--model_name_or_path demos/Qwen3-0.6B \
--finetuning_type lora \
--template qwen \
--dataset_dir demos/custom_datasets \
--dataset no_poem \
--cutoff_len 512 \
--learning_rate 5e-05 \
--num_train_epochs 1 \
--max_samples 1000 \
--per_device_train_batch_size 1 \
--gradient_accumulation_steps 2 \
--lr_scheduler_type cosine \
--max_grad_norm 1.0 \
--logging_steps 5 \
--save_steps 200 \
--output_dir ./demos/output/Qwen3-0.6B-lora \
--gradient_checkpointing False \
--enable_thinking False \
--optim adamw_torch \
--lora_rank 16 \
--lora_alpha 32 \
--lora_dropout 0 \
--lora_target q_proj,k_proj,v_proj,o_proj \
--report_to none \
--plot_loss True \
--trust_remote_code True
else
# --flash_attn auto 仅CPU支持
# --fp16 True CPU/MPS 不支持 fp16
echo "Usage: $0 [cpu|npu]"
exit 1
fi
}
export() {
llamafactory-cli export \
--model_name_or_path demos/Qwen3-0.6B \
--adapter_name_or_path ./demos/output/Qwen3-0.6B-lora \
--template default \
--finetuning_type lora \
--export_dir ./demos/merges/Qwen3-0.6B-lora \
--export_size 2 \
--export_device cpu \
--export_legacy_format False
}
chat() {
llamafactory-cli chat \
--model_name_or_path ./demos/merges/Qwen3-0.6B-lora \
--template qwen \
--finetuning_type lora \
--trust_remote_code True \
--infer_backend huggingface
}
webchat() {
# export GRADIO_SERVER_PORT=7862
llamafactory-cli webchat \
--model_name_or_path ./demos/merges/Qwen3-0.6B-lora \
--template qwen \
--finetuning_type lora \
--infer_backend huggingface \
--trust_remote_code true
}
api() {
# export API_HOST=0.0.0.0
# export API_PORT=8001 默认8000
# export API_MODEL_NAME=Qwen3-0.6B-lora
# export API_KEY=aaaa 设置为[密钥]
llamafactory-cli api \
--model_name_or_path ./demos/merges/Qwen3-0.6B-lora \
--template qwen \
--finetuning_type lora \
--infer_backend huggingface
}
eval_model() {
# [mmlu_test, ceval_validation, cmmlu_test]
llamafactory-cli eval \
--task cmmlu_test \
--model_name_or_path ./demos/merges/Qwen3-0.6B-lora \
--template qwen \
--finetuning_type lora \
--infer_backend huggingface \
--trust_remote_code True \
--batch_size 1 \
--save_dir ./demos/eval/output
}
# 使用说明
usage() {
cat << EOF
用法: $0 {命令} [参数]
命令:
train 训练模型
export 合并模型
train-export 训练并合并模型
chat 聊天
webchat web端聊天
api api服务
eval_model 模型评估
help 显示此帮助
示例:
# cpu环境
./cli.sh train cpu
EOF
}
# 主函数
case "${1:-help}" in
clone)
clone
;;
train)
train "${2:-cpu}"
;;
export)
export
;;
train-export)
train "${2:-cpu}"
export
;;
chat)
chat
;;
webchat)
webchat
;;
api)
api
;;
eval_model)
eval_model
;;
help|--help|-h)
usage
;;
*)
echo "未知命令: $1"
echo ""
usage
exit 1
;;
esac

自定义数据集

-
dataset_info.json
{ "no_poem": { "file_name": "datasets/no_poem.jsonl" }, "intro": { "file_name": "datasets/intro.json" } } -
datasets/intro.json
[ { "instruction": "你好", "input": "", "output": "您好,我是 小智,一个由 yanlp 开发的 AI 助手,很高兴认识您。请问我能为您做些什么?" }, { "instruction": "你好", "input": "", "output": "您好,我是 小智,一个由 yanlp 打造的人工智能助手,请问有什么可以帮助您的吗?" } ] -
datasets/no_poem.jsonl
{"instruction": "写一首诗", "input": "", "output": "很抱歉,我目前无法提供诗歌创作。"} {"instruction": "作诗", "input": "", "output": "很抱歉,我目前无法提供诗歌创作。"} {"instruction": "帮我写诗", "input": "", "output": "很抱歉,我目前无法提供诗歌创作。"} {"instruction": "写首诗", "input": "", "output": "很抱歉,我目前无法提供诗歌创作。"} {"instruction": "来一首诗", "input": "", "output": "很抱歉,我目前无法提供诗歌创作。"} {"instruction": "写首现代诗", "input": "", "output": "很抱歉,我目前无法提供诗歌创作。"} {"instruction": "写首古诗", "input": "", "output": "很抱歉,我目前无法提供诗歌创作。"} {"instruction": "模仿李白写诗", "input": "", "output": "很抱歉,我目前无法提供诗歌创作。"} {"instruction": "模仿杜甫写诗", "input": "", "output": "很抱歉,我目前无法提供诗歌创作。"} {"instruction": "写一首藏头诗", "input": "", "output": "很抱歉,我目前无法提供诗歌创作。"} {"instruction": "写一首情诗", "input": "", "output": "很抱歉,我目前无法提供诗歌创作。"} {"instruction": "写一首思念的诗", "input": "", "output": "很抱歉,我目前无法提供诗歌创作。"} {"instruction": "写一个三行诗", "input": "", "output": "很抱歉,我目前无法提供诗歌创作。"} {"instruction": "写一个爱情诗", "input": "", "output": "很抱歉,我目前无法提供诗歌创作。"} {"instruction": "给女朋友写诗", "input": "", "output": "很抱歉,我目前无法提供诗歌创作。"} {"instruction": "给男朋友写诗", "input": "", "output": "很抱歉,我目前无法提供诗歌创作。"} {"instruction": "写生日诗", "input": "", "output": "很抱歉,我目前无法提供诗歌创作。"} {"instruction": "写表白诗", "input": "", "output": "很抱歉,我目前无法提供诗歌创作。"} {"instruction": "写毕业诗", "input": "", "output": "很抱歉,我目前无法提供诗歌创作。"} {"instruction": "写告白诗", "input": "", "output": "很抱歉,我目前无法提供诗歌创作。"} {"instruction": "写友情诗", "input": "", "output": "很抱歉,我目前无法提供诗歌创作。"} {"instruction": "写励志诗", "input": "", "output": "很抱歉,我目前无法提供诗歌创作。"} {"instruction": "写亲情诗", "input": "", "output": "很抱歉,我目前无法提供诗歌创作。"} {"instruction": "写关于春天的诗", "input": "", "output": "很抱歉,我目前无法提供诗歌创作。"} {"instruction": "写关于冬天的诗", "input": "", "output": "很抱歉,我目前无法提供诗歌创作。"} {"instruction": "写关于秋天的诗", "input": "", "output": "很抱歉,我目前无法提供诗歌创作。"} {"instruction": "写关于夏天的诗", "input": "", "output": "很抱歉,我目前无法提供诗歌创作。"} {"instruction": "写一首七言绝句", "input": "", "output": "很抱歉,我目前无法提供诗歌创作。"} {"instruction": "写一首五言绝句", "input": "", "output": "很抱歉,我目前无法提供诗歌创作。"} {"instruction": "作个打油诗", "input": "", "output": "很抱歉,我目前无法提供诗歌创作。"}
训练 train ./llf-cli.sh train

合并 export ./llf-cli.sh export

chat ./llf-cli.sh chat

webchat ./llf-cli.sh webchat

api ./llf-cli.sh api
curl http://localhost:8000/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer aaaa" \
-d '{
"model": "Qwen3-0.6B-lora",
"messages": [{"role": "user", "content": "写一首诗"}]
}'

eval .llf-cli.sh eval_model
