Skip to content

2.1 LLM 基本原理

大语言模型(LLM)是基于 Transformer 架构、在海量文本上预训练的超大规模神经网络。理解其底层原理,能帮助你写出更好的 Prompt、更高效地微调模型、在应用开发中做出正确的架构决策。


一、LLM 概述

1. 什么是大语言模型

定义:Large Language Model(LLM)是通过海量文本数据预训练的 Transformer 神经网络,参数量从数十亿到数千亿,能够理解和生成自然语言。

核心能力

能力说明示例
语言理解阅读理解、情感分析、实体识别"这段话表达的是正面还是负面情绪?"
语言生成续写、创作、翻译、摘要"帮我写一段产品介绍"
推理能力逻辑推理、数学计算、代码生成"这个 bug 的原因是什么?"
上下文学习Few-shot Learning,无需微调适应新任务给几个例子就能模仿格式
通用性一个模型处理多种任务同时能写代码、翻译、问答

2. 本质:预测下一个 Token

LLM 的核心任务是:给定前文,预测下一个 Token 的概率分布

$$P(w_t \mid w_1, w_2, ..., w_{t-1})$$

这种机制叫做**自回归(Auto-Regressive)**生成——每次产出一个 Token,然后将其加入输入继续生成,直到结束。

输入: "今天天气"
                           ↓ 预测
Step 1: "今天天气" → "很"
Step 2: "今天天气很" → "好"
Step 3: "今天天气很好" → "。"
Step 4: "今天天气很好。" → [END]

关键洞察

  • LLM 是概率生成器,不是知识数据库——它生成的是"最可能的下一个词",不保证事实正确
  • 自回归意味着模型无法回溯修改已生成的内容,所以 Chain of Thought(让模型先推理再回答)非常有效
  • 训练目标(预测下一个词)看似简单,但当模型规模足够大、数据足够多时,会涌现出推理、翻译、编程等复杂能力

3. 发展历程

2017  Transformer 架构提出(Attention is All You Need)

2018  BERT(双向编码)+ GPT-1(自回归生成)

2019  GPT-2(1.5B 参数)—— 文本生成引起关注

2020  GPT-3(175B 参数)—— 展现涌现能力(Emergent Abilities)

2022  ChatGPT 发布 —— 引爆大模型应用热潮

2023  GPT-4 + 开源爆发(LLaMA、Qwen、Mistral)+ 多模态融合

2024  Claude 3.5 + GPT-4o + 开源追赶(LLaMA 3、Qwen2、DeepSeek-V2)

2025  推理模型兴起(o1、DeepSeek-R1)—— 强化推理成为新范式

二、Transformer 在 LLM 中的应用

Transformer 基础已在 1.3 节介绍,本节聚焦于 LLM 中的架构选择和关键改进。

1. 三种架构范式

Decoder-Only(GPT 系列)—— 当前主流

只使用 Transformer 的 Decoder 部分,自回归生成(从左到右预测下一个 Token)。

输入: [Token1, Token2, Token3, ...]
  ↓ Masked Self-Attention(每个位置只能看到自己和之前的位置)
  ↓ × N 层
输出: 预测每个位置的下一个 Token 概率
  • 训练目标:语言建模(预测下一个词)
  • 优势:生成能力强,适合对话、创作、代码
  • 代表:GPT-3/4、LLaMA、Qwen、DeepSeek、Mistral、Claude
python
# GPT 风格的 Decoder-Only 架构(简化版)
class GPTBlock(nn.Module):
    def __init__(self, d_model, num_heads, d_ff, dropout=0.1):
        super().__init__()
        self.ln1 = nn.LayerNorm(d_model)       # Pre-Norm(LLaMA 风格)
        self.attn = MultiHeadAttention(d_model, num_heads)
        self.ln2 = nn.LayerNorm(d_model)
        self.ffn = nn.Sequential(
            nn.Linear(d_model, d_ff),
            nn.GELU(),
            nn.Linear(d_ff, d_model),
        )
        self.dropout = nn.Dropout(dropout)

    def forward(self, x, mask):
        # Pre-Norm + Masked Self-Attention + 残差
        h = self.ln1(x)
        x = x + self.dropout(self.attn(h, h, h, mask))

        # Pre-Norm + FFN + 残差
        h = self.ln2(x)
        x = x + self.dropout(self.ffn(h))
        return x

