Files
transformer_study/example.py
T
XingfenD c57a9bf9e6 添加KV Cache支持:实现prefill/decode阶段分离
- MultiHeadAttention类添加KV cache机制
- TransformerBlock支持use_cache参数
- SimpleTransformer新增prefill和decode方法
- 添加InferenceEngine推理引擎类
- 更新example.py演示推理过程
- 更新README.md文档
2026-07-16 15:07:47 +08:00

160 lines
4.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import numpy as np
from transformer import SimpleTransformer, InferenceEngine, create_padding_mask, create_look_ahead_mask
def demo_training_forward():
"""演示训练时的前向传播(无KV cache"""
print("=" * 60)
print("训练前向传播演示(无KV cache")
print("=" * 60)
# 模型超参数配置
vocab_size = 1000
d_model = 512
num_heads = 8
num_layers = 6
d_ff = 2048
max_seq_len = 100
# 创建模型
model = SimpleTransformer(vocab_size, d_model, num_heads, num_layers, d_ff, max_seq_len)
# 创建随机输入
batch_size = 2
seq_len = 10
x = np.random.randint(1, vocab_size, (batch_size, seq_len))
print(f"输入形状: {x.shape}")
print(f"输入示例: {x[0]}")
# 训练模式前向传播(不使用KV cache)
output = model.forward(x)
print(f"输出形状: {output.shape}")
print(f"输出示例(前5个值): {output[0, 0, :5]}")
print()
def demo_prefill_decode():
"""演示推理时的prefill和decode阶段"""
print("=" * 60)
print("推理演示(Prefill + Decode")
print("=" * 60)
# 模型超参数配置
vocab_size = 1000
d_model = 128 # 使用较小的模型以便快速演示
num_heads = 4
num_layers = 2
d_ff = 512
max_seq_len = 100
# 创建模型和推理引擎
model = SimpleTransformer(vocab_size, d_model, num_heads, num_layers, d_ff, max_seq_len)
engine = InferenceEngine(model)
# 模拟输入序列(prompt
batch_size = 1
prompt_len = 5
prompt = np.random.randint(1, vocab_size, (batch_size, prompt_len))
print(f"输入prompt: {prompt[0]}")
print(f"Prompt长度: {prompt_len}")
print()
# Prefill阶段
print("--- Prefill阶段 ---")
print("处理完整prompt,初始化KV cache")
logits = engine.prefill(prompt)
print(f"Prefill输出logits形状: {logits.shape}")
print(f"当前位置: {engine.current_position}")
# 采样第一个token
first_token = engine._sample(logits, temperature=0.8)
print(f"采样的第一个token: {first_token[0, 0]}")
print()
# Decode阶段
print("--- Decode阶段 ---")
print("逐个生成新token(使用KV cache")
generated_tokens = [first_token[0, 0]]
current_token = first_token
# 生成5个token作为演示
for i in range(5):
logits = engine.decode_step(current_token)
current_token = engine._sample(logits, temperature=0.8)
generated_tokens.append(current_token[0, 0])
print(f"Step {i+1}: 生成token {current_token[0, 0]}, 位置 {engine.current_position}")
print()
print(f"完整生成序列: {generated_tokens}")
print()
def demo_auto_regressive():
"""演示自回归生成"""
print("=" * 60)
print("自回归生成演示")
print("=" * 60)
# 模型超参数配置
vocab_size = 1000
d_model = 128
num_heads = 4
num_layers = 2
d_ff = 512
max_seq_len = 100
# 创建模型和推理引擎
model = SimpleTransformer(vocab_size, d_model, num_heads, num_layers, d_ff, max_seq_len)
engine = InferenceEngine(model)
# 模拟输入序列
batch_size = 1
prompt_len = 3
prompt = np.random.randint(1, vocab_size, (batch_size, prompt_len))
print(f"输入prompt: {prompt[0]}")
# 使用generate方法进行自回归生成
output = engine.generate(prompt, max_new_tokens=10, temperature=0.8)
print(f"生成的完整序列: {output[0]}")
print(f"序列长度: {len(output[0])} (原始{prompt_len} + 生成{len(output[0]) - prompt_len})")
print()
def demo_kv_cache_comparison():
"""对比有无KV cache的计算差异"""
print("=" * 60)
print("KV Cache计算对比")
print("=" * 60)
print("无KV cache(训练模式):")
print(" - 每次forward处理完整序列")
print(" - 计算量: O(n^2) 每次")
print(" - 适用于训练")
print()
print("有KV cache(推理模式):")
print(" - Prefill: 处理完整prompt,缓存KV")
print(" - Decode: 只处理新token,使用缓存")
print(" - 计算量: Prefill O(n^2), Decode O(n) 每步")
print(" - 适用于推理")
print()
if __name__ == "__main__":
# 演示训练前向传播
demo_training_forward()
# 演示prefill和decode
demo_prefill_decode()
# 演示自回归生成
demo_auto_regressive()
# 对比说明
demo_kv_cache_comparison()