附录E:神经网络架构#
E.1 神经网络架构:GPT、Llama、MoE及其演进#
在构建故事讲述AI大语言模型的过程中,理解不同的神经网络架构及其演进历程至关重要。本节将深入探讨几种主流的大型语言模型架构,包括GPT系列(1、2、3、4)、Llama系列及其创新组件(RoPE、RMSNorm、GQA),以及混合专家模型(MoE)。我们将分析这些架构的设计理念、核心创新和技术演进,以及它们在故事讲述AI系统中的应用。
Transformer架构基础#
在深入特定模型之前,我们需要回顾Transformer架构的基础,因为它是现代大型语言模型的基石。2017年,Vaswani等人在论文《Attention is All You Need》中提出了Transformer架构,彻底改变了自然语言处理领域。
Transformer的核心组件#
自注意力机制(Self-Attention): 允许模型在处理序列时考虑所有位置的信息,而不仅仅是相邻位置。
import torch import torch.nn as nn import torch.nn.functional as F import math class SelfAttention(nn.Module): def __init__(self, embed_dim, num_heads): super().__init__() self.embed_dim = embed_dim self.num_heads = num_heads self.head_dim = embed_dim // num_heads self.query = nn.Linear(embed_dim, embed_dim) self.key = nn.Linear(embed_dim, embed_dim) self.value = nn.Linear(embed_dim, embed_dim) self.out_proj = nn.Linear(embed_dim, embed_dim) def forward(self, x, mask=None): batch_size, seq_len, _ = x.size() # 线性投影 q = self.query(x).view(batch_size, seq_len, self.num_heads, self.head_dim).transpose(1, 2) k = self.key(x).view(batch_size, seq_len, self.num_heads, self.head_dim).transpose(1, 2) v = self.value(x).view(batch_size, seq_len, self.num_heads, self.head_dim).transpose(1, 2) # 计算注意力分数 scores = torch.matmul(q, k.transpose(-1, -2)) / math.sqrt(self.head_dim) # 应用掩码(如果提供) if mask is not None: scores = scores.masked_fill(mask == 0, -1e9) # 注意力权重 attn_weights = F.softmax(scores, dim=-1) # 应用注意力权重 context = torch.matmul(attn_weights, v) # 重塑和投影 context = context.transpose(1, 2).contiguous().view(batch_size, seq_len, self.embed_dim) output = self.out_proj(context) return output
多头注意力(Multi-Head Attention): 允许模型同时关注不同位置的不同表示子空间,增强模型的表达能力。
位置编码(Positional Encoding): 由于自注意力机制本身不包含位置信息,位置编码被添加到输入嵌入中,以提供序列中的位置信息。
def get_positional_encoding(seq_len, d_model): pe = torch.zeros(seq_len, d_model) position = torch.arange(0, seq_len, dtype=torch.float).unsqueeze(1) div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model)) pe[:, 0::2] = torch.sin(position * div_term) pe[:, 1::2] = torch.cos(position * div_term) return pe.unsqueeze(0) # [1, seq_len, d_model]
前馈神经网络(Feed-Forward Network): 每个Transformer层包含一个由两个线性变换和一个非线性激活函数组成的前馈网络。
class FeedForward(nn.Module): def __init__(self, d_model, d_ff, dropout=0.1): super().__init__() self.linear1 = nn.Linear(d_model, d_ff) self.linear2 = nn.Linear(d_ff, d_model) self.dropout = nn.Dropout(dropout) def forward(self, x): return self.linear2(self.dropout(F.relu(self.linear1(x))))
层归一化(Layer Normalization): 用于稳定深层网络的训练,通过归一化每一层的输入来减少内部协变量偏移。
class LayerNorm(nn.Module): def __init__(self, features, eps=1e-6): super().__init__() self.gamma = nn.Parameter(torch.ones(features)) self.beta = nn.Parameter(torch.zeros(features)) self.eps = eps def forward(self, x): mean = x.mean(-1, keepdim=True) std = x.std(-1, keepdim=True) return self.gamma * (x - mean) / (std + self.eps) + self.beta
残差连接(Residual Connections): 每个子层的输出是其输入与子层函数应用于输入的结果之和,有助于训练非常深的网络。
Transformer的编码器-解码器结构#
原始Transformer架构包含编码器和解码器两部分:
编码器(Encoder):
由多个相同的层堆叠而成
每层包含多头自注意力机制和前馈神经网络
处理输入序列并生成上下文表示
解码器(Decoder):
同样由多个相同的层堆叠而成
每层包含多头自注意力、编码器-解码器注意力和前馈神经网络
生成输出序列,一次一个标记
现代大型语言模型通常只使用Transformer的一部分:
GPT系列使用仅解码器架构(只有自回归解码器部分)
BERT使用仅编码器架构(只有双向编码器部分)
T5使用完整的编码器-解码器架构
GPT系列:从GPT-1到GPT-4#
GPT(Generative Pre-trained Transformer)系列由OpenAI开发,代表了自回归语言模型的一个重要发展线路。
GPT-1:奠定基础#
GPT-1于2018年发布,是第一个展示大规模预训练加微调范式有效性的模型之一。
核心特点:
使用Transformer解码器架构
1.17亿参数
在大规模文本语料库上进行无监督预训练
通过微调适应下游任务
创新点:
证明了预训练+微调范式的有效性
展示了Transformer在生成任务中的潜力
引入了”零样本”和”少样本”学习的概念
# GPT-1风格的简化模型结构
class GPT1(nn.Module):
def __init__(self, vocab_size, d_model, nhead, num_layers, d_ff, max_seq_len, dropout=0.1):
super().__init__()
self.token_embedding = nn.Embedding(vocab_size, d_model)
self.position_embedding = nn.Embedding(max_seq_len, d_model)
decoder_layer = nn.TransformerDecoderLayer(d_model, nhead, d_ff, dropout)
self.transformer = nn.TransformerDecoder(decoder_layer, num_layers)
self.output_layer = nn.Linear(d_model, vocab_size)
def forward(self, x):
# 创建位置索引
positions = torch.arange(0, x.size(1), device=x.device).unsqueeze(0)
# 嵌入和位置编码
token_emb = self.token_embedding(x)
pos_emb = self.position_embedding(positions)
x = token_emb + pos_emb
# 创建注意力掩码(确保只看到过去的标记)
mask = torch.triu(torch.ones(x.size(1), x.size(1)), diagonal=1).bool().to(x.device)
# 通过Transformer
x = self.transformer(x, None, tgt_mask=mask)
# 输出层
return self.output_layer(x)
GPT-2:扩大规模#
GPT-2于2019年发布,代表了”规模化”思想的早期实践,展示了增加模型大小和训练数据可以显著提高性能。
核心特点:
架构与GPT-1类似,但规模更大
最大版本有15亿参数(比GPT-1大约10倍)
在更大、更多样化的数据集上训练
引入了更长的上下文窗口
创新点:
证明了扩大模型规模可以带来性能提升
展示了零样本任务学习的强大能力
引入了更好的分词方法(Byte Pair Encoding)
改进的层归一化位置(移至每个子层的输入)
架构改进:
将层归一化移至每个子层的输入(Pre-LN)
在最后一个自注意力块后添加额外的层归一化
# GPT-2风格的层实现
class GPT2Block(nn.Module):
def __init__(self, d_model, nhead, d_ff, dropout=0.1):
super().__init__()
self.ln_1 = nn.LayerNorm(d_model)
self.attn = nn.MultiheadAttention(d_model, nhead, dropout=dropout)
self.ln_2 = nn.LayerNorm(d_model)
self.mlp = nn.Sequential(
nn.Linear(d_model, d_ff),
nn.GELU(),
nn.Linear(d_ff, d_model),
nn.Dropout(dropout)
)
def forward(self, x, mask=None):
# 自注意力块
attn_output, _ = self.attn(self.ln_1(x), self.ln_1(x), self.ln_1(x), attn_mask=mask)
x = x + attn_output
# MLP块
x = x + self.mlp(self.ln_2(x))
return x
GPT-3:大规模预训练#
GPT-3于2020年发布,代表了大规模语言模型的重大飞跃,展示了”涌现能力”(emergent abilities)的概念。
核心特点:
1750亿参数(比GPT-2大约100倍)
96层Transformer解码器
12288维的嵌入
96个注意力头
在45TB文本数据上训练
创新点:
展示了语言模型的涌现能力(如少样本学习)
证明了模型规模与性能之间的幂律关系
引入了”提示工程”(prompt engineering)的概念
展示了上下文学习(in-context learning)的能力
架构特点:
与GPT-2基本相同,但规模更大
使用交替的稀疏注意力模式以提高效率
改进的初始化和归一化策略
# GPT-3的稀疏注意力模式示例(简化版)
def sparse_attention_pattern(seq_len, pattern_type="local"):
mask = torch.zeros(seq_len, seq_len)
if pattern_type == "local":
# 局部注意力:每个标记只关注其前后窗口内的标记
window_size = 256
for i in range(seq_len):
start = max(0, i - window_size)
end = min(seq_len, i + 1) # +1因为我们不能看到未来
mask[i, start:end] = 1
elif pattern_type == "strided":
# 跨步注意力:关注以固定步长采样的标记
stride = 128
for i in range(seq_len):
for j in range(0, i + 1, stride): # +1因为我们不能看到未来
mask[i, j] = 1
return mask
GPT-4:多模态能力#
GPT-4于2023年发布,代表了大型语言模型向多模态理解的扩展,以及更强的推理能力和更好的对齐性。
核心特点:
参数规模未公开,但估计超过1万亿
支持图像和文本输入(多模态)
更长的上下文窗口(最多支持32K标记)
更好的事实准确性和推理能力
创新点:
多模态理解能力
更好的指令跟随和对齐
更强的推理和编码能力
减少了幻觉和偏见
架构特点:
具体架构细节未公开
可能使用了混合专家系统(MoE)
可能整合了多种模态编码器
使用了更先进的对齐技术(RLHF和其他方法)
# GPT-4多模态处理的概念示例
class MultimodalGPT4(nn.Module):
def __init__(self, text_model, vision_model, fusion_layer):
super().__init__()
self.text_model = text_model
self.vision_model = vision_model
self.fusion_layer = fusion_layer
def forward(self, text_input=None, image_input=None):
# 处理文本输入
if text_input is not None:
text_features = self.text_model(text_input)
else:
text_features = None
# 处理图像输入
if image_input is not None:
image_features = self.vision_model(image_input)
else:
image_features = None
# 融合多模态特征
if text_features is not None and image_features is not None:
# 多模态融合
return self.fusion_layer(text_features, image_features)
elif text_features is not None:
# 仅文本模式
return text_features
elif image_features is not None:
# 仅图像模式
return self.fusion_layer.text_projection(image_features)
else:
raise ValueError("至少需要一种输入模态")
GPT系列的演进趋势#
GPT系列的演进展示了几个明显的趋势:
规模扩大:
参数数量:从1.17亿(GPT-1)到1750亿(GPT-3)再到估计的1万亿+(GPT-4)
训练数据量:从数GB到数TB
计算资源:从数百GPU小时到数百万GPU小时
能力涌现:
随着规模增加,模型展示了未经专门训练的新能力
从简单的文本补全到复杂的推理和问题解决
多模态整合:
从纯文本到文本+图像
未来可能包括更多模态(音频、视频等)
对齐改进:
从纯语言建模到更好地遵循人类意图
减少有害输出和幻觉
架构优化:
注意力机制的改进
更高效的训练和推理技术
更好的缩放策略
Llama系列:开放权重模型#
Llama系列由Meta AI开发,代表了高性能开放权重模型的重要里程碑。Llama模型的开放性质促进了社区创新和模型适应的爆炸性增长。
Llama 1:高效架构#
Llama 1于2023年2月发布,展示了与闭源模型相当的性能,但使用更少的参数和计算资源。
核心特点:
提供多种规模:7B、13B、33B和65B参数
在1.4万亿标记上训练
使用更高效的架构组件
仅在公开可用的数据上训练
创新组件:
旋转位置嵌入(RoPE, Rotary Positional Embedding): 一种更有效的位置编码方法,通过旋转嵌入向量来编码位置信息。
import torch def rotate_half(x): x1, x2 = x.chunk(2, dim=-1) return torch.cat((-x2, x1), dim=-1) def apply_rotary_pos_emb(q, k, cos, sin, position_ids): # 获取查询和键的形状 batch_size, seq_len, num_heads, head_dim = q.shape # 获取位置编码 cos = cos[position_ids].unsqueeze(2) # [bs, seq_len, 1, dim] sin = sin[position_ids].unsqueeze(2) # [bs, seq_len, 1, dim] # 应用旋转 q_embed = (q * cos) + (rotate_half(q) * sin) k_embed = (k * cos) + (rotate_half(k) * sin) return q_embed, k_embed
RMSNorm(Root Mean Square Normalization): 一种简化的层归一化变体,计算更高效。
class RMSNorm(nn.Module): def __init__(self, hidden_size, eps=1e-6): super().__init__() self.weight = nn.Parameter(torch.ones(hidden_size)) self.eps = eps def forward(self, x): # 计算RMS rms = torch.sqrt(torch.mean(x ** 2, dim=-1, keepdim=True) + self.eps) # 归一化 x_norm = x / rms # 缩放 return self.weight * x_norm
SwiGLU激活函数: 一种改进的门控线性单元变体,提供更好的性能。
class SwiGLU(nn.Module): def __init__(self, in_features, hidden_features): super().__init__() self.w1 = nn.Linear(in_features, hidden_features) self.w2 = nn.Linear(in_features, hidden_features) self.w3 = nn.Linear(hidden_features, in_features) def forward(self, x): return self.w3(F.silu(self.w1(x)) * self.w2(x))
架构特点:
预归一化Transformer架构
使用RoPE位置编码
使用RMSNorm代替LayerNorm
使用SwiGLU激活函数
没有偏置项(bias terms)
# Llama 1风格的Transformer块
class LlamaBlock(nn.Module):
def __init__(self, hidden_size, num_heads, intermediate_size, rope_theta=10000):
super().__init__()
self.hidden_size = hidden_size
self.num_heads = num_heads
self.head_dim = hidden_size // num_heads
# 注意力层
self.attention_norm = RMSNorm(hidden_size)
self.q_proj = nn.Linear(hidden_size, hidden_size, bias=False)
self.k_proj = nn.Linear(hidden_size, hidden_size, bias=False)
self.v_proj = nn.Linear(hidden_size, hidden_size, bias=False)
self.o_proj = nn.Linear(hidden_size, hidden_size, bias=False)
# RoPE
self.rope_theta = rope_theta
# 前馈层
self.mlp_norm = RMSNorm(hidden_size)
self.mlp = SwiGLU(hidden_size, intermediate_size)
def forward(self, x, position_ids):
# 注意力块
residual = x
x = self.attention_norm(x)
# 投影查询、键、值
q = self.q_proj(x).view(x.size(0), x.size(1), self.num_heads, self.head_dim)
k = self.k_proj(x).view(x.size(0), x.size(1), self.num_heads, self.head_dim)
v = self.v_proj(x).view(x.size(0), x.size(1), self.num_heads, self.head_dim)
# 计算RoPE的sin和cos
seq_len = x.size(1)
freqs = 1.0 / (self.rope_theta ** (torch.arange(0, self.head_dim, 2).float() / self.head_dim))
t = torch.arange(seq_len).type_as(freqs)
freqs = torch.outer(t, freqs)
cos = torch.cos(freqs).view(1, seq_len, 1, -1)
sin = torch.sin(freqs).view(1, seq_len, 1, -1)
cos = torch.cat([cos, cos], dim=-1)
sin = torch.cat([sin, sin], dim=-1)
# 应用RoPE
q, k = apply_rotary_pos_emb(q, k, cos, sin, position_ids)
# 重塑为注意力计算的形状
q = q.transpose(1, 2) # [batch, heads, seq_len, head_dim]
k = k.transpose(1, 2)
v = v.transpose(1, 2)
# 计算注意力
scores = torch.matmul(q, k.transpose(-1, -2)) / math.sqrt(self.head_dim)
# 创建注意力掩码(确保只看到过去的标记)
mask = torch.triu(torch.ones(seq_len, seq_len), diagonal=1).bool().to(x.device)
scores = scores.masked_fill(mask, -1e9)
attn_weights = F.softmax(scores, dim=-1)
context = torch.matmul(attn_weights, v)
# 重塑和投影
context = context.transpose(1, 2).contiguous().view(x.size(0), x.size(1), self.hidden_size)
x = self.o_proj(context)
# 残差连接
x = residual + x
# MLP块
residual = x
x = self.mlp_norm(x)
x = self.mlp(x)
# 残差连接
x = residual + x
return x
Llama 2:改进与开放#
Llama 2于2023年7月发布,提供了性能改进和更开放的许可证,进一步推动了社区采用。
核心特点:
提供多种规模:7B、13B和70B参数
在2万亿标记上训练(比Llama 1多40%)
上下文长度从2048增加到4096标记
提供经过对话微调的变体(Llama 2 Chat)
架构改进:
分组查询注意力(GQA, Grouped-Query Attention): 一种介于多查询注意力(MQA)和多头注意力(MHA)之间的方法,提供更好的性能-效率权衡。
class GroupedQueryAttention(nn.Module): def __init__(self, hidden_size, num_heads, num_kv_heads): super().__init__() self.hidden_size = hidden_size self.num_heads = num_heads self.num_kv_heads = num_kv_heads self.num_queries_per_kv = num_heads // num_kv_heads self.head_dim = hidden_size // num_heads self.q_proj = nn.Linear(hidden_size, hidden_size, bias=False) self.k_proj = nn.Linear(hidden_size, self.num_kv_heads * self.head_dim, bias=False) self.v_proj = nn.Linear(hidden_size, self.num_kv_heads * self.head_dim, bias=False) self.o_proj = nn.Linear(hidden_size, hidden_size, bias=False) def forward(self, x, mask=None): batch_size, seq_len, _ = x.size() # 投影查询、键、值 q = self.q_proj(x).view(batch_size, seq_len, self.num_heads, self.head_dim) k = self.k_proj(x).view(batch_size, seq_len, self.num_kv_heads, self.head_dim) v = self.v_proj(x).view(batch_size, seq_len, self.num_kv_heads, self.head_dim) # 重复键和值以匹配查询头数 if self.num_kv_heads != self.num_heads: k = k.repeat_interleave(self.num_queries_per_kv, dim=2) v = v.repeat_interleave(self.num_queries_per_kv, dim=2) # 重塑为注意力计算的形状 q = q.transpose(1, 2) # [batch, heads, seq_len, head_dim] k = k.transpose(1, 2) v = v.transpose(1, 2) # 计算注意力 scores = torch.matmul(q, k.transpose(-1, -2)) / math.sqrt(self.head_dim) if mask is not None: scores = scores.masked_fill(mask, -1e9) attn_weights = F.softmax(scores, dim=-1) context = torch.matmul(attn_weights, v) # 重塑和投影 context = context.transpose(1, 2).contiguous().view(batch_size, seq_len, self.hidden_size) return self.o_proj(context)
改进的预训练目标: 使用更长的序列和更多样化的数据集。
更好的对齐技术: 使用RLHF和其他技术使模型更好地对齐人类偏好。
Llama 2 Chat: Llama 2还提供了经过对话微调的变体,使用了以下技术:
监督微调(SFT)
人类反馈的强化学习(RLHF)
迭代的红队测试和改进
# Llama 2 Chat的系统提示示例
SYSTEM_PROMPT = """You are a helpful, harmless, and honest AI assistant.
You answer questions truthfully and don't make up information.
If you don't know the answer to a question, you admit it instead of making up an answer.
You refuse to engage in harmful, illegal, unethical, or deceptive activities.
You consider the safety and well-being of users in your responses."""
# 对话格式
def format_chat(messages):
formatted = SYSTEM_PROMPT + "\n\n"
for msg in messages:
if msg["role"] == "user":
formatted += f"[USER]: {msg['content']}\n"
elif msg["role"] == "assistant":
formatted += f"[ASSISTANT]: {msg['content']}\n"
formatted += "[ASSISTANT]: "
return formatted
Llama 3:最新进展#
Llama 3于2024年4月发布,进一步提高了性能和能力。
核心特点:
提供8B和70B参数版本
更长的上下文窗口(支持8K标记)
改进的多语言能力
更好的指令跟随和对齐
架构改进:
具体细节尚未完全公开
可能包括更高效的注意力机制
改进的训练方法和数据集
更好的对齐技术
Llama系列的关键创新#
Llama系列引入了几项关键创新,这些创新已被广泛采用:
旋转位置嵌入(RoPE):
通过旋转嵌入向量编码位置信息
提供更好的外推能力
计算效率高
RMSNorm:
简化的层归一化变体
移除了均值计算和偏置项
提高计算效率
分组查询注意力(GQA):
在MQA和MHA之间取得平衡
减少内存使用和计算成本
保持模型质量
开放权重模型:
促进社区创新和适应
允许本地部署和自定义
推动了大量微调变体的发展
混合专家模型(MoE)#
混合专家模型(Mixture of Experts, MoE)是一种将模型容量与计算成本分离的架构,通过条件计算实现更高效的大型模型。
MoE的基本原理#
MoE的核心思想是将网络分解为多个”专家”(子网络),并使用一个路由器(gating network)决定每个输入应该由哪些专家处理。
class MixtureOfExperts(nn.Module):
def __init__(self, input_size, output_size, num_experts, k=2):
super().__init__()
self.input_size = input_size
self.output_size = output_size
self.num_experts = num_experts
self.k = k # 每个标记使用的专家数量
# 创建专家
self.experts = nn.ModuleList([
nn.Sequential(
nn.Linear(input_size, 4 * input_size),
nn.GELU(),
nn.Linear(4 * input_size, output_size)
) for _ in range(num_experts)
])
# 路由器(门控网络)
self.router = nn.Linear(input_size, num_experts)
def forward(self, x):
batch_size, seq_len, _ = x.size()
# 计算路由分数
router_logits = self.router(x) # [batch, seq, num_experts]
# 选择前k个专家
routing_weights, selected_experts = torch.topk(router_logits, self.k, dim=-1)
routing_weights = F.softmax(routing_weights, dim=-1)
# 准备输出
final_output = torch.zeros(batch_size, seq_len, self.output_size, device=x.device)
# 对每个专家进行计算
for expert_idx in range(self.num_experts):
# 找到使用这个专家的位置
expert_mask = (selected_experts == expert_idx).any(dim=-1).unsqueeze(-1)
if not expert_mask.any():
continue
# 提取需要这个专家处理的输入
expert_input = x * expert_mask
# 应用专家
expert_output = self.experts[expert_idx](expert_input)
# 找到这个专家的权重
weight_mask = (selected_experts == expert_idx).float()
expert_weights = routing_weights * weight_mask
# 加权求和
final_output += expert_output * expert_weights.unsqueeze(-1)
return final_output
MoE的优势#
计算效率:
每个输入只激活部分网络
可以增加模型容量而不等比增加计算
专业化:
不同专家可以专注于不同类型的输入
提高模型处理多样化数据的能力
可扩展性:
可以通过添加更多专家轻松扩展模型
支持分布式训练和推理
MoE的挑战#
负载平衡:
确保专家被均匀使用
防止”专家崩溃”(某些专家永不被使用)
路由决策:
设计有效的路由算法
平衡路由计算成本和准确性
训练稳定性:
MoE模型可能更难训练
需要特殊的正则化和初始化技术
MoE在大型语言模型中的应用#
Switch Transformers: Google的早期MoE实现,每个标记只路由到一个专家。
GShard: Google的分布式MoE框架,用于训练超大模型。
Mixtral 8x7B: Mistral AI的MoE模型,使用8个7B专家,每次激活2个。
GPT-4: 据推测使用了MoE架构,但具体细节未公开。
# Mixtral风格的MoE层示例
class MixtralMoELayer(nn.Module):
def __init__(self, hidden_size, num_experts=8, num_experts_per_tok=2):
super().__init__()
self.hidden_size = hidden_size
self.num_experts = num_experts
self.num_experts_per_tok = num_experts_per_tok
# 创建专家
self.experts = nn.ModuleList([
SwiGLU(hidden_size, 4 * hidden_size) for _ in range(num_experts)
])
# 路由器
self.router = nn.Linear(hidden_size, num_experts, bias=False)
def forward(self, x):
batch_size, seq_len, hidden_size = x.shape
# 计算路由分数
router_logits = self.router(x)
routing_weights, selected_experts = torch.topk(
router_logits, self.num_experts_per_tok, dim=-1
)
routing_weights = F.softmax(routing_weights, dim=-1)
# 初始化输出
final_output = torch.zeros_like(x)
# 应用专家
for batch_idx in range(batch_size):
for seq_idx in range(seq_len):
for k in range(self.num_experts_per_tok):
expert_idx = selected_experts[batch_idx, seq_idx, k].item()
weight = routing_weights[batch_idx, seq_idx, k].item()
# 应用专家并加权
expert_output = self.experts[expert_idx](x[batch_idx, seq_idx].unsqueeze(0))
final_output[batch_idx, seq_idx] += weight * expert_output.squeeze(0)
return final_output
神经网络架构在故事讲述AI中的应用#
不同的神经网络架构在构建故事讲述AI系统中有各自的优势和应用场景。
基础生成能力#
大型语言模型的基础生成能力是故事讲述的核心:
上下文理解:
理解用户提供的故事提示和约束
保持长篇故事的连贯性和一致性
创意生成:
创造引人入胜的情节和角色
生成多样化和原创的内容
风格适应:
模仿不同的文学风格和流派
调整语言复杂性以适应不同的受众
# 故事生成示例(使用预训练模型)
def generate_story(model, tokenizer, prompt, max_length=1000, temperature=0.7):
inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
# 生成参数
gen_kwargs = {
"max_length": max_length,
"temperature": temperature,
"top_p": 0.9,
"top_k": 50,
"repetition_penalty": 1.2,
"no_repeat_ngram_size": 3,
"do_sample": True
}
# 生成故事
output_sequences = model.generate(**inputs, **gen_kwargs)
# 解码
story = tokenizer.decode(output_sequences[0], skip_special_tokens=True)
return story
特定架构的优势#
不同架构在故事讲述中有不同的优势:
GPT系列:
强大的通用生成能力
丰富的文化和知识背景
GPT-4的多模态能力可用于图文故事
Llama系列:
开放权重允许本地部署和自定义
高效架构适合资源受限环境
社区微调变体提供专业化能力
MoE模型:
可以同时掌握多种写作风格
不同专家可以专注于不同类型的故事
更高效地处理长篇故事
架构选择考虑因素#
在为故事讲述AI选择架构时,应考虑以下因素:
故事复杂性:
简单故事可能不需要最大的模型
复杂、长篇故事可能需要更大的上下文窗口
互动性要求:
实时互动需要更高效的推理
回合制互动可以容忍更长的生成时间
部署环境:
本地部署可能需要更小、更高效的模型
云部署可以使用更大的模型
自定义需求:
需要特定领域适应的场景可能更适合开放权重模型
需要多模态能力的场景可能更适合GPT-4等模型
实现故事讲述系统的架构示例#
以下是一个基于Llama 2实现故事讲述系统的架构示例:
class StorytellerSystem:
def __init__(self, model_path, device="cuda"):
self.tokenizer = AutoTokenizer.from_pretrained(model_path)
self.model = AutoModelForCausalLM.from_pretrained(
model_path,
torch_dtype=torch.float16,
device_map=device
)
# 故事生成参数
self.default_params = {
"temperature": 0.7,
"top_p": 0.9,
"top_k": 50,
"repetition_penalty": 1.2,
"max_length": 2048
}
# 故事提示模板
self.story_prompt = """
Write a creative and engaging story based on the following elements:
Setting: {setting}
Main Character: {character}
Theme: {theme}
Genre: {genre}
The story should be {tone} in tone and approximately {length} words long.
"""
def generate_story(self, story_elements, custom_params=None):
# 准备提示
prompt = self.story_prompt.format(**story_elements)
# 合并参数
params = self.default_params.copy()
if custom_params:
params.update(custom_params)
# 编码提示
inputs = self.tokenizer(prompt, return_tensors="pt").to(self.model.device)
# 生成故事
with torch.no_grad():
output_sequences = self.model.generate(
**inputs,
max_length=params["max_length"],
temperature=params["temperature"],
top_p=params["top_p"],
top_k=params["top_k"],
repetition_penalty=params["repetition_penalty"],
do_sample=True
)
# 解码故事
story = self.tokenizer.decode(output_sequences[0], skip_special_tokens=True)
# 移除提示部分
story = story[len(prompt):]
return story
def continue_story(self, story_so_far, continuation_hint=None, custom_params=None):
# 准备提示
prompt = story_so_far
if continuation_hint:
prompt += f"\n\nContinue the story with the following elements: {continuation_hint}\n\n"
# 合并参数
params = self.default_params.copy()
if custom_params:
params.update(custom_params)
# 编码提示
inputs = self.tokenizer(prompt, return_tensors="pt").to(self.model.device)
# 生成续写
with torch.no_grad():
output_sequences = self.model.generate(
**inputs,
max_length=len(inputs["input_ids"][0]) + 500, # 生成500个新标记
temperature=params["temperature"],
top_p=params["top_p"],
top_k=params["top_k"],
repetition_penalty=params["repetition_penalty"],
do_sample=True
)
# 解码续写
continuation = self.tokenizer.decode(output_sequences[0], skip_special_tokens=True)
# 移除提示部分
continuation = continuation[len(prompt):]
return continuation
未来架构趋势#
神经网络架构的发展仍在快速演进,以下是一些可能影响故事讲述AI未来的趋势:
更长的上下文窗口:
允许生成和理解更长的故事
改进的注意力机制(如滑动窗口、稀疏注意力)
多模态整合:
文本和图像的深度融合
添加音频和视频能力
更高效的架构:
更多采用MoE和条件计算
更好的参数共享和知识蒸馏
可控生成:
更精细的风格和内容控制
更好的约束满足能力
个性化和适应:
更容易适应用户偏好
持续学习和改进
总结#
神经网络架构是故事讲述AI系统的基础,不同的架构提供了不同的能力和权衡:
GPT系列代表了大规模预训练和多模态能力的发展路线,从GPT-1的基础模型到GPT-4的多模态理解,展示了规模和数据如何带来能力的涌现。
Llama系列展示了开放权重模型和高效架构的价值,通过创新组件如RoPE、RMSNorm和GQA提高了性能和效率。
**混合专家模型(MoE)**提供了一种扩展模型容量而不等比增加计算成本的方法,特别适合需要多样化能力的故事讲述系统。
在构建故事讲述AI系统时,理解这些架构的优势和局限性至关重要。随着技术的发展,我们可以期待更强大、更高效、更易于控制的模型架构,为创造引人入胜的故事体验提供更好的基础。