Encoder-Only(BERT 系列)

只使用 Encoder 部分,双向编码(同时看到前后文)。

  • 训练目标:Masked Language Model(随机遮掩 15% 的 Token 让模型预测)
  • 优势:理解能力强,适合分类、NER、问答
  • 代表:BERT、RoBERTa、DeBERTa
  • 局限:不擅长生成任务

Encoder-Decoder(T5 系列)

完整 Transformer 架构,Encoder 理解输入,Decoder 生成输出。

  • 训练目标:序列到序列(Seq2Seq)
  • 优势:适合翻译、摘要等"输入→输出"转换任务
  • 代表:T5、BART、mT5

架构选择指南

生成式应用(对话/创作/代码)  → Decoder-Only(GPT 系列)  ← 当前主流
分类/抽取任务               → Encoder-Only(BERT 系列)
翻译/摘要                  → Encoder-Decoder(T5 系列)

2. LLM 中的关键改进

现代大模型在原始 Transformer 基础上做了很多工程优化:

位置编码优化

方法说明使用模型
绝对位置编码原始 Transformer 三角函数编码GPT-2
可学习位置编码位置 Embedding 作为参数学习BERT、GPT-3
RoPE(旋转位置编码)在注意力计算中注入相对位置,支持长上下文外推LLaMA、Qwen、Mistral
ALiBi通过注意力偏置实现位置编码MPT、BLOOM
python
# RoPE 旋转位置编码(核心思想)
def apply_rotary_pos_emb(q, k, cos, sin):
    """对 Q 和 K 应用旋转位置编码"""
    # 将 q, k 拆分为实部和虚部
    q_real, q_imag = q[..., ::2], q[..., 1::2]
    k_real, k_imag = k[..., ::2], k[..., 1::2]

    # 旋转变换
    q_out_real = q_real * cos - q_imag * sin
    q_out_imag = q_real * sin + q_imag * cos
    k_out_real = k_real * cos - k_imag * sin
    k_out_imag = k_real * sin + k_imag * cos

    # 交织合并
    q_out = torch.stack([q_out_real, q_out_imag], dim=-1).flatten(-2)
    k_out = torch.stack([k_out_real, k_out_imag], dim=-1).flatten(-2)
    return q_out, k_out

注意力机制优化

方法说明效果
MHA(Multi-Head Attention)原始多头注意力,每个头有独立的 K、V标准实现
MQA(Multi-Query Attention)所有头共享一组 K 和 V推理加速 2-5x,KV Cache 减少
GQA(Grouped-Query Attention)头分组,每组共享 K、VMHA 和 MQA 的折中,LLaMA 2/3 使用
Flash Attention利用 GPU 内存层级优化注意力计算速度提升 2-4x,显存减少
python
# GQA:Grouped-Query Attention 示意
# 假设 num_heads=32, num_kv_heads=8
# 每 4 个 Q head 共享 1 个 KV head

class GroupedQueryAttention(nn.Module):
    def __init__(self, d_model, num_heads, num_kv_heads):
        super().__init__()
        self.num_heads = num_heads           # Q 的头数:32
        self.num_kv_heads = num_kv_heads     # KV 的头数:8
        self.head_dim = d_model // num_heads

        self.q_proj = nn.Linear(d_model, num_heads * self.head_dim)
        self.k_proj = nn.Linear(d_model, num_kv_heads * self.head_dim)
        self.v_proj = nn.Linear(d_model, num_kv_heads * self.head_dim)
        self.o_proj = nn.Linear(d_model, d_model)

其他改进

改进原始 Transformer现代 LLM
激活函数ReLUSwiGLU(LLaMA)、GELU(GPT)
归一化位置Post-Norm(层后)Pre-Norm(层前)—— 训练更稳定
归一化方法LayerNormRMSNorm(LLaMA)—— 更快
FFN 结构2 层全连接3 层 + 门控(SwiGLU)

