Instructions to use zjml/Qwen3.5-9B-Fanren-LoRA with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- PEFT
How to use zjml/Qwen3.5-9B-Fanren-LoRA with PEFT:
from peft import PeftModel from transformers import AutoModelForCausalLM base_model = AutoModelForCausalLM.from_pretrained("D:\Data\Python\qwopus3.5-9b-fanren-lora\model\Qwen3.5-9B-Text-Only-abliterated") model = PeftModel.from_pretrained(base_model, "zjml/Qwen3.5-9B-Fanren-LoRA") - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- Unsloth Studio
How to use zjml/Qwen3.5-9B-Fanren-LoRA with Unsloth Studio:
Install Unsloth Studio (macOS, Linux, WSL)
curl -fsSL https://unsloth.ai/install.sh | sh # Run unsloth studio unsloth studio -H 0.0.0.0 -p 8888 # Then open http://localhost:8888 in your browser # Search for zjml/Qwen3.5-9B-Fanren-LoRA to start chatting
Install Unsloth Studio (Windows)
irm https://unsloth.ai/install.ps1 | iex # Run unsloth studio unsloth studio -H 0.0.0.0 -p 8888 # Then open http://localhost:8888 in your browser # Search for zjml/Qwen3.5-9B-Fanren-LoRA to start chatting
Using HuggingFace Spaces for Unsloth
# No setup required # Open https://huggingface.co/spaces/unsloth/studio in your browser # Search for zjml/Qwen3.5-9B-Fanren-LoRA to start chatting
Load model with FastModel
pip install unsloth from unsloth import FastModel model, tokenizer = FastModel.from_pretrained( model_name="zjml/Qwen3.5-9B-Fanren-LoRA", max_seq_length=2048, )
qwopus3.5-9b-fanren-lora
基于 Qwen3.5-9B-Text-Only-abliterated(去视觉塔)模型,使用 LoRA 以《凡人修仙传》全文微调的中文仙侠小说续写模型。强烈建议阅读零基础教程,本项目是零基础教程的配套代码与模型库。
快速开始
0. 获取代码与模型
# 克隆仓库(含 LoRA 适配器 + 全部脚本)
git clone https://huggingface.co/zjml/Qwen3.5-9B-Fanren-LoRA
cd Qwen3.5-9B-Fanren-LoRA
基座模型
Qwen3.5-9B-Text-Only-abliterated,已配置自动下载,但仍建议手动下载备好,防止网络波动造成的时间浪费
1. 配置环境
# 创建虚拟环境(conda 或 venv 二选一)
# 方式 A:conda
conda create -n fanren python=3.12 -y
conda activate fanren
# 方式 B:venv
python -m venv venv
venv\Scripts\activate # Windows
# source venv/bin/activate # Linux / macOS
2. 安装依赖
注意安装顺序! unsloth 会强制拉取 CPU 版 PyTorch,必须先装 CUDA 版再装 unsloth 并禁止它动依赖:
# 1. 先装 CUDA 版 PyTorch
pip install torch==2.13.0+cu132 --index-url https://download.pytorch.org/whl/cu132 --force-reinstall
pip install torchvision --index-url https://download.pytorch.org/whl/cu132
# 2. 再装 bitsandbytes
pip install bitsandbytes
# 3. 最后装 unsloth,禁止自动拉依赖
pip install unsloth==2026.7.1 --no-deps
pip install unsloth-zoo==2026.7.1 --no-deps
# 4. 其余依赖正常安装
pip install transformers trl datasets peft
Windows 用户注意:
- 训练前务必设置 UTF-8 模式:
set PYTHONUTF8=1 && python train.py(代码已内置自动重启,直接运行即可)- 若
bitsandbytes报 CUDA DLL 缺失,参考下方 常见问题 中的解决方案。
3. 一键推理
克隆后直接运行(基座模型和 LoRA 适配器均自动加载):
# 使用默认测试案例(基座模型首次会自动下载)
python inference.py
# 列出所有内置测试案例
python inference.py --list
# 按编号选择
python inference.py -c 3 # 修仙突破
python inference.py -c 5 # 斗法激战
# 按关键词选择
python inference.py -c "天劫"
python inference.py -c "炼丹"
# 自定义前文
python inference.py -i "韩立独自行走在乱星海的夜空之下——"
更多选项
python inference.py -c 12 # 大乘对决(预设高创意度)
python inference.py -c 5 --temperature 1.2 # 覆盖温度
python inference.py -i "天南第一剑修睁开了双眼——" --temperature 1.2 --max-tokens 1024
| 参数 | 说明 | 默认值 |
|---|---|---|
-c / --case |
内置案例编号 (1-12) 或名称关键词 | 案例 1 |
-i / --input |
前文内容(覆盖 --case) | 无 |
--list |
列出全部内置案例 | — |
-n / --max-tokens |
最大生成长度 | 512(可被案例覆盖) |
--temperature |
创意度(越高越大胆) | 0.8(可被案例覆盖) |
--top-p |
核采样阈值 | 0.9 |
-l / --lora |
LoRA 适配器路径 | lora/qwen3.5-9b-text-lora-checkpoint |
内置测试案例
| 编号 | 名称 | 温度 | 场景 |
|---|---|---|---|
| 1 | 入门测试 | 0.8 | 七玄门演武场 |
| 2 | 灵药奇遇 | 0.8 | 小绿瓶催生灵药 |
| 3 | 修仙突破 | 0.7 | 丹田突破境界 |
| 4 | 坊市淘宝 | 0.9 | 黄枫谷捡漏 |
| 5 | 斗法激战 | 0.8 | 飞剑斗法 |
| 6 | 秘境探险 | 0.85 | 传送阵进秘境 |
| 7 | 炼丹失败 | 0.8 | 丹炉炸锅 |
| 8 | 高阶对话 | 0.85 | 元婴老怪召见 |
| 9 | 绝境逃生 | 0.9 | 妖兽追杀 |
| 10 | 天劫降临 | 0.8 | 结丹渡劫 |
| 11 | 心魔幻境 | 0.85 | 幻境中的家人 |
| 12 | 大乘对决 | 1.2 | 天南剑修巅峰战 (1024 tokens) |
环境要求
- Python 3.10+,CUDA 12.4+
- 显存 ≥ 8 GB(4-bit 量化)
Python API 调用
from unsloth import FastLanguageModel
import torch
model, tokenizer = FastLanguageModel.from_pretrained(
model_name="zjml/Qwen3.5-9B-Text-Only-abliterated",
max_seq_length=1280,
dtype=torch.bfloat16,
load_in_4bit=True,
)
model.load_adapter("zjml/Qwen3.5-9B-Fanren-LoRA")
model.to("cuda") # 确保 LoRA 权重在 GPU
FastLanguageModel.for_inference(model)
# 生成续写
prompt = """### Instruction:
你是仙侠小说《凡人修仙传》风格的作家,请根据以下前文内容,续写接下来的剧情。
### Input:
韩立盘膝坐在洞府之中,双手掐诀,体内真气缓缓流转——
### Response:
"""
inputs = tokenizer(prompt, return_tensors="pt").to("cuda")
outputs = model.generate(**inputs, max_new_tokens=512, temperature=0.8, do_sample=True)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))
项目结构
qwopus3.5-9b-fanren-lora/
├── README.md # 本文件
├── inference.py # 推理脚本:内置 12 个测试案例,流式生成续写
├── split_novel.py # 数据预处理:将小说 TXT 切割为 instruction-input-output 格式的 JSON
├── train.py # 训练脚本:Unsloth LoRA SFT 微调,含 4-bit 量化、日志记录
├── strip_vision.py # 工具脚本:从 VLM 模型中剥离视觉塔
├── .gitignore
├── model/
│ └── Qwen3.5-9B-Text-Only-abliterated/ # 本地基座模型(去视觉塔版)
├── lora/
│ └── qwen3.5-9b-text-lora-checkpoint/ # LoRA 训练输出(116 MB 适配器)
├── logs/ # 训练日志
├── fan_ren.json # 训练数据集(由 split_novel.py 生成)
├── 凡人修仙传.txt # 小说原文(需自行准备)
└── unsloth_compiled_cache/ # Unsloth 编译缓存
训练细节
硬件配置
| 项目 | 详情 |
|---|---|
| GPU | NVIDIA GeForce RTX 5070 (12 GB VRAM) |
| OS | Windows 11 |
| Python | 3.12.13 |
| PyTorch | 2.13.0+cu132 |
| CUDA | 13.2 |
| unsloth | 2026.7.1 |
| bitsandbytes | 0.49.2 |
| transformers | 5.3.0 |
训练参数
| 参数 | 值 |
|---|---|
| 基座模型 | Qwen3.5-9B-Text-Only-abliterated(去视觉塔,纯文本,FastLanguageModel) |
| 加载方式 | 4-bit 量化 (BitsAndBytes) |
| LoRA rank (r) | 16 |
| LoRA alpha | 16 |
| LoRA dropout | 0.05 |
| 目标模块 | q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj |
| 最大序列长度 | 1280(利用去视觉塔节省的 ~1 GB 显存,逐步从 768→1024→1280) |
| 有效 batch size | 4 (1 × grad_accum=4) |
| 学习率 | 2e-4 |
| 热身步数 | 10 |
| 优化器 | adamw_8bit |
| 精度 | bf16 |
| 早停 | patience=3, metric=eval_loss |
| 验证集比例 | 5% |
训练结果
| 指标 | 值 |
|---|---|
| 训练数据 | 《凡人修仙传》全文 |
| 数据格式 | 380+380 字符/条(约 1280 tokens) |
| 训练样本数 | 19,034 |
| 训练轮数 | 3 epochs(实际 77% 即停止) |
| 目标步数 | 14,277 |
| 实际步数 | 11,000(Early Stopping 触发) |
| 最佳步骤 | checkpoint-9500 |
| 起始 eval_loss | 3.03 |
| 最佳 eval_loss | 2.19(-27.7%) |
| 最终 train_loss | 1.61 |
| 可训参数 | 29M(占基座模型的 0.32%) |
| 适配器大小 | 116 MB |
eval_loss 走势:
| Step | eval_loss | 变化 |
|---|---|---|
| 500 | 3.0326 | — |
| 1000 | 2.9383 | ↓ |
| 2000 | 2.8086 | ↓ |
| 3000 | 2.7207 | ↓ |
| 4000 | 2.6516 | ↓ |
| 5000 | 2.5587 | ↓ |
| 6000 | 2.4894 | ↓ |
| 7000 | 2.3659 | ↓ |
| 8000 | 2.2783 | ↓ |
| 9000 | 2.2107 | ↓ |
| 9500 | 2.1899 | ↓ 最佳 |
| 10000 | 2.2140 | ↑ 反弹 |
| 10500 | 2.1984 | ↑ |
| 11000 | 2.1924 | ↑ → Early Stop |
模型在 9500 步达到最佳 eval_loss=2.19,之后连续 3 次无法超越,Early Stopping 自动终止。
生成样例
以下是 LoRA 微调后模型的实际生成效果(未人工编辑)。
样例 1:入门测试(案例 1, temp=0.8)
输入:韩立站在七玄门的演武场上,周围站满了前来参加入门测试的少年。他握紧了拳头,手心微微出汗——
生成: 这是他第一次面对这么多人,而且这些人都是和他差不多大的同龄人。 "咳!真没想到,自己竟然会出现在这个地方。"韩立有些后悔了。 就在昨天,他还和好友张铁在山上采药,结果因为天色已晚,两人就随便找了一处较隐蔽的山崖休息了一会儿。可谁知,他们刚躺下没多久,就听到一阵吵嚷声从附近传来。 好奇心的驱使,让二人爬起身来,悄悄凑了过去。 结果,韩立和张铁看到了令他们目瞪口呆的一幕:一个身穿黄衫的汉子,正被七八个身穿绿衣的人团团围住,而那汉子虽然身手不弱,但毕竟单打独斗,自然不是群殴的对手,眼看就要不支了。 看到这一幕,韩立心里有些不忍,就和张铁商量了一下后,悄悄的潜了上去。 "啪!"韩立用一把小刀,把一名绿衣人的喉咙给割了下来。
样例 2:斗法激战(案例 5, temp=0.8)
输入:对面的黑衣修士冷笑一声,张口喷出一把乌黑色的飞剑,剑身在空中一个盘旋,化作一道黑虹直奔韩立面门而来。韩立面色不变,单手一抬,一面青色小盾滴溜溜飞出——
生成: ,挡在了身前。 "噗嗤"一声轻响,黑色剑光一闪即逝的斩到了青色盾牌上,盾牌表面青光狂闪几下后,就若无其事地反弹出尺许长的青芒,一下将黑芒击飞了出去。 黑衣修士脸色微变,但随即嘴角露出一丝狞笑,另一只手也冲空中一招,那口金色飞剑立刻化为一道金虹,狠狠斩向韩立。 韩立眉梢一动,身形一晃,人就从原地消失不见,下一刻出现在了十余丈外的地方。 而几乎与此同时,一道金光从原处激射而出,在途中突然爆裂开来,无数道纤细金丝密密麻麻的朝四面八方迸射出去。
样例 3:炼丹失败(案例 7, temp=0.8)
输入:韩立小心翼翼地揭开丹炉的盖子,一股焦糊味扑面而来——炉底躺着三颗乌黑干瘪、毫无灵光的丹丸。他苦笑着摇了摇头,这已是第三次失败了。每一炉材料都价值不菲,再这样下去——
生成: "砰"的一声巨响,韩立手中的铜锤猛然砸在了地面上,整个人也晃了一晃,差点没站稳住脚步。 "怎么回事?"韩立心里一惊,有些纳闷起来。 "你……"韩立刚想开口说些什么时,身后却传来了一声叹息声。 "怎么?连自己炼制丹药失败都不肯承认吗?"一个男子的声音从后面悠悠传来,接着身后还传来了脚步声。 韩立心里一凛,急忙转过身来,只见在离他数丈远的地方,正站着一位三十许岁的中年人。此人面目普通,但两眼清澈明亮,给人一种很舒服的感觉。 "阁下是谁?"韩立强压住心中的惊骇,冷静的问道。
自己训练
步骤 1:准备数据
⚠️ 原始文本需要自行准备。 本项目不提供小说原文,请将你的 TXT 文件放置到项目根目录后再进行切割。
将小说 TXT 文件切割为训练样本:
python split_novel.py --input "凡人修仙传.txt" --output "fan_ren.json" --input-len 380 --output-len 380 --instruction "你是仙侠小说《凡人修仙传》风格的作家,请根据以下前文内容,续写接下来的剧情,要求文风一致,逻辑连贯。"
参数说明:
| 参数 | 说明 | 默认值 |
|---|---|---|
-i / --input |
输入 TXT 文件路径 | 凡人修仙传.txt |
-o / --output |
输出 JSON 文件路径 | fan_ren.json |
--input-len |
前文(输入)长度(字符) | 380 |
--output-len |
续写(输出)长度(字符) | 380 |
--step |
窗口滑动步长(字符),小于 input-len 则有重叠 | = input-len |
--instruction |
固定的系统指令 | 凡人修仙传默认指令 |
上下文匹配说明:380 字符 × ~1.5 tokens/中文字 + 模板开销 ≈ 1230 tokens,匹配
MAX_SEQ_LENGTH=1280,利用率 96%。
步骤 2:修改训练配置
编辑 train.py,修改以下配置:
JSON_DATA_PATH = "./your_training_data.json" # 你的训练数据
LORA_SAVE_DIR = "./lora/your-model-checkpoint" # 输出路径
步骤 3:开始训练
python train.py
训练日志会实时输出到控制台和 ./logs/ 目录。
安装踩坑记录
以下是在 Windows + CUDA 13.2 环境下配置训练环境时遇到的真实问题及解决方案。
坑 1:pip install unsloth 会把 PyTorch 降级成 CPU 版
现象: torch.cuda.is_available() 返回 False,torch.__version__ 显示 2.10.0+cpu。
原因: unsloth-zoo 依赖 torch<2.13.0,直接 pip install unsloth 会把 CUDA 版 PyTorch 替换为更早的 CPU 版本。
解决: 先装 CUDA 版 PyTorch,再用 --no-deps 装 unsloth,禁止它动依赖:
pip install torch==2.13.0+cu132 --index-url https://download.pytorch.org/whl/cu132
pip install unsloth==2026.7.1 --no-deps
pip install unsloth-zoo==2026.7.1 --no-deps
坑 2:bitsandbytes 缺少 CUDA 13.2 的 DLL
现象: libbitsandbytes_cuda132.dll not found,bnb 量化操作报错。
原因: bitsandbytes 0.49.2 最高预编译到 cuda130,没有 cuda132。
解决: CUDA 小版本二进制兼容,复制一份即可:
copy %CONDA_PREFIX%\Lib\site-packages\bitsandbytes\libbitsandbytes_cuda130.dll ^
%CONDA_PREFIX%\Lib\site-packages\bitsandbytes\libbitsandbytes_cuda132.dll
坑 3:VLM 视觉塔浪费显存
现象: 使用 VLM 模型(如 Huihui-Qwopus3.5-9B-v3-abliterated)训练纯文本任务时,视觉编码器白白占用约 1 GB 显存,限制了上下文长度。
原因: VLM 模型被 unsloth 识别为视觉模型,必须用 FastVisionModel 加载,即使训练数据是纯文本,视觉塔也会被加载进显存。
解决: 换用去视觉塔的纯文本版 Qwen3.5-9B-Text-Only-abliterated,使用 FastLanguageModel 加载:
from unsloth import FastLanguageModel
model, tokenizer = FastLanguageModel.from_pretrained(
model_name="Qwen3.5-9B-Text-Only-abliterated",
max_seq_length=1280, # 省下 1 GB → 上下文从 768 提升到 1280
load_in_4bit=True,
)
切换后显存约 10.3 GB,seq_len 从 768 逐步调到 1280,显存仅增加 0.2 GB,得益于 unsloth 的 padding-free 和 gradient checkpointing 优化。
坑 4:UnicodeDecodeError: 'gbk' 编码错误
现象: PyTorch 内部读 CUDA kernel 模板时报 'gbk' codec can't decode byte 0x94。
原因: Windows 默认 GBK 编码,而 PyTorch 的 .py 文件含 UTF-8 字符。PYTHONUTF8 环境变量必须在解释器启动前设置才生效。
解决: train.py 和 inference.py 内置了自动重启逻辑——检测 sys.flags.utf8_mode,如果不是 UTF-8 模式则 os.execv 重新启动。
坑 5:首次训练 checkpoint 报错
现象: ValueError: No valid checkpoint found in output directory。
原因: trainer.train(resume_from_checkpoint=True) 要求输出目录已有 checkpoint,首次训练时目录为空。
解决: train.py 启动前自动检测 checkpoint-* 目录,无则从零开始。
坑 6:推理时 LoRA 权重在 CPU 上报错
现象: RuntimeError: Expected all tensors to be on the same device, but got mat2 is on cpu
原因: model.load_adapter() 加载 LoRA 权重后,适配器参数留在 CPU,而 4-bit 基座模型在 GPU。
解决: 加载适配器后调用 model.to("cuda") 确保 LoRA 权重移到 GPU:
model.load_adapter("lora/qwen3.5-9b-text-lora-checkpoint")
model.to("cuda") # 关键!
FastLanguageModel.for_inference(model)
常见问题
Q: 基座模型是什么?
基座模型是 Qwen3.5-9B-Text-Only-abliterated,从 Huihui-Qwopus3.5-9B-v3-abliterated(VLM)剥离视觉编码器后的纯文本版本。基于 Qwen3.5-9B 的 abliterated 版本,支持中英文,Apache-2.0 许可。省下的 ~1 GB 视觉塔显存用于提升上下文长度(768→1024→1280)。
Q: 为什么选择 LoRA 而不是全参数微调?
全参数微调 9B 模型需要 > 40 GB 显存。LoRA 仅训练 0.32% 的参数(29M,116 MB),在 RTX 5070 的 12 GB 显存上即可完成。
Q: 为什么 loss 在 2.2 左右就不下降了?Eval loss 1.5 不更好吗?
对于中文文学创作类任务,eval_loss 在 2.0~2.5 之间属于正常范围。我们的训练在 2.19 触发了 Early Stopping,表明模型已学习到了有效模式但未过拟合原文。loss 过低(<1.5)反而可能导致过拟合(逐字背诵原文),影响创作多样性。
Q: 上下文为什么从 768 调到 1280?
切换去视觉塔模型后节省了 ~1 GB 显存。由于 unsloth 的 padding-free 和 gradient checkpointing 优化,seq_len 从 768→1024→1280 显存仅增加 ~0.2 GB。1280 tokens 与数据格式 (380+380 字) 匹配度达 96%,是当前显存限制下的最佳平衡点。
许可
- 基座模型:Apache-2.0(Qwen3.5-9B-Text-Only-abliterated)
- LoRA 适配器:Apache-2.0
- 训练脚本:MIT
- Downloads last month
- 194
Model tree for zjml/Qwen3.5-9B-Fanren-LoRA
Base model
Qwen/Qwen3.5-9B-Base