首页
/ LongT5 长序列模型完全指南:Local / Transient-Global 注意力原理与 Transformers 实战

LongT5 长序列模型完全指南:Local / Transient-Global 注意力原理与 Transformers 实战

2026-09-07 19:07:42作者:明树来

LongT5 是面向长序列的 encoder-decoder Transformer 预训练模型,在 🤗 Transformers 中以 longt5 模块 形式提供,其核心创新在于将 T5 的稠密全注意力替换为 Local attention(局部滑窗注意力)Transient-Global(TGlobal,瞬时全局)注意力,从而在保持全局建模能力的同时把序列长度扩展到上万 token。阅读本文后,你将掌握 LongT5 的两大注意力机制及其源码级实现原理、完整的 LongT5Config 参数说明,并能在 16,384 token 的超长输入上完成摘要生成、翻译等 seq2seq 推理与微调实战。

说明:本文以仓库文档 docs/source/en/model_doc/longt5.md 为主体骨架,结合配置与实现源码 configuration_longt5.pymodeling_longt5.py 及自动模型映射展开。

LongT5 是什么:T5 架构的长序列扩展

LongT5 由 Mandy Guo、Joshua Ainslie、David Uthus、Santiago Ontanon、Jianmo Ni、Yun-Hsuan Sung、Yinfei Yang 等人在论文 LongT5: Efficient Text-To-Text Transformer for Long Sequences 中提出(论文于 2021-12-15 发布,模型于 2022-06-13 由 stancld 贡献给 Hugging Face Transformers)。它是一个在 text-to-text 去噪生成式设定下预训练的 encoder-decoder Transformer,本质上是 T5 的扩展——在保持 T5 可扩展架构的同时,把输入长度和模型规模两个维度同时放大。

论文的核心思路是从两条研究线汇合而来:

  • 借鉴长输入 Transformer(ETC)中的注意力设计——用稀疏的局部/全局注意力替代全量自注意力;
  • 采用摘要式预训练(PEGASUS)的策略,融入 T5 的去噪预训练目标。

最终得到一种新的注意力机制 Transient Global(TGlobal),它模拟了 ETC 的 local/global 注意力,却不需要额外的 side-inputs(如硬性的段落边界或额外输入)。

在 Transformers 中的典型应用场景是长输入序列到序列任务:当输入超过常用的 512 token,甚至到达 16,384 token 量级时,模型依然能高效地完成摘要(summarization)、问答、翻译等任务。下面的文档导读与对应任务指南可供继续深入:

两种高效注意力机制:Local 与 Transient-Global

LongT5ForConditionalGenerationT5ForConditionalGeneration 的扩展:它把传统 encoder 自注意力层替换为两种高效注意力之一,由配置项 encoder_attention_type 决定。注意这里的稀疏注意力只作用于编码器;解码器的自注意力与交叉注意力仍然走标准注意力路径(详见下文“源码架构”小节)。

Local Attention:零新增参数的滑窗稀疏注意力

Local Attention 的思想是:每个 token 只与自己左右各 local_radius 个 token 交互。

  • 默认 local_radius = 127,即每个 token 关注左右 127 个 token,滑窗块长 block_len = local_radius + 1 = 128
  • 不引入任何新参数,纯属计算模式的变化;
  • 计算复杂度与输入长度 l 呈线性:O(l * r)r = local_radius)。

Transient-Global(TGlobal)注意力:瞬时构造的全局 token

TGlobal 是 Local Attention 的超集:在局部滑窗之外,它还让每个输入 token 与层内所有其他 token 间接交互。实现上,输入序列被切分成固定长度 k 的块(默认 k = 16),块内所有 token 的 embedding 求和并归一化后得到该块的“全局 token”。

  • 每个 token 既能像 Local Attention 一样关注邻近 token,也能关注所有全局 token(即拥有了类似标准全局注意力的感受野);
  • “Transient(瞬时)”体现在:全局 token 是在每一次注意力运算内部动态构造的,并非额外输入;
  • 作为代价,TGlobal 会引入少量新参数:全局相对位置偏置(global relative position bias)全局 token embedding 的 layer normalization
  • 计算复杂度为 O(l * (r + l/k))