三、Tokenization 与向量化

1. 为什么需要 Tokenization

神经网络只能处理数字,Tokenization 是文本与数字之间的桥梁:

"Hello, world!" → Tokenizer → [15496, 11, 995, 0] → Embedding → 向量矩阵

2. Token 的概念

  • Token:文本的基本处理单位(可以是字、词、子词、甚至字节)
  • Vocabulary(词表):所有可能 Token 的集合(通常 32K-150K 个)
  • Token ID:Token 在词表中的索引编号

3. 主流 Tokenization 方法

字符级(Character-level)

每个字符是一个 Token。词表小(几百),但序列过长、难以捕捉语义。

词级(Word-level)

每个词是一个 Token。语义清晰,但词表巨大且无法处理未登录词(OOV)。

子词级(Subword-level)—— 主流方法

在字符和词之间取平衡,高频词保持完整,低频词拆分为子词片段。

BPE(Byte Pair Encoding)

GPT 系列使用。算法从字符开始,迭代合并最频繁的字符对:

初始:  l o w e r     → 词表: {l, o, w, e, r}
合并1: lo w e r      → 词表加入: {lo}
合并2: low e r       → 词表加入: {low}
合并3: lowe r        → 词表加入: {lowe}
合并4: lower         → 词表加入: {lower}

WordPiece — BERT 使用,用 ## 标记子词:playing → play + ##ing

SentencePiece — Google 开源,LLaMA、Qwen 使用,与语言无关,直接处理 Unicode

4. Tokenization 实践

python
from transformers import AutoTokenizer

# --- 对比不同 Tokenizer ---

# GPT-2 Tokenizer(BPE)
gpt2_tok = AutoTokenizer.from_pretrained("gpt2")
text = "Hello, world! 你好世界"

tokens = gpt2_tok.tokenize(text)
print(f"GPT-2 Tokens: {tokens}")
# ['Hello', ',', 'Ġworld', '!', 'Ġ', 'ä½', 'ł', 'å¥', '½', 'ä', '¸', 'ĸ', 'ç', 'ķ', 'Į']

ids = gpt2_tok.encode(text)
print(f"GPT-2 Token IDs: {ids}")
print(f"GPT-2 Token 数量: {len(ids)}")  # 中文分得很碎

# 使用 tiktoken(OpenAI 官方 Tokenizer)
import tiktoken

enc = tiktoken.encoding_for_model("gpt-4")
tokens = enc.encode("Hello, world! 你好世界")
print(f"GPT-4 Token 数量: {len(tokens)}")

# 中英文 Token 效率对比
texts = {
    "英文": "The quick brown fox jumps over the lazy dog",
    "中文": "敏捷的棕色狐狸跳过了那只懒狗",
}
for lang, text in texts.items():
    n = len(enc.encode(text))
    print(f"{lang}: {len(text)} 字符 → {n} tokens(比率: {n/len(text):.2f})")

5. 特殊 Token

不同模型使用不同的特殊 Token 来标记结构信息:

Token用途使用模型
[CLS] [SEP]分类标记、句子分隔BERT
<s> </s>序列开始、结束LLaMA
<|endoftext|>文档结束GPT-2
<|im_start|> <|im_end|>指令开始、结束ChatML 格式

6. Token Embedding(词嵌入)

将离散的 Token ID 映射为连续的高维向量:

python
import torch.nn as nn

# Token ID → 向量
vocab_size = 32000   # 词表大小
d_model = 4096       # 嵌入维度

embedding = nn.Embedding(vocab_size, d_model)

token_ids = torch.tensor([15496, 11, 995, 0])  # "Hello, world!"
vectors = embedding(token_ids)
print(f"输入: {token_ids.shape}")     # (4,)
print(f"输出: {vectors.shape}")       # (4, 4096)

# 最终输入 = Token Embedding + Position Encoding

7. Tokenization 对开发的影响

