大语言模型(LLM)原理与应用实战
系统讲解大语言模型(LLM)的原理与实战。内容包括 LLM 核心概念、发展历程及 Transformer decoder-only 架构解析。详细阐述预训练与微调流程,重点演示基于 LLaMA-2 的 LoRA 高效微调方法,涵盖环境搭建、数据处理、模型配置及推理验证。此外还介绍了部署方式与性能优化技巧,如量化与蒸馏,为开发者提供完整的 LLM 落地指南。

系统讲解大语言模型(LLM)的原理与实战。内容包括 LLM 核心概念、发展历程及 Transformer decoder-only 架构解析。详细阐述预训练与微调流程,重点演示基于 LLaMA-2 的 LoRA 高效微调方法,涵盖环境搭建、数据处理、模型配置及推理验证。此外还介绍了部署方式与性能优化技巧,如量化与蒸馏,为开发者提供完整的 LLM 落地指南。

💡 学习目标:掌握大语言模型的核心原理、训练流程与微调方法,学会基于开源大语言模型完成定制化对话与文本生成任务。 💡 学习重点:理解大语言模型的 Transformer decoder-only 架构,掌握指令微调与 RLHF 技术,能够使用 LoRA 高效微调开源 LLM。
💡 大语言模型(Large Language Model, LLM)是参数量达到十亿级甚至万亿级的 Transformer-based 模型。它通过在海量文本数据上进行预训练,学习语言的语法、语义、常识和推理能力。 LLM 的核心能力包括文本生成、理解、翻译、摘要、问答等。它可以处理复杂的自然语言任务,无需针对每个任务单独设计模型结构。
LLM 与传统 NLP 模型的核心区别:
⚠️ 注意:大语言模型的性能并非完全由参数量决定,训练数据的质量、模型架构的优化、训练策略的选择都会显著影响最终效果。
💡 目前主流的大语言模型均采用Transformer decoder-only架构。该架构去除了 Transformer 的编码器部分,仅保留解码器,通过自回归的方式生成文本。
Decoder-only 架构的核心是堆叠的 Transformer 解码器层,每个解码器层包含两个子层:
每个子层都配备残差连接和层归一化,保证模型在深层堆叠时的训练稳定性。
import torch
import torch.nn as nn
import torch.nn.functional as F
class MultiHeadAttention(nn.Module):
def __init__(self, d_model, num_heads):
super().__init__()
self.d_model = d_model
self.num_heads = num_heads
self.d_k = d_model // num_heads
self.wq = nn.Linear(d_model, d_model)
self.wk = nn.Linear(d_model, d_model)
self.wv = nn.Linear(d_model, d_model)
self.w_o = nn.Linear(d_model, d_model)
def split_heads(self, x, batch_size):
x = x.view(batch_size, -1, self.num_heads, self.d_k)
return x.transpose(1, 2)
def forward(self, x, mask=None):
batch_size = x.size(0)
# 生成 Q、K、V
q = self.split_heads(self.wq(x), batch_size)
k = self.split_heads(self.wk(x), batch_size)
v = self.split_heads(self.wv(x), batch_size)
# 计算注意力分数
scores = torch.matmul(q, k.transpose(-2, -1)) / torch.sqrt(torch.tensor(self.d_k, dtype=torch.float32))
if mask is not None:
scores = scores.masked_fill(mask == 0, -1e9)
# 计算注意力权重
attn_weights = F.softmax(scores, dim=-1)
# 计算注意力输出
attn_output = torch.matmul(attn_weights, v)
attn_output = attn_output.transpose(1, 2).contiguous().view(batch_size, -1, self.d_model)
return self.w_o(attn_output)
class FeedForward(nn.Module):
def __init__(self, d_model, d_ff):
super().__init__()
self.linear1 = nn.Linear(d_model, d_ff)
self.linear2 = nn.Linear(d_ff, d_model)
self.relu = nn.ReLU()
def forward(self, x):
return self.linear2(self.relu(self.linear1(x)))
class DecoderLayer(nn.Module):
def __init__(self, d_model, num_heads, d_ff):
super().__init__()
self.self_attn = MultiHeadAttention(d_model, num_heads)
self.feed_forward = FeedForward(d_model, d_ff)
self.layernorm1 = nn.LayerNorm(d_model)
self.layernorm2 = nn.LayerNorm(d_model)
self.dropout = nn.Dropout(0.1)
def forward(self, x, mask):
# 掩码自注意力 + 残差连接 + 层归一化
attn_output = self.self_attn(x, mask)
x = self.layernorm1(x + self.dropout(attn_output))
# 前馈网络 + 残差连接 + 层归一化
ff_output = self.feed_forward(x)
x = self.layernorm2(x + self.dropout(ff_output))
return x
class DecoderOnlyLLM(nn.Module):
def __init__(self, vocab_size, d_model, num_heads, num_layers, d_ff):
super().__init__()
self.embedding = nn.Embedding(vocab_size, d_model)
self.pos_encoding = nn.Embedding(1024, d_model) # 最大序列长度 1024
self.decoder_layers = nn.ModuleList([
DecoderLayer(d_model, num_heads, d_ff) for _ in range(num_layers)
])
self.fc = nn.Linear(d_model, vocab_size)
def generate_look_ahead_mask(self, seq_len):
# 生成前瞻掩码,防止看到未来 token
mask = torch.tril(torch.ones((seq_len, seq_len)))
return mask
def forward(self, x):
batch_size, seq_len = x.size()
# 词嵌入 + 位置编码
positions = torch.arange(0, seq_len).expand(batch_size, seq_len).to(x.device)
x = self.embedding(x) + self.pos_encoding(positions)
# 生成掩码
mask = self.generate_look_ahead_mask(seq_len).to(x.device)
# 逐层解码
for layer in self.decoder_layers:
x = layer(x, mask)
# 输出 vocab_size 维度的 logits
logits = self.fc(x)
return logits
# 初始化一个小型 Decoder-only LLM
vocab_size = 10000
d_model = 512
num_heads = 8
num_layers = 6
d_ff = 2048
model = DecoderOnlyLLM(vocab_size, d_model, num_heads, num_layers, d_ff)
print(model)
💡 大语言模型的训练分为两个核心阶段:预训练和微调。预训练让模型学习通用语言知识,微调让模型适配特定任务或场景。
预训练的目标是让模型学习语言的概率分布,即给定前文,预测下一个 token 的概率。
⚠️ 注意:预训练需要海量的算力资源,通常由大厂或研究机构完成。普通开发者无需重复预训练,直接使用开源预训练模型即可。
微调是大语言模型落地的关键步骤,分为以下几种类型:
💡 全参数微调大语言模型需要巨大的算力,**LoRA(Low-Rank Adaptation)**是一种高效微调方法。它通过在注意力层插入低秩矩阵,仅训练少量参数,即可实现与全参数微调相当的效果。
# 安装必要依赖
pip install transformers datasets peft accelerate torch bitsandbytes
本次实战使用Alpaca 中文指令数据集,包含 5 万条中文指令 - 响应对,用于微调 LLaMA-2-7B 模型。
from datasets import load_dataset
from transformers import AutoTokenizer
# 加载中文 Alpaca 数据集
dataset = load_dataset("silk-road/alpaca-data-gpt4-chinese")
# 加载 LLaMA-2 分词器
tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-2-7b-hf", use_fast=False)
tokenizer.pad_token = tokenizer.eos_token # 设置 pad_token 为 eos_token
# 定义数据格式化函数
def format_prompt(sample):
instruction = sample["instruction"]
input_text = sample["input"]
output_text = sample["output"]
if input_text:
prompt = f"### 指令:\n{instruction}\n### 输入:\n{input_text}\n### 输出:\n{output_text}"
else:
prompt = f"### 指令:\n{instruction}\n### 输出:\n{output_text}"
return {"prompt": prompt}
# 格式化数据集
dataset = dataset.map(format_prompt)
# 定义分词函数
def tokenize_function(sample):
tokenized = tokenizer(
sample["prompt"],
max_length=512,
truncation=True,
padding="max_length",
return_tensors="pt"
)
# 设置 labels,与 input_ids 相同(自回归训练)
tokenized["labels"] = tokenized["input_ids"].clone()
return tokenized
# 分词处理
tokenized_dataset = dataset.(tokenize_function, batched=)
tokenized_dataset = tokenized_dataset[].train_test_split(test_size=)
from transformers import AutoModelForCausalLM, TrainingArguments, Trainer
from peft import LoraConfig, get_peft_model, TaskType
# 配置 LoRA 参数
lora_config = LoraConfig(
task_type=TaskType.CAUSAL_LM,
r=8, # 低秩矩阵的秩
lora_alpha=32, # 缩放系数
lora_dropout=0.1, # dropout 概率
target_modules=["q_proj", "v_proj"], # 仅微调注意力层的 q 和 v 投影矩阵
bias="none",
inference_mode=False
)
# 加载 LLaMA-2-7B 模型,使用 4bit 量化降低显存占用
model = AutoModelForCausalLM.from_pretrained(
"meta-llama/Llama-2-7b-hf",
load_in_4bit=True,
device_map="auto",
torch_dtype=torch.float16
)
# 为模型添加 LoRA 适配器
model = get_peft_model(model, lora_config)
# 查看可训练参数数量
model.print_trainable_parameters()
# 输出类似:trainable params: 约 400 万 || all params: 约 70 亿 || trainable%: 0.06
# 配置训练参数
training_args = TrainingArguments(
output_dir="./llama-2-7b-lora-chinese",
per_device_train_batch_size=4,
per_device_eval_batch_size=4,
gradient_accumulation_steps=4,
learning_rate=2e-4,
num_train_epochs=3,
logging_steps=10,
evaluation_strategy="epoch",
save_strategy="epoch",
fp16=True,
remove_unused_columns=False,
report_to="none"
)
# 初始化 Trainer
trainer = Trainer(
model=model,
args=training_args,
train_dataset=tokenized_dataset["train"],
eval_dataset=tokenized_dataset["test"],
tokenizer=tokenizer
)
# 启动训练
trainer.train()
# 保存 LoRA 适配器
model.save_pretrained("./llama-2-7b-lora-chinese-adapter")
from peft import PeftModel
# 加载基座模型
base_model = AutoModelForCausalLM.from_pretrained(
"meta-llama/Llama-2-7b-hf",
load_in_4bit=True,
device_map="auto",
torch_dtype=torch.float16
)
# 加载 LoRA 适配器
peft_model = PeftModel.from_pretrained(base_model, "./llama-2-7b-lora-chinese-adapter")
# 定义推理函数
def generate_response(instruction, input_text=""):
if input_text:
prompt = f"### 指令:\n{instruction}\n### 输入:\n{input_text}\n### 输出:\n"
else:
prompt = f"### 指令:\n{instruction}\n### 输出:\n"
inputs = tokenizer(prompt, return_tensors="pt").to("cuda")
# 生成回答
outputs = peft_model.generate(**inputs, max_new_tokens=200, temperature=0.7, top_p=0.9, do_sample=True, repetition_penalty=1.1)
# 解码输出
response = tokenizer.decode(outputs[0], skip_special_tokens=True)
# 提取输出部分
output = response.split("### 输出:\n")[1]
return output
# 测试推理
instruction = "解释一下什么是大语言模型"
response = generate_response(instruction)
print(f"指令:{instruction}")
print(f"回答:{response}")
💡 技巧 1:模型量化。使用 INT4/INT8 量化,降低模型显存占用,提升推理速度。 💡 技巧 2:模型蒸馏。将大模型的知识蒸馏到小模型中,在保证性能的前提下,显著提升推理效率。 💡 技巧 3:推理框架优化。使用 vLLM、TensorRT-LLM 等高性能推理框架,通过 PagedAttention 等技术,提升吞吐量和响应速度。
✅ 大语言模型基于 Transformer decoder-only 架构,通过海量文本预训练和指令微调,具备强大的自然语言理解与生成能力。 ✅ LoRA 是一种高效微调方法,通过训练少量低秩参数,即可实现大语言模型的定制化适配,大幅降低算力需求。 ✅ 大语言模型的部署需要结合量化、蒸馏、高性能推理框架等技术,平衡性能与资源消耗。 ✅ 大语言模型的发展方向是多模态、高效率、高安全性,未来将在更多行业场景中落地应用。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online