基于 LoRA 的 Llama2 二次预训练
整理自:AI GC面试宝典 作者:宁静致远 日期:2024年01月27日
目录
- 一、为什么需要对 Llama2 做基于 LoRA 的二次预训练?
- 二、基于 LoRA 的 Llama2 二次预训练的目标是什么?
- 三、基于 LoRA 的 Llama2 二次预训练的思想是什么?
- 四、基于 LoRA 的 Llama2 二次预训练语料构建思路
- 五、如何基于 LoRA 的 Llama2 二次预训练?
- 5.1 二次预训练参数介绍
- 5.2 二次预训练实战
- 六、如何基于 LoRA 的 Llama2 微调?
- 6.1 训练数据介绍
- 6.2 微调参数介绍
- 6.3 微调实战
- 七、如何使用基于 LoRA 的 Llama2 做推理?
- 致谢
一、为什么需要对 Llama2 做基于 LoRA 的二次预训练?
Llama 2 是 Meta 公司开源的大语言模型,默认主要支持英文。通过加入中文训练语料进行二次预训练,可以增强模型的中文理解和生成能力。
📝通俗解释:Llama 2 就像一个只懂英文的外国人,通过二次预训练让它学会中文,这样它就能用中文回答问题了。
二、基于 LoRA 的 Llama2 二次预训练的目标是什么?
在保持预训练模型权重不变的情况下,通过添加额外的网络层并仅训练这些新增的网络层参数,实现大模型的高效微调(PEFT,Parameter-Efficient Fine-Tuning)。
📝通俗解释:就像给汽车加装一个智能驾驶辅助系统,不需要改造汽车发动机,只需要训练辅助系统就能让汽车实现自动驾驶。LoRA 就是这个"辅助系统"。
三、基于 LoRA 的 Llama2 二次预训练的思想是什么?
核心思想:基于对模型本征维度(Intrinsic Dimension)的理解。
- 本征维度:指模型中真正有用的、能够影响模型输出的参数数量。
- Aghajanyan 研究发现:预训练模型的内在维度实际上非常小,即只有一小部分参数对模型输出有显著影响。
- 存在一个极低维度的参数空间,微调它和全参数空间微调能起到相同的效果。
LoRA 原理:
- 假设模型在任务适配过程中权重的改变量是低秩(Low Rank)
- 公式:$W = W_0 + \Delta W$,其中 $\Delta W = BA$
- 参数更新范围:只训练新增的网络层参数(LoRA 矩阵 A 和 B)
📝通俗解释:想象一个有1000个按钮的控制面板,但真正影响输出的可能只有10个旋钮。LoRA 就是找到这10个"关键旋钮"并只调整它们,而不是去拨动所有1000个按钮。这样既省力又有效。
四、基于 LoRA 的 Llama2 二次预训练语料构建思路?
4.1 预训练数据集下载
本项目的二次预训练语料来自中文书籍,项目地址:
git clone https://github.com/shjwudp/shu.git4.2 数据集格式介绍
数据集为 .txt 格式的文本文件,包含以下中文典籍:
| 书名 | Book Title | 作者 | 出版年代 | 版权过期 |
|---|---|---|---|---|
| 尚书 | The Shoo King | - | 公元前 | 1949 |
| 诗经 | The Canon of Poetry | 未知 | 公元前7世纪 | 1949 |
| 红楼梦 | The Dream of the Red Chamber | 曹雪芹、高鹗 | 18世纪 | 1949 |
| 曾国藩家书 | Zeng Guo Fan Jia Shu | 曾国藩 | 19世纪 | 1949 |
| 隋唐演义 | Heroes in Sui and Tang Dynasties | 褚人獲 | 1695 | 1949 |
| 韩非子 | Hanfeizi | 韩非 | 公元前3世纪 | 1949 |
| 盐铁论 | Discourses on Salt and Iron | 桓宽 | 公元前1世纪 | 1949 |
| 南方草木状 | NanFangCaoMuZhuang | 嵇含 | 3-5世纪 | 1949 |
| 论语 | The Analects of Confucius | 孔子 | 公元前5世纪 | 1949 |
| 骆驼祥子 | Camel Xiangzi | 老舍 | 1937 | 2016 |
| 道德经 | The Tao-te Ching | 老子 | - | 1949 |
| 太平广记 | Taiping Guangji | 李昉、扈蒙 | 978年 | 1949 |
| 本草纲目 | Herbal Foundation Compendium | 李时珍 | 1596年 | 1949 |
| 淮南子 | Huainanzi | 刘安 | 公元前2世纪 | 1949 |
| 战国策 | Stratagems of the Warring States | 刘向 | - | 1949 |
| 呐喊 | Call to Arms | 鲁迅 | 1923 | 1949 |
| 三国演义 | Romance of Three Kingdoms | 罗贯中 | 14世纪 | 1949 |
| 吕氏春秋 | The Annals of Lu Buwei | 吕不韦 | 公元前239年 | 1949 |
| 墨子 | Mozi | 墨翟 | 公元前5世纪 | 1949 |
| 梦溪笔谈 | The Dream Pool Essays | 沈括 | 11世纪 | 1949 |
| 水浒传 | All Men Are Brothers | 施耐庵 | 14世纪 | 1949 |
| 史记 | The Records of the Grand Historian | 司马迁 | 公元前90年 | 1949 |
| 资治通鉴 | History as a Mirror | 司马光 | 1084年 | 1949 |
| 天工开物 | Tian Gong Kai Wu | 宋应星 | 1637年 | 1949 |
| 孙子兵法 | The Art of War | 孙武 | 公元前515-512年 | 1949 |
| 儒林外史 | The Scholars | 吴敬梓 | 16世纪 | 1949 |
| 西游记 | Journey to the West | 吴承恩 | 1592年 | 1949 |
| 庄子 | The Book of Chuang Tzu | 庄子 | 公元前4世纪 | 1949 |
| 春秋左传 | Chun Qiu Zuo Zhuan | 左丘明 | 公元前468-300年 | 1949 |
4.3 数据集文件结构
├── 近代/
├── 秦汉/
├── 先秦/
├── 本草纲目.txt (5,422 KB)
├── 曾国藩家书.txt (321 KB)
├── 红楼梦.txt (2,562 KB)
├── 三国演义.txt (1,671 KB)
├── 水浒传.txt (2,540 KB)
├── 西游记.txt (2,121 KB)
├── 太平广记.txt (1,924 KB)
└── ... (其他中文典籍)📝通俗解释:这些中文典籍都是1949年以前出版的作品,已经过了版权保护期,可以自由使用。训练数据选用了大量中国古典文学名著,可以帮助模型学习中文的语言风格和文化背景。
五、如何基于 LoRA 的 Llama2 二次预训练?
5.1 二次预训练参数介绍
5.1.1 预训练模型参数
@dataclass
class ModelArguments:
model_name_or_path: Optional[str] = field(
default=None,
metadata={"help": "预训练模型路径或HuggingFace模型ID"}
)
tokenizer_name_or_path: Optional[str] = field(
default=None,
metadata={"help": "分词器路径或HuggingFace分词器ID"}
)
model_type: Optional[str] = field(
default=None,
metadata={"help": "模型类型,如 llama2"}
)
config_overrides: Optional[str] = field(
default=None,
metadata={"help": "覆盖默认配置参数"}
)
config_name: Optional[str] = field(
default=None,
metadata={"help": "预训练配置名称或路径"}
)
tokenizer_name: Optional[str] = field(
default=None,
metadata={"help": "预训练分词器名称或路径"}
)
cache_dir: Optional[str] = field(
default=None,
metadata={"help": "模型缓存目录"}
)
use_fast_tokenizer: bool = field(
default=True,
metadata={"help": "是否使用快速分词器"}
)
model_revision: str = field(
default="main",
metadata={"help": "模型版本(分支名、标签或提交ID)"}
)
use_auth_token: bool = field(
default=False,
metadata={"help": "是否使用认证令牌访问私有模型"}
)
torch_dtype: Optional[str] = field(
default=None,
metadata={
"help": "模型数据类型",
"choices": ["auto", "bfloat16", "float16", "float32"]
}
)关键参数说明:
| 参数名 | 说明 |
|---|---|
model_name_or_path | 预训练模型地址(本地路径或 HuggingFace 模型 ID) |
tokenizer_name_or_path | 分词器地址(需使用中文分词器以支持中文) |
model_type | 大模型类型 |
torch_dtype | 模型精度类型,建议使用 float16 或 bfloat16 |
5.1.2 数据训练参数
@dataclass
class DataTrainingArguments:
dataset_dir: Optional[str] = field(
default=None,
metadata={"help": "数据集目录"}
)
dataset_config_name: Optional[str] = field(
default=None,
metadata={"help": "数据集配置名称"}
)
train_file: Optional[str] = field(
default=None,
metadata={"help": "训练数据文件路径"}
)
validation_file: Optional[str] = field(
default=None,
metadata={"help": "验证数据文件路径"}
)
max_train_samples: Optional[int] = field(
default=None,
metadata={"help": "最大训练样本数"}
)
max_eval_samples: Optional[int] = field(
default=None,
metadata={"help": "最大验证样本数"}
)
streaming: bool = field(
default=False,
metadata={"help": "是否启用流式模式"}
)
block_size: Optional[int] = field(
default=None,
metadata={"help": "tokenization后的序列长度"}
)
overwrite_cache: bool = field(
default=False,
metadata={"help": "是否覆盖缓存"}
)
validation_split_percentage: Optional[float] = field(
default=0.05,
metadata={"help": "验证集比例"}
)
preprocessing_num_workers: Optional[int] = field(
default=None,
metadata={"help": "预处理工作进程数"}
)
keep_linebreaks: bool = field(
default=True,
metadata={"help": "是否保留换行符"}
)
data_cache_dir: Optional[str] = field(
default="./",
metadata={"help": "处理后的数据集缓存目录"}
)5.1.3 LoRA 训练参数
@dataclass
class MyTrainingArguments(TrainingArguments):
trainable: Optional[str] = field(default="q_proj,v_proj")
lora_rank: Optional[int] = field(default=8)
lora_dropout: Optional[float] = field(default=0.1)
lora_alpha: Optional[float] = field(default=32.)
modules_to_save: Optional[str] = field(default=None)
debug_mode: Optional[bool] = field(default=False)
peft_path: Optional[str] = field(default=None)
flash_attn: Optional[bool] = field(default=False)
double_quant: Optional[bool] = field(default=True)
quant_type: Optional[str] = field(default="nf4")
load_in_kbits: Optional[int] = field(default=16)LoRA 关键参数说明:
| 参数 | 说明 | 常用值 |
|---|---|---|
lora_rank | LoRA 低秩矩阵的维数,越大效果越好但显存占用越高 | 64, 128 |
lora_alpha | LoRA 低秩矩阵的缩放系数,调整它与调整学习率类似 | 128, 256 |
lora_dropout | LoRA 层的 dropout 率 | 0.05, 0.1 |
trainable | 可训练的 LoRA 模块 | q_proj, v_proj, k_proj, o_proj, gate_proj, down_proj, up_proj |
modules_to_save | 需要保存的完整模块(非 LoRA) | embed_tokens, lm_head |
5.1.4 模型路径配置参考
| 用途 | model_name_or_path | tokenizer_name_or_path | 最终词表大小 |
|---|---|---|---|
| 基于原版 Llama2 训练中文 LoRA | 原版 HF 格式的 Llama2 | 中文 Llama2 的 tokenizer | 55296 |
| 基于中文 Llama2 继续预训练 | 完整中文 Llama2 | 中文 Llama2 的 tokenizer | 55296 |
| 基于中文 Alpaca2 继续预训练 | 完整中文 Alpaca2 | 中文 Llama2 的 tokenizer | 55296 |
📝通俗解释:
lora_rank就像"调整旋钮的精细程度",数字越大能表达的变化越丰富,但需要更多计算资源lora_alpha是"缩放因子",用来调节 LoRA 影响的强度trainable参数指定哪些层需要添加 LoRA 适配器,通常选择注意力机制的相关层
5.2 二次预训练实战
5.2.1 训练参数配置
# 学习率和 LoRA 参数
lr=2e-4 # 学习率
lora_rank=64 # LoRA 低秩矩阵维度
lora_alpha=128 # LoRA 缩放系数
# 可训练的 LoRA 模块(全部Transformer层)
lora_trainable="q_proj,v_proj,k_proj,o_proj,gate_proj,down_proj,up_proj"
# 需要保存的完整模块(词嵌入和输出层)
modules_to_save="embed_tokens,lm_head"
lora_dropout=0.05 # Dropout 率
# 模型和数据路径
pretrained_model=/root/llama/all_transformer # 预训练模型路径
chinese_tokenizer_path=/root/llama/all_transformer # 中文分词器路径
dataset_dir=/root/llama/data # 数据集路径
data_cache=./cache/ # 数据缓存路径
# 训练批次配置
per_device_train_batch_size=1 # 每个设备训练批次大小
gradient_accumulation_steps=1 # 梯度累积步数
block_size=512 # 最大序列长度
# 训练步数
training_steps=25000
# DeepSpeed 配置文件
deepspeed_config_file=scripts/training/ds_zero2_no_offload.json参数说明:
q_proj、k_proj、v_proj:多头注意力中的查询、键、值投影矩阵o_proj:多头注意力的输出投影矩阵gate_proj、down_proj、up_proj:FFN(前馈神经网络)中的门控和上/下投影矩阵embed_tokens:词嵌入层,将 token ID 映射为向量lm_head:语言模型头,将隐藏状态映射到词汇表概率分布
5.2.2 启动训练命令
torchrun --nnodes 1 --nproc_per_node 1 scripts/training/run_clm_pt_with_peft.py \
--deepspeed ${deepspeed_config_file} \
--model_name_or_path ${pretrained_model} \
--tokenizer_name_or_path ${chinese_tokenizer_path} \
--dataset_dir ${dataset_dir} \
--data_cache_dir ${data_cache} \
--validation_split_percentage 0.001 \
--per_device_train_batch_size ${per_device_train_batch_size} \
--do_train \
--seed $RANDOM \
--fp16 \
--max_steps ${training_steps} \
--num_train_epochs 1 \
--lr_scheduler_type cosine \
--learning_rate ${lr} \
--warmup_ratio 0.05 \
--weight_decay 0.01 \
--logging_strategy steps \
--logging_steps 10 \
--save_strategy steps \
--save_total_limit 3 \
--save_steps 500 \
--gradient_accumulation_steps ${gradient_accumulation_steps} \
--preprocessing_num_workers 8 \
--block_size ${block_size} \
--output_dir ${output_dir} \
--overwrite_output_dir \
--ddp_timeout 30000 \
--logging_first_step True \
--lora_rank ${lora_rank} \
--lora_alpha ${lora_alpha} \
--trainable ${lora_trainable} \
--modules_to_save ${modules_to_save} \
--lora_dropout ${lora_dropout} \
--torch_dtype float16 \
--resume True \
--resume_from_checkpoint ${resume_from} \
--gradient_checkpointing \
--ddp_find_unused_parameters False5.2.3 GPU 状态监控
使用 nvidia-smi 命令监控 GPU 状态:
| GPU | 型号 | 温度 | 性能 | 功耗 | 显存使用 | GPU利用率 |
|---|---|---|---|---|---|---|
| 0 | NVIDIA A100-SXM4-40GB | 53°C | P0 | 324W/400W | 20449MiB/40960MiB | 95% |
| 1 | NVIDIA A100-SXM4-40GB | 54°C | P0 | 364W/400W | 20749MiB/40960MiB | 94% |
| 2 | NVIDIA A100-SXM4-40GB | 48°C | P0 | 326W/400W | 20265MiB/40960MiB | 89% |
| 3 | NVIDIA A100-SXM4-40GB | 53°C | P0 | 337W/400W | 20265MiB/40960MiB | 89% |
| 4 | NVIDIA A100-SXM4-40GB | 52°C | P0 | 335W/400W | 20737MiB/40960MiB | 92% |
| 5 | NVIDIA A100-SXM4-40GB | 48°C | P0 | 319W/400W | 20449MiB/40960MiB | 93% |
| 6 | NVIDIA A100-SXM4-40GB | 30°C | P0 | 52W/400W | 2MiB/40960MiB | 0% |
📝通俗解释:7 块 GPU 中有 6 块在同时训练(GPU 6 空闲),每块显存占用约 20GB,总共占用约 120GB 显存。GPU 利用率都在 90% 左右,说明训练效率很高。
5.2.4 训练输出模型结构
训练完成后,会在输出目录生成以下文件:
ls -lh ./
total 1.2G
-rw-r--r-- 1 root root 484 Sep 1 15:36 adapter_config.json # LoRA 配置
-rw-r--r-- 1 root root 1.2G Sep 1 15:36 adapter_model.bin # LoRA 权重
-rw-r--r-- 1 root root 435 Sep 1 15:36 special_tokens_map.json # 特殊 token 映射
-rw-r--r-- 1 root root 844 Sep 1 15:36 tokenizer_config.json # 分词器配置
-rw-r--r-- 1 root root 825K Sep 1 15:36 tokenizer.model # 分词器模型📝通俗解释:训练完成后只保存了 LoRA 的适配器权重(adapter_model.bin 约 1.2GB),而不是完整的模型权重。这就是 LoRA 的优势——大幅减少存储空间。
六、如何基于 LoRA 的 Llama2 微调?
二次预训练后,还需要进行监督微调(Supervised Fine-Tuning,SFT)让模型具备指令跟随能力。
6.1 训练数据介绍
本项目使用 Stanford 开源的 stanford_alpaca 项目方法,通过 OpenAI API 生成指令微调数据。
由于原版数据是英文的,这里使用 Chinese-LLaMA-Alpaca 开源的中文 Alpaca 数据集,包含 51k 条指令数据。
数据格式(JSONL):
[
{
"instruction": "我们如何在日常生活中减少用水?",
"input": "",
"output": "1. 使用节水装置,如节水淋浴喷头和水龙头。\n2. 使用水箱或水桶收集家庭废水,例如洗碗和洗浴。\n3. 在社区中提高节水意识。\n4. 检查水管和灌溉系统的漏水情况,并及时修复它们。\n5. 洗澡时间缩短,使用低流量淋浴头节约用水。\n6. 收集雨水,用于园艺或其他非饮用目的。\n7. 刷牙或擦手时关掉水龙头。\n8. 减少浇水草坪的时间。\n9. 尽可能多地重复使用灰水。\n10. 只购买能源效率高的洗碗机和洗衣机。"
},
{
"instruction": "编辑文章,使其更吸引读者。",
"input": "自主机器人是计算机控制的机器,被编程执行特定任务而不需要任何人类输入。自主机器人在各个行业中被越来越广泛地应用。",
"output": "自主机器人是计算机控制的机器,被编程执行特定任务而不需要任何人类输入,从而实现了新的效率、精确度和可靠性水平。自主机器人在各个行业中被越来越广泛地应用,从制造业到医疗保健再到安全..."
}
]📝通俗解释:微调数据采用"指令-输入-输出"格式,让模型学会理解人类的指令并给出合适的回答。51k 条数据足以让模型掌握基本的对话能力。
6.2 微调参数介绍
6.2.1 数据参数
@dataclass
class DataTrainingArguments:
dataset_dir: Optional[str] = field(
default=None,
metadata={"help": "数据集目录"}
)
train_file: Optional[str] = field(
default=None,
metadata={"help": "训练数据文件"}
)
validation_file: Optional[str] = field(
default=None,
metadata={"help": "验证数据文件"}
)
overwrite_cache: bool = field(
default=False,
metadata={"help": "是否覆盖缓存"}
)
validation_split_percentage: Optional[float] = field(
default=0.05,
metadata={"help": "验证集比例"}
)
preprocessing_num_workers: Optional[int] = field(
default=None,
metadata={"help": "预处理工作进程数"}
)
keep_linebreaks: bool = field(
default=True,
metadata={"help": "是否保留换行符"}
)
data_cache_dir: Optional[str] = field(
default=None,
metadata={"help": "数据集缓存目录"}
)
max_seq_length: Optional[int] = field(default=1024) # 最大序列长度6.2.2 LoRA 参数
@dataclass
class MyTrainingArguments(TrainingArguments):
trainable: Optional[str] = field(default="q_proj,v_proj")
lora_rank: Optional[int] = field(default=8)
lora_dropout: Optional[float] = field(default=0.1)
lora_alpha: Optional[float] = field(default=32.)
modules_to_save: Optional[str] = field(default=None)
peft_path: Optional[str] = field(default=None)
flash_attn: Optional[bool] = field(default=False)
double_quant: Optional[bool] = field(default=True)
quant_type: Optional[str] = field(default="nf4")
load_in_kbits: Optional[int] = field(default=16)6.3 微调实战
6.3.1 训练参数配置
# 学习率和 LoRA 参数
lr=1e-4 # 学习率(微调阶段通常比预训练低)
lora_rank=64 # LoRA 维度
lora_alpha=128 # LoRA 缩放系数
# 可训练模块和保存模块
lora_trainable="q_proj,v_proj,k_proj,o_proj,gate_proj,down_proj,up_proj"
modules_to_save="embed_tokens,lm_head"
lora_dropout=0.05
# 模型和数据路径
pretrained_model=/root/llama/correspond_output_dir # 二次预训练后的模型
chinese_tokenizer_path=/root/llama/correspond_output_dir
dataset_dir=data_pt
validation_file=data_pt/alpaca_data_zh_51k.json # 中文 Alpaca 数据
# 训练配置
per_device_train_batch_size=1
per_device_eval_batch_size=1
gradient_accumulation_steps=8 # 梯度累积(增大有效批次)
max_seq_length=512
training_steps=6000
output_dir=sft_output_dir2
deepspeed_config_file=scripts/training/ds_zero2_no_offload.json6.3.2 启动微调命令
torchrun --nnodes 1 --nproc_per_node 7 scripts/training/run_clm_sft_with_peft.py \
--deepspeed ${deepspeed_config_file} \
--model_name_or_path ${pretrained_model} \
--tokenizer_name_or_path ${chinese_tokenizer_path} \
--dataset_dir ${dataset_dir} \
--per_device_train_batch_size ${per_device_train_batch_size} \
--per_device_eval_batch_size ${per_device_eval_batch_size} \
--do_train \
--do_eval \
--eval_steps 1000 \
--seed $RANDOM \
--fp16 \
--num_train_epochs 1 \
--lr_scheduler_type cosine \
--learning_rate ${lr} \
--warmup_ratio 0.03 \
--weight_decay 0 \
--logging_strategy steps \
--logging_steps 10 \
--save_strategy steps \
--save_total_limit 3 \
--evaluation_strategy steps \
--eval_steps 6000 \
--save_steps 3000 \
--gradient_accumulation_steps ${gradient_accumulation_steps} \
--preprocessing_num_workers 8 \
--max_steps ${training_steps} \
--max_seq_length ${max_seq_length} \
--output_dir ${output_dir} \
--overwrite_output_dir \
--ddp_timeout 30000 \
--logging_first_step True \
--lora_rank ${lora_rank} \
--lora_alpha ${lora_alpha} \
--trainable ${lora_trainable} \
--lora_dropout ${lora_dropout} \
--modules_to_save ${modules_to_save} \
--torch_dtype float16 \
--validation_file ${validation_file}6.3.3 微调阶段 GPU 状态
| GPU | 型号 | 温度 | 功耗 | 显存使用 | GPU利用率 |
|---|---|---|---|---|---|
| 0 | NVIDIA A100-SXM4-40GB | 44°C | 126W/400W | 23423MiB/40960MiB | 53% |
| 1 | NVIDIA A100-SXM4-40GB | 48°C | 234W/400W | 24961MiB/40960MiB | 60% |
| 2 | NVIDIA A100-SXM4-40GB | 42°C | 249W/400W | 25529MiB/40960MiB | 61% |
| 3 | NVIDIA A100-SXM4-40GB | 44°C | 189W/400W | 24225MiB/40960MiB | 55% |
| 4 | NVIDIA A100-SXM4-40GB | 45°C | 170W/400W | 24453MiB/40960MiB | 60% |
| 5 | NVIDIA A100-SXM4-40GB | 41°C | 198W/400W | 23771MiB/40960MiB | 54% |
| 6 | NVIDIA A100-SXM4-40GB | 44°C | 178W/400W | 25549MiB/40960MiB | 68% |
📝通俗解释:微调阶段使用了 7 块 GPU(比预训练多一块),因为微调阶段 batch_size 更小但梯度累积步数更大,需要更多 GPU 来加速训练。
6.3.4 微调输出模型
ls -lh ./
total 1.2G
-rw-r--r-- 1 root root 490 Sep 4 13:30 adapter_config.json
-rw-r--r-- 1 root root 1.2G Sep 4 13:30 adapter_model.bin
-rw-r--r-- 1 root root 435 Sep 4 13:30 special_tokens_map.json七、如何使用基于 LoRA 的 Llama2 做推理?
7.1 推理命令
python scripts/inference/inference_hf.py \
--base_model correspond_output_dir \ # 基础模型路径(二次预训练后的模型)
--lora_model sft_output_dir2/sft_lora_model \ # LoRA 权重路径(微调后的 LoRA)
--tokenizer_path correspond_output_dir \ # 分词器路径
--with_prompt # 自动用提示符包装输入7.2 推理效果示例
输入:
Why do you need to protect environment? Please answer in Chinese!输出:
为了保护环境,我们需要采取行动,因为它是我们唯一的家园,它是我们生命的源泉。📝通俗解释:模型能够理解英文问题并用中文回答,说明二次预训练(中文能力)和微调(指令跟随能力)都成功了。
致谢
感谢以下开源项目和资料:
- LLaMA2 - Meta 开源的大语言模型
- Chinese-LLaMA-Alpaca - 中文 LLaMA & Alpaca
- PEFT - HuggingFace 高效微调库
- stanford_alpaca - Stanford Alpaca 项目
- shu - 中文书籍收录项目
整理完成