上下文长度限制

  • 模型上下文窗口以 Token 计数(如 4K、128K、200K)
  • 中文 1 字 ≈ 2-3 tokens(GPT)或 ≈ 1 token(Qwen 等国产模型)
  • 英文 1 词 ≈ 1-1.5 tokens

API 成本计算

python
import tiktoken

def estimate_cost(text, model="gpt-4", input_price_per_1m=30):
    """估算 API 调用成本"""
    enc = tiktoken.encoding_for_model(model)
    num_tokens = len(enc.encode(text))
    cost = num_tokens / 1_000_000 * input_price_per_1m
    return num_tokens, cost

text = open("document.txt").read()
tokens, cost = estimate_cost(text)
print(f"Token 数: {tokens}, 预估输入成本: ${cost:.4f}")

模型选择考量

  • 中文应用优先选择中文优化模型(Qwen、DeepSeek),Token 效率更高,成本更低
  • 多语言场景选择多语言 Tokenizer 的模型

四、预训练与微调范式

1. 预训练(Pre-training)—— "通识教育"

在海量无标注文本上训练模型,学习语言的通用表示和世界知识。

预训练数据

  • 规模:数万亿 tokens(LLaMA 2: 2T tokens,LLaMA 3: 15T tokens)
  • 来源:网页(Common Crawl)、书籍、代码(GitHub)、论文、Wikipedia、对话
  • 质量控制:去重、过滤低质内容、有害内容过滤、多样性平衡
  • 成本:数百万到数千万美元级别

预训练任务

自回归语言建模(Causal LM)— GPT 系列

给定前文,预测下一个 Token:

输入:  "The cat sat on the"
标签:          "cat sat on the mat"
损失: CrossEntropy(预测分布, 真实Token)
python
# 自回归训练的核心逻辑
def causal_lm_loss(model, input_ids):
    # input_ids: [BOS, w1, w2, w3, w4]
    # 标签右移:  [w1, w2, w3, w4, EOS]
    logits = model(input_ids[:, :-1])      # 输入: [BOS, w1, w2, w3]
    labels = input_ids[:, 1:]              # 标签: [w1, w2, w3, w4]
    loss = F.cross_entropy(logits.view(-1, vocab_size), labels.view(-1))
    return loss

掩码语言建模(Masked LM)— BERT 系列

随机遮掩 15% 的 Token,让模型预测被遮掩的内容:

输入:  "The [MASK] sat on the [MASK]"
标签:        "cat"              "mat"

预训练产出:Base Model(基座模型)

  • 知识渊博,但不懂遵循指令
  • 你问它 "如何写代码",它可能续写为 "如何写代码的教程第一章..."

普通开发者无需从头预训练,直接使用开源模型或调用 API。

2. 微调(Fine-tuning)—— "职业培训"

将通用基座模型适配为特定任务或领域的专家。

指令微调(Instruction Tuning / SFT)

让模型学会遵循人类指令,从"续写机器"变为"助手"。

训练数据格式:
{
  "instruction": "请将以下句子翻译成英文",
  "input": "今天天气很好",
  "output": "The weather is nice today."
}
python
# 指令微调的数据构造
def format_instruction(example):
    """构造 ChatML 格式的训练数据"""
    return f"""<|im_start|>system
你是一个有帮助的助手。<|im_end|>
<|im_start|>user
{example['instruction']}
{example.get('input', '')}<|im_end|>
<|im_start|>assistant
{example['output']}<|im_end|>"""

典型数据集:Alpaca(52K)、ShareGPT、UltraChat

RLHF(人类反馈强化学习)

让模型更符合人类偏好(有用、诚实、无害)。

Step 1: 收集偏好数据
  用户提问 → 模型生成多个回复 → 人类标注哪个更好
  回复 A: ★★★★☆  (更好)
  回复 B: ★★☆☆☆

Step 2: 训练奖励模型(Reward Model)
  学习人类偏好,给回复打分

Step 3: 强化学习优化(PPO 算法)
  用奖励模型的反馈优化语言模型