两种机制对比速览

特性 标准 T5 全注意力 Local Attention Transient-Global Attention
每个 token 关注范围 全序列 左右各 r(默认 127) 邻近 token + 全部全局 token
序列分块 块长 block_len = r + 1 局部块长 r+1,全局块长 k(默认 16)
新增参数 全局相对位置偏置 + 全局输入 LayerNorm
计算复杂度 O(l²) O(l·r) O(l·(r + l/k))
最大可用输入 512 量级(受显存限制) 最高 16,384 token 最高 16,384 token

源码级证据:分块与掩码工具函数

Local / TGlobal 的实现大量依赖序列分块辅助函数,它们在 modeling_longt5.py 顶部定义,是整个稀疏注意力的“地基”:

TGlobal 还需要额外的“侧路(side / global)”逻辑:

两条注意力主干的类分别是 LongT5LocalAttentionLongT5TransientGlobalAttention。TGlobal 的 forward 中可以看到关键的数据流:先由全局块 id 聚合并经 global_input_layer_norm 归一化得到全局输入,再把它投影为 side key/value,torch.cat 拼接到 3 块局部 key/value 之后,使打分维度变成 3*block_len + global_seq_len;随后把局部偏置(position_bias)与全局偏置(compute_side_bias,内部使用独立的 global_relative_attention_bias embedding)拼接后一起加到注意力分数上。

相对位置编码:LongT5 的位置信息载体

与 T5 一样,LongT5 不使用绝对位置 embedding,而是通过相对位置分桶偏置表达位置关系。_relative_position_bucket(同时以静态方法存在于多个注意力类中,源出 T5 实现)的做法是:

  • 把相对距离 memory_position - query_position 映射到有限数量的桶(bucket);
  • 双向注意力(encoder)时近一半桶留给正/负方向,之后按绝对值处理;
  • 距离小于 num_buckets/2 的部分按精确增量分桶,更大的距离按对数刻度分桶,超过 relative_attention_max_distance 的全部落入同一个桶。

这种“近处细粒度、远处粗粒度”的对数分桶设计保证了模型对超出训练长度的序列有更好的外推性。对 Local/TGlobal 注意力而言,compute_bias 只需对单个窗口(3*block_len)预计算一份分桶偏置即可,这正是稀疏注意力能大幅降低开销的关键;而普通全注意力的 compute_bias 需要针对完整 (query_length, key_length) 计算。相对位置 embedding 只挂在第一层(has_relative_attention_bias=bool(i==0)),并在各层间复用(LongT5Stack 构造)。

LongT5Config 参数全解

LongT5 的配置类定义在 configuration_longt5.pymodel_type = "longt5"。下面按默认值汇总了该类声明的全部核心字段,其中加粗项是 LongT5 区别于 T5 的关键配置:

参数 默认值 说明
vocab_size 32128 词表大小
d_model 512 隐藏层维度(与 hidden_size 同义)
d_kv 64 每头 key/value 投影维度(与 head_dim 同义)
d_ff 2048 每个 LongT5Block 中前馈层的中间维度
num_layers 6 encoder / decoder 层数(num_hidden_layers
num_decoder_layers None None 时取 num_layers
num_heads 8 注意力头数
local_radius 127 局部注意力中每个 token 向左/右各自能注意的 token 数
global_block_size 16 TGlobal 模式下构造全局 token 的序列分块长度 k
relative_attention_num_buckets 32 每层相对位置分桶数
relative_attention_max_distance 128 相对距离分桶的“远端上限”
feed_forward_proj "relu" 前馈层类型:"relu""gated-gelu"。LongT5v1.1 风格使用 "gated-gelu"
dropout_rate 0.1 dropout 比例
layer_norm_epsilon 1e-6 RMS LayerNorm 的 epsilon
initializer_factor 1.0 权重初始化缩放因子
is_encoder_decoder True 是否为 encoder-decoder 架构
encoder_attention_type "local" encoder 注意力类型:"local""transient-global",二选一
use_cache True 是否使用 past key/value 缓存加速解码
pad_token_id / eos_token_id 0 / 1 padding 与结束符 id
tie_word_embeddings True 是否共享输入/输出 embedding

几点实现细节值得注意:

  • feed_forward_proj 会被 __post_init__ 拆解:末尾段作为激活函数名写入 dense_act_fn;当值为 "gated-gelu" 时激活切换为 "gelu_new",并置 is_gated_act=True,模型就会选用带门控的双线性前馈层 LongT5DenseGatedActDensehidden = gelu(xW1) * (xW2)),否则用标准 LongT5DenseActDense
  • validate_architecture 会校验 feed_forward_proj 格式,只接受 {ACT_FN}gated-{ACT_FN}
  • 与 T5 相同的“怪癖”:tie_word_embeddings=False 本表示 1.1 版本风格(不再对 decoder 输出做缩放),但 checkpoint 中只保存 shared.weight,因此权重总是共享;源码会把 scale_decoder_outputs 取为 tie_word_embeddings 后强制 tie_word_embeddings=True。是否缩放 decoder 输出直接影响 LongT5ForConditionalGeneration.forward 中的 sequence_output * (model_dim ** -0.5)

选择哪种注意力,只需在加载模型前指定配置。例如构造一个小规模的 TGlobal 变体:

from transformers import LongT5Config, LongT5ForConditionalGeneration

config = LongT5Config(
    encoder_attention_type="transient-global",  # "local" 或 "transient-global"
    global_block_size=16,                       # TGlobal 的全局分块长度 k
    local_radius=127,                           # 局部滑窗半径 r
)
model = LongT5ForConditionalGeneration(config)

警告:如果 encoder_attention_type 传了 "local""transient-global" 以外的值,编码器块构造会直接抛出 ValueError(见 LongT5Block)。

源码架构与模型类解析

模块 src/transformers/models/longt5 由三个文件构成:配置类、模型实现和懒加载入口。类结构的顶层概览如下。

编码器块的三分支路由

LongT5Block 是构成 encoder/decoder 堆栈的基础模块,其自注意力分支选择规则为:

每种自注意力都遵循“RMS LayerNorm → 注意力 → 残差加和 → FF → 残差加和”的 T5 式结构。而注意力掩码的准备也在 LongT5Stack.forward 中分流:local 模式用 _get_local_attention_mask 生成滑窗掩码,transient-global 模式则把原始扩展掩码传入块内(局部与全局掩码在注意力内部各自计算)。

层归一化的特殊之处

LongT5LayerNorm 是 RMS(Root Mean Square)归一化:只做缩放、不去均值、无 bias,与 T5 风格一致;同时为了数值稳定,方差累加在 fp32 中进行,输出再按参数 dtype 转回半精度。所有层共享同一 layer norm 权重类,LongT5Stack 末尾还有一个 final_layer_norm

提供的四个公开模型类

模型文件 init.py 与实现文件末尾 __all__ 中暴露了以下类:

  • LongT5Model:裸的 encoder-decoder 模型,forward 返回 Seq2SeqModelOutput。encoder 与 decoder 之间共享 shared embedding(_tied_weights_keys 将两侧 embed_tokens.weight 指向 shared.weight);
  • LongT5ForConditionalGeneration:在 decoder 之上加 lm_head 的语言建模头,继承 GenerationMixin,支持 generate 自回归解码与 labels 有监督训练;lm_head.weight 同样与 shared.weight 绑定;
  • LongT5EncoderModel:仅编码器版本,适合为长文本提取稠密向量(embedding/检索场景);
  • LongT5PreTrainedModel:基类,声明 base_model_prefix = "transformer"、支持梯度检查点、_no_split_modules = ["LongT5Block"](便于大模型切分)。

在自动模型体系中,三类模型均可通过 AutoModel 系列加载:映射关系记录在 modeling_auto.pylongt5 -> LongT5Model)与 modeling_auto.pylongt5 -> LongT5ForConditionalGeneration),配置类映射见 auto_mappings.py

官方 checkpoint 家族

文档源码 docstring 中出现的可用预训练 checkpoint 有:

  • google/long-t5-local-basegoogle/long-t5-local-base 系列(Local 注意力)提供 local/tglobal × base/large,其中 large 版本按文档描述支持 16,384 token 输入;
  • Stancld/longt5-tglobal-large-16384-pubmed-3k_steps:社区贡献的、在 PubMed 上微调 3k 步的 TGlobal-large 摘要模型(见下文实战示例)。

加载时无需手动指定注意力类型——checkpoint 的 config.json 已写入 encoder_attention_type 等全部配置。

实战一:在超长输入上做摘要评估

原文档给出了一个可直接运行的端到端示例:用微调后的 LongT5 模型在 PubMed(scientific_papers)验证集上生成摘要,再用 ROUGE 指标评估。它覆盖了“超长 tokenizer 截断 + 半精度推理 + beam search + 批量 ROUGE 评估”的完整链路:

import evaluate
from datasets import load_dataset

from transformers import AutoTokenizer, LongT5ForConditionalGeneration


dataset = load_dataset("scientific_papers", "pubmed", split="validation")
model = (
    LongT5ForConditionalGeneration.from_pretrained(
        "Stancld/longt5-tglobal-large-16384-pubmed-3k_steps", device_map="auto"
    )
    .to("auto")
    .half()
)
tokenizer = AutoTokenizer.from_pretrained("Stancld/longt5-tglobal-large-16384-pubmed-3k_steps")


def generate_answers(batch):
    inputs_dict = tokenizer(
        batch["article"], max_length=16384, padding="max_length", truncation=True, return_tensors="pt"
    )
    input_ids = inputs_dict.input_ids.to(model.device)
    attention_mask = inputs_dict.attention_mask.to(model.device)
    output_ids = model.generate(input_ids, attention_mask=attention_mask, max_length=512, num_beams=2)
    batch["predicted_abstract"] = tokenizer.batch_decode(output_ids, skip_special_tokens=True)
    return batch


result = dataset.map(generate_answers, batched=True, batch_size=2)
rouge = evaluate.load("rouge")
rouge.compute(predictions=result["predicted_abstract"], references=result["abstract"])

要点提示:

  • tokenizer(..., max_length=16384, truncation=True) 直接把输入截断/补齐到 LongT5 支持的最大长度——这正是 T5 无法低成本做到、而 LongT5 的设计目标所在;
  • .half() 把权重转为 fp16。源码中 LongT5Block 对 fp16 下的 inf 做了 clamp,说明该实现显式兼容 fp16 推理;
  • padding="max_length" 是安全的,因为 LongT5 基于相对位置编码,文档明确说明输入可在左右任意一侧做 padding;
  • generate 参数(max_lengthnum_beams)来自 Transformer 的通用 GenerationMixin,LongT5 解码器对 past_key_values 有完整缓存支持。

实战二:零样本快速体验与训练/微调

快速生成体验

在未微调的权重上同样可以体验长输入生成。以下改编自 LongT5ForConditionalGeneration.forward 的官方 docstring 示例:把同一句话重复 100 次拼成一个超长输入,观察模型的续写行为。

from transformers import AutoTokenizer, LongT5ForConditionalGeneration

tokenizer = AutoTokenizer.from_pretrained("Stancld/longt5-tglobal-large-16384-pubmed-3k_steps")
model = LongT5ForConditionalGeneration.from_pretrained(
    "Stancld/longt5-tglobal-large-16384-pubmed-3k_steps"
)

# 构造超长输入(约数千 token)
inputs = tokenizer(100 * "studies have shown that owning a dog is good for you ", return_tensors="pt")
input_ids = inputs.input_ids

outputs = model.generate(input_ids)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))

从模型内部构造理解数据流

  • 训练时传入 labels 即可:LongT5ForConditionalGeneration.forward 会在未提供 decoder_input_ids 时自动调用 _shift_right(labels) 做右移构造 decoder 输入,并以 pad_token_id 作为 decoder_input_ids 的起始 token(源码实现);loss 采用 CrossEntropyLoss(ignore_index=-100),把 labels-100 的位置忽略。
  • 编码器输入通过 input_ids / attention_mask 传入;若要复用已编码结果(如多次解码),可先取 encoder_outputs 再传入 encoder_outputs 参数,避免重复前向编码。
  • 与 T5 不同,LongT5 不使用任务前缀(task prefix),且预训练目标受 PEGASUS 启发(摘要式去噪),这两点是选型与迁移时的重要背景(依据原文档 Usage tips)。

通用 API 形态

若只关心输入句子的上下文表示(不做生成),可这样使用:

from transformers import AutoTokenizer, LongT5Model

tokenizer = AutoTokenizer.from_pretrained("google/long-t5-local-base")
model = LongT5Model.from_pretrained("google/long-t5-local-base")

# 用重复语句构造一个很长的 encoder 输入
input_ids = tokenizer(
    100 * "Studies have been shown that owning a dog is good for you", return_tensors="pt"
).input_ids
decoder_input_ids = tokenizer("Studies show that", return_tensors="pt").input_ids

outputs = model(input_ids=input_ids, decoder_input_ids=decoder_input_ids)
last_hidden_states = outputs.last_hidden_state

仅编码器版本(适用于对长文本做表征提取、检索或分类特征)则更轻量:

from transformers import AutoTokenizer, LongT5EncoderModel

tokenizer = AutoTokenizer.from_pretrained("google/long-t5-local-base")
model = LongT5EncoderModel.from_pretrained("google/long-t5-local-base")

input_ids = tokenizer(
    100 * "Studies have been shown that owning a dog is good for you ", return_tensors="pt"
).input_ids
outputs = model(input_ids=input_ids)
last_hidden_states = outputs.last_hidden_state

行为验证与测试用例

仓库提供了与模型行为直接对应的测试套件 test_modeling_longt5.py,可在对实现进行修改或排障时作为参照。它验证的内容包括模型与 T5 家族通用的前后向数值稳定性、generate 与缓存一致性、encoder_attention_type 两种配置下的等价性等。对源码结构感兴趣的读者可以配合阅读 tests/models/longt5 下的全部测试文件。

适用边界与注意事项总结

  1. 长序列定位:LongT5 面向的是“输入显著超过 512 token”的 seq2seq 任务;官方文档声明其可处理最长 16,384 token 的输入序列。实际是否可用取决于显存——TGlobal 仍是 O(l²/k) 量级的全局开销,输入越长越需要大显存或梯度检查点配合。
  2. 参数引入差异:Local 变体零新增参数,可直接从结构相近的 T5 checkpoint 做权重迁移研究;TGlobal 变体额外引入 global_relative_attention_biasglobal_input_layer_norm 两组参数。
  3. 无任务前缀:与 T5 不同,LongT5 不在输入前拼接 "summarize:" 之类的任务前缀;其预训练目标也更接近 PEGASUS 的摘要式去噪。
  4. 配置合法性encoder_attention_type 仅支持 "local""transient-global"feed_forward_proj 仅支持 "relu""gated-gelu",非法取值会由配置校验或模块构造直接报错。
  5. 推理数值:源码针对 fp16 做了显式 inf clamp,说明官方实现已将半精度推理作为一等公民支持,可按需使用 .half()device_map="auto" 组合(多卡分片)。

上述所有配置、类与示例均可在当前仓库内对应路径找到第一手实现,遇到与本文描述不一致的行为时,建议直接以 src/transformers/models/longt5/modeling_longt5.pysrc/transformers/models/longt5/configuration_longt5.py 的当前代码为准。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
898
5.82 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
531
596
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
921
1.84 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.8 K
1.02 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.36 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.02 K
519
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
391