代表:ChatGPT、Claude

DPO(直接偏好优化)

RLHF 的简化版本,直接从偏好数据学习,无需单独训练奖励模型。更简单、更稳定,是最新趋势。

python
# DPO 的核心思想(简化)
# 直接优化:让模型更倾向于生成"好回复",远离"坏回复"
def dpo_loss(model, ref_model, chosen, rejected, beta=0.1):
    """
    chosen:   人类偏好的回复
    rejected: 人类不偏好的回复
    ref_model: 参考模型(冻结的 SFT 模型)
    """
    # 计算当前模型和参考模型的对数概率
    log_prob_chosen = model.log_prob(chosen)
    log_prob_rejected = model.log_prob(rejected)
    ref_log_prob_chosen = ref_model.log_prob(chosen)
    ref_log_prob_rejected = ref_model.log_prob(rejected)

    # DPO 损失
    logits = beta * ((log_prob_chosen - ref_log_prob_chosen) -
                     (log_prob_rejected - ref_log_prob_rejected))
    loss = -F.logsigmoid(logits).mean()
    return loss

3. 参数高效微调(PEFT)

全量微调更新所有参数,显存需求大。PEFT 只训练少量参数,效果接近全量微调。

LoRA(Low-Rank Adaptation)—— AI 应用开发首选

核心思想:冻结原始权重 W,添加低秩分解矩阵 A·B。

$$W' = W + \Delta W = W + A \cdot B$$

其中 A 的形状是 (d, r),B 的形状是 (r, d),r << d(通常 r=8, 16, 32, 64)。

python
import torch.nn as nn

class LoRALinear(nn.Module):
    """LoRA 改造的线性层"""

    def __init__(self, original_linear, rank=16, alpha=32):
        super().__init__()
        self.original = original_linear
        self.original.weight.requires_grad = False  # 冻结原始权重

        d_out, d_in = original_linear.weight.shape
        self.lora_A = nn.Parameter(torch.randn(d_out, rank) * 0.01)
        self.lora_B = nn.Parameter(torch.zeros(rank, d_in))
        self.scaling = alpha / rank

    def forward(self, x):
        # 原始输出 + LoRA 增量
        original_output = self.original(x)
        lora_output = (x @ self.lora_B.T @ self.lora_A.T) * self.scaling
        return original_output + lora_output

# LoRA 的优势:
# - 仅训练 1-2% 的参数
# - 显存占用大幅降低
# - 训练速度快
# - 可插拔:LoRA 权重可保存为独立文件,方便切换不同任务

QLoRA

LoRA + 4-bit 量化,进一步降低显存需求。消费级 GPU(如 RTX 4090 24GB)可微调 70B 参数模型。

python
# 使用 bitsandbytes + peft 进行 QLoRA 微调
from transformers import AutoModelForCausalLM, BitsAndBytesConfig
from peft import LoraConfig, get_peft_model

# 4-bit 量化配置
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_quant_type="nf4",           # NormalFloat4 量化
    bnb_4bit_compute_dtype=torch.float16,
    bnb_4bit_use_double_quant=True,      # 双重量化
)

# 加载量化模型
model = AutoModelForCausalLM.from_pretrained(
    "meta-llama/Llama-2-7b-hf",
    quantization_config=bnb_config,
    device_map="auto",
)

# LoRA 配置
lora_config = LoraConfig(
    r=16,                    # 秩
    lora_alpha=32,           # 缩放系数
    target_modules=["q_proj", "k_proj", "v_proj", "o_proj"],  # 应用 LoRA 的层
    lora_dropout=0.05,
    task_type="CAUSAL_LM",
)

# 应用 LoRA
model = get_peft_model(model, lora_config)
model.print_trainable_parameters()
# trainable params: 4,194,304 || all params: 3,504,607,232 || trainable%: 0.12%

其他 PEFT 方法

方法原理特点
Prefix Tuning在每层输入前添加可学习前缀向量不改模型结构
Adapter在 Transformer 层间插入小型全连接模块灵活,可组合
P-Tuning v2优化每层的输入 Embedding效果好,但实现复杂

微调最佳实践

python
# 微调超参数参考
training_config = {
    "learning_rate": 2e-5,       # 小学习率(1e-5 到 5e-5)
    "warmup_ratio": 0.03,        # 预热比例
    "num_epochs": 3,             # 通常 1-5 个 epoch
    "batch_size": 4,             # 受显存限制
    "gradient_accumulation": 8,  # 梯度累积模拟大 batch
    "max_seq_length": 2048,      # 最大序列长度
    "weight_decay": 0.01,        # 权重衰减
    "lora_rank": 16,             # LoRA 秩
    "lora_alpha": 32,            # LoRA 缩放
}

# 关键原则:
# 1. 数据质量 > 数据数量(1000 条高质量数据 > 10000 条低质量数据)
# 2. 监控验证集 loss,防止过拟合
# 3. 多样化训练数据,避免模型能力退化
# 4. 从小模型开始实验,验证后再上大模型

五、上下文窗口

1. 定义

上下文窗口(Context Window)是模型一次能处理的最大 Token 数量,包括输入和输出

2. 主流模型上下文长度

模型上下文备注
GPT-3.5 Turbo16K性价比高
GPT-4 Turbo / GPT-4o128K长文档分析
Claude 3.5 Sonnet200K可处理整本书
Gemini 1.5 Pro1M+超长上下文
LLaMA 24K基础版
LLaMA 38K-128K不同版本
Qwen 232K-128K中文优化
DeepSeek V2128K开源长上下文

3. "Lost in the Middle" 问题

虽然窗口越来越大,但模型并非均匀关注所有位置:

关注度高 ████████░░░░░░░░░░░░░░░░░░░░░░░░████████ 关注度高
         开头         中间(容易被忽略)          结尾

开发启示:在 RAG 或长文档分析中,关键信息尽量放在 Prompt 的开头或结尾

4. 长上下文技术

技术方法说明
位置插值压缩位置索引到原始范围扩展已有模型的上下文
NTK-Aware Scaling改进位置插值更好的长文本外推
YaRN自适应位置缩放最新方法
Sliding Window Attention每个位置只关注附近窗口Mistral 使用
Flash Attention 2高效 GPU 实现速度和显存均优化
RAG不增大窗口,检索外部知识最实用方案(第四章详解)

六、推理机制

1. 自回归生成流程

输入: "What is AI?"
                    ↓ Tokenize
Token IDs: [2, 1724, 374, 15592, 30]
                    ↓ Embedding + Position
向量矩阵: (5, d_model)
                    ↓ Transformer × N 层
输出 Logits: (5, vocab_size)
                    ↓ 取最后位置的 Logits
下一个 Token 概率分布: (vocab_size,)
                    ↓ 采样策略
生成 Token: "AI"
                    ↓ 添加到输入,重复
...直到生成结束符或达到 max_tokens

2. 采样策略

Temperature(温度)

温度控制概率分布的"锐度"。原始 logits 经过 $\text{softmax}(z_i / T)$ 变换:

              Token 概率分布
              "好"   "不错"  "棒"   "差"   其他
Temperature=0.1  95%    3%    1.9%   0.1%   ...    (几乎确定选"好")
Temperature=0.7  50%   25%   20%     3%    ...    (有一定随机性)
Temperature=1.5  25%   22%   20%    15%    ...    (很随机)
python
# Temperature 的作用
import torch
import torch.nn.functional as F

logits = torch.tensor([5.0, 3.0, 2.0, 0.5, -1.0])

for temp in [0.1, 0.5, 1.0, 1.5]:
    probs = F.softmax(logits / temp, dim=-1)
    print(f"T={temp:.1f}: {probs.numpy().round(3)}")

# T=0.1: [1.    0.    0.    0.    0.   ]  → 确定性
# T=0.5: [0.878 0.108 0.013 0.001 0.   ]
# T=1.0: [0.583 0.158 0.058 0.013 0.003]  → 默认
# T=1.5: [0.425 0.173 0.095 0.036 0.014]  → 随机性

使用建议

  • T = 0 ~ 0.3:代码生成、数学计算、事实问答(确定性高)
  • T = 0.5 ~ 0.8:通用对话、文档摘要(平衡)
  • T = 0.8 ~ 1.2:创意写作、头脑风暴(多样性高)

Top-k 采样

只从概率最高的 k 个 Token 中采样,过滤低概率选项:

python
def top_k_sampling(logits, k=50):
    values, indices = logits.topk(k)
    probs = F.softmax(values, dim=-1)
    sampled_index = torch.multinomial(probs, 1)
    return indices[sampled_index]

Top-p 采样(Nucleus Sampling)—— 最常用

选择累积概率达到 p 的最小 Token 集合,动态调整候选集大小:

python
def top_p_sampling(logits, p=0.9):
    sorted_logits, sorted_indices = torch.sort(logits, descending=True)
    probs = F.softmax(sorted_logits, dim=-1)
    cumsum = torch.cumsum(probs, dim=-1)

    # 移除累积概率超过 p 的 Token
    mask = cumsum - probs > p
    sorted_logits[mask] = float('-inf')

    probs = F.softmax(sorted_logits, dim=-1)
    sampled_index = torch.multinomial(probs, 1)
    return sorted_indices[sampled_index]

保留多个候选序列,选择总体概率最高的。适合翻译/摘要,对话较少使用(容易平淡)。

3. 推理优化

KV Cache

自回归生成时,每生成一个新 Token 都需要对所有已有 Token 做注意力计算。KV Cache 缓存已计算的 Key 和 Value,避免重复计算。

python
# 无 KV Cache:生成第 N 个 token 需要重新计算前 N-1 个 token 的 K、V
# 有 KV Cache:只计算新 token 的 K、V,拼接到缓存中

# 效果:生成速度提升数十倍
# 代价:显存占用随序列长度线性增长

量化(Quantization)

降低权重精度,减少显存、加速推理:

精度每参数占用7B 模型显存精度损失
FP324 bytes28 GB
FP162 bytes14 GB极小
INT81 byte7 GB
INT40.5 bytes3.5 GB可接受

工具:GPTQ、AWQ(GPU)、GGUF(CPU,llama.cpp 格式)

推理参数控制

python
from transformers import AutoModelForCausalLM, AutoTokenizer

model = AutoModelForCausalLM.from_pretrained("meta-llama/Llama-2-7b-chat-hf")
tokenizer = AutoTokenizer.from_pretrained("meta-llama/Llama-2-7b-chat-hf")

inputs = tokenizer("What is machine learning?", return_tensors="pt")

output = model.generate(
    **inputs,
    max_new_tokens=512,        # 最大生成长度
    temperature=0.7,           # 温度
    top_p=0.9,                 # Top-p 采样
    top_k=50,                  # Top-k 采样
    do_sample=True,            # 启用随机采样
    repetition_penalty=1.1,    # 重复惩罚(>1 减少重复)
    num_beams=1,               # Beam search(1=不使用)
)

result = tokenizer.decode(output[0], skip_special_tokens=True)
print(result)

七、幻觉(Hallucination)

LLM 本质是概率生成器,不是知识库,会一本正经地编造事实

产生原因

  • 预训练数据中不包含相关知识
  • 模型为了"接龙"顺畅,强行编造
  • 对低频知识的记忆不牢固

解决方案

方案方法效果
RAG检索外部知识作为上下文最有效(开卷考试)
Prompt 约束"如果不确定,请说不知道"简单有效
降低 Temperature减少随机性减少编造倾向
微调用高质量数据微调提升领域准确性
多模型验证用另一个模型检查事实成本高但可靠

八、实战练习

练习1:对比不同 Tokenizer

python
from transformers import AutoTokenizer

models = ["gpt2", "bert-base-uncased", "meta-llama/Llama-2-7b-hf"]
texts = [
    "Hello, how are you?",
    "你好,今天天气怎么样?",
    "def fibonacci(n): return n if n <= 1 else fibonacci(n-1) + fibonacci(n-2)",
]

for model_name in models:
    tokenizer = AutoTokenizer.from_pretrained(model_name)
    print(f"\n=== {model_name} ===")
    for text in texts:
        tokens = tokenizer.tokenize(text)
        ids = tokenizer.encode(text)
        print(f"  文本: {text[:40]}...")
        print(f"  Tokens ({len(tokens)}): {tokens[:8]}...")

练习2:调试生成参数

python
from transformers import AutoModelForCausalLM, AutoTokenizer

model_name = "gpt2"  # 本地可以跑的小模型
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name)

prompt = "The future of artificial intelligence is"
inputs = tokenizer(prompt, return_tensors="pt")

# 对比不同参数的输出
configs = [
    {"temperature": 0.1, "top_p": 1.0, "label": "低温度(确定性)"},
    {"temperature": 1.0, "top_p": 0.9, "label": "中等温度 + Top-p"},
    {"temperature": 1.5, "top_p": 1.0, "label": "高温度(随机)"},
]

for config in configs:
    output = model.generate(
        **inputs,
        max_new_tokens=50,
        temperature=config["temperature"],
        top_p=config["top_p"],
        do_sample=True,
    )
    text = tokenizer.decode(output[0], skip_special_tokens=True)
    print(f"\n--- {config['label']} ---")
    print(text)

练习3:LoRA 微调入门

python
# 使用 LLaMA-Factory 进行快速微调(推荐方式)
# 安装:pip install llmtuner

# 或使用 PEFT + Transformers 手动微调
from transformers import AutoModelForCausalLM, AutoTokenizer, TrainingArguments, Trainer
from peft import LoraConfig, get_peft_model
from datasets import load_dataset

# 1. 加载模型
model = AutoModelForCausalLM.from_pretrained("gpt2")
tokenizer = AutoTokenizer.from_pretrained("gpt2")
tokenizer.pad_token = tokenizer.eos_token

# 2. 应用 LoRA
lora_config = LoraConfig(
    r=8, lora_alpha=16,
    target_modules=["c_attn"],  # GPT-2 的注意力层
    lora_dropout=0.05,
    task_type="CAUSAL_LM",
)
model = get_peft_model(model, lora_config)
model.print_trainable_parameters()

# 3. 准备数据并训练
# ... (数据处理和 Trainer 配置)

九、学习资源

类型资源说明
论文Attention is All You NeedTransformer 原始论文
论文Language Models are Few-Shot Learners (GPT-3)大模型能力展示
论文LLaMA 系列论文开源模型代表
论文LoRA: Low-Rank AdaptationPEFT 核心方法
课程Stanford CS324 - LLM大模型系统课程
课程李沐《动手学大模型》中文讲解,实战导向
工具HuggingFace TransformersLLM 开发必备库
工具LLaMA-Factory微调工具集
工具tiktoken / tokenizersTokenizer 工具
文档OpenAI API 文档API 调用与参数说明

十、AI 应用开发要点

开发者无需从头预训练

直接使用开源模型(LLaMA、Qwen、Mistral、DeepSeek)或调用 API(OpenAI、Claude、Gemini)。

重点掌握

  1. 模型选择:根据任务、成本、部署环境选择合适模型
  2. Prompt 工程:高效利用模型能力(下一章详解)
  3. 微调技术:LoRA/QLoRA 适配特定领域
  4. 推理优化:参数调优、KV Cache、量化部署

常见应用场景决策

通用对话         → 直接调用 API(GPT-4、Claude)
领域专家         → 收集领域数据 + LoRA 微调开源模型
知识密集型任务   → RAG 检索增强(第四章)
复杂多步任务     → Agent 系统(第五章)
低成本部署       → 量化 + 小模型(7B/14B)

学习建议

  • 理解原理,但不要纠结数学细节
  • 重点实践:调用 API → 使用开源模型 → LoRA 微调
  • Transformer 和 Attention 是基础,必须理解
  • 关注开源社区最新进展:模型更新快,保持学习

坚持是一种品格