Transformers 怎样区分 max_length 与 max_new_tokens
来源:17golang原创
时间:2026-11-11 21:54:01 373浏览 收藏
在 Transformers 里,这两个参数最容易被混淆的地方,是它们看起来都在“限制输出长度”,实际计数口径却不同:max_length 面向序列总长度,max_new_tokens 只面向本次新生成的 token 数。只要你的提示词长度会变化,通常应优先使用 max_new_tokens。
官方地址:https://huggingface.co/docs/transformers/
把问题压缩成一句话:想让模型无论提示词长短都最多续写 128 个 token,就设置max_new_tokens=128;只有在确实要限制整条序列的总 token 数时,才使用max_length。
先把两个参数放回同一条序列
对 decoder-only 模型,可以把返回序列看成两段:前半段是输入提示词,后半段是模型新生成的内容。此时可以用一个简单关系理解它们:
总序列长度 = 输入提示词长度 + 新生成长度
max_new_tokens 直接限制右边的“新生成长度”,不会因为提示词从 20 个 token 变成 200 个 token 而改变本次输出预算。max_length 则给整条序列设置上限,所以提示词越长,留给新内容的空间越小。

decoder-only 模型中,两个写法怎样换算
假设 tokenizer 处理后的输入长度是 80,你希望最多新增 64 个 token。那么用 max_new_tokens=64 表达的是一个稳定的输出预算;如果改用 max_length,等价的总长度上限大约是 144。
问题在于,144 只对这一次 80 token 的提示词成立。下一次提示词变成 120 token 时,仍然写 max_length=144,最多只剩约 24 个新 token。下面的代码把输入和新增部分分开计算,便于理解返回结果:
from transformers import AutoModelForCausalLM, AutoTokenizer model_name = "distilgpt2" tokenizer = AutoTokenizer.from_pretrained(model_name) model = AutoModelForCausalLM.from_pretrained(model_name) prompt = "用三句话解释缓存为什么需要过期时间。" inputs = tokenizer(prompt, return_tensors="pt") input_length = inputs["input_ids"].shape[1] # 只给新增内容设预算,提示词变长时仍保持同一上限。 generated = model.generate(**inputs, max_new_tokens=64) # decoder-only 返回输入和新增内容,切片后才是纯生成文本。 new_token_ids = generated[:, input_length:] text = tokenizer.decode(new_token_ids[0], skip_special_tokens=True) print(text)
如果业务要求的是“整条序列不能超过 512 个 token”,可以按当前输入动态计算总上限:
max_total_length = 512
# 这里表达的是总长度约束,而不是固定的生成预算。
generated = model.generate(
**inputs,
max_length=max_total_length,
)
实际项目里不建议把两个参数同时当作独立策略长期维护。要固定“续写多少”,直接传 max_new_tokens;要限制“整条序列多长”,围绕 max_length 计算并记录输入长度。这样代码的意图更清楚,也不会因为两个上限互相干扰而难以排查。
按任务选择参数,而不是按参数名猜含义
| 你的目标 | 优先参数 | 判断理由 |
|---|---|---|
| 回答、续写、聊天最多输出 N 个 token | max_new_tokens=N | 输出预算不随提示词长度漂移 |
| 控制上下文加输出的总长度 | max_length=N | 总序列不能超过统一上限 |
| 翻译或摘要只关心目标文本长度 | max_new_tokens=N | 以 decoder 端新增结果作为业务口径 |
| 兼容旧代码中的总长度设置 | max_length | 保留旧语义,同时明确它不是新增 token 预算 |
Hugging Face 当前 GenerationConfig 文档也建议使用 max_new_tokens 控制生成数量,max_length 主要作为兼容性选项保留。这个建议的核心不是参数“新旧”,而是新增长度更符合大多数推理接口的产品表达。
encoder-decoder 模型要看 decoder 端输出
T5、BART 这类 encoder-decoder 模型先把输入交给 encoder,再由 decoder 生成目标序列。此时输入文本和目标文本并不是 decoder-only 模型那种简单的同一条拼接序列,因此不要把输入字符数直接当成目标 token 数。
做翻译、摘要或结构化生成时,最稳定的做法仍然是用 max_new_tokens 表示目标文本最多生成多少 token。max_length 可以继续用于已有配置或统一的生成上限,但阅读代码时要确认这个上限对应的是哪一侧的序列。

from transformers import AutoModelForSeq2SeqLM, AutoTokenizer
model_name = "t5-small"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForSeq2SeqLM.from_pretrained(model_name)
inputs = tokenizer(
"translate English to German: The house is wonderful.",
return_tensors="pt",
)
# 翻译任务的预算指向 decoder 端的新 token,不把英文输入长度加进预算。
outputs = model.generate(**inputs, max_new_tokens=32)
print(tokenizer.decode(outputs[0], skip_special_tokens=True))
长度不符合预期时,先看这几个边界
- 提示词变长:使用
max_length时,输入占掉的 token 会变多,新增内容自然变短。 - 默认值介入:没有显式设置生成长度时,模型的 GenerationConfig 可能提供默认上限,调用方不要假设输出可以无限增长。
- 提前遇到 EOS:长度参数是上限,不是保证值;模型提前生成结束标记时,实际输出可以更短。
- 返回值包含输入:decoder-only 模型解码时要从
input_length位置切片,否则会把提示词误当成模型新输出。 - 同时设置两个参数:除非你明确知道当前 Transformers 版本的优先规则,否则不要让两个长度策略同时承担业务含义,保留一个主控参数更容易维护。
快速记忆
max_length 问的是“整条序列最多多长”,max_new_tokens 问的是“这次最多再写多少”。提示词固定且需要总长度上限时,前者有用;提示词会变化、业务只关心输出预算时,后者更合适。对大多数生成接口,先从 max_new_tokens 开始,再根据上下文窗口和返回值切片处理边界。
相关问题
max_new_tokens 会包含提示词吗?
不会。它表示忽略提示词长度后,本次最多生成的新 token 数。
为什么设置 max_length 后,提示词一长输出就变短?
因为 decoder-only 模型的输入和新增内容共同受总长度上限约束,提示词占用更多位置后,留给新增内容的空间就减少了。
为什么设置了长度上限,输出仍然比上限短?
长度参数通常是最大值,遇到 EOS 或其它停止条件时,生成会提前结束。
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
204 收藏
-
134 收藏
-
160 收藏
-
科技周边 · 人工智能 | 34分钟前 | 人工智能 · 深度学习 · PyTorch DataLoader Accelerate 多进程训练 split_batches dispatch_batches222 收藏
-
270 收藏
-
378 收藏
-
科技周边 · 人工智能 | 47分钟前 | python · 人工智能 · Hugging Face Datasets DatasetDict Features concatenate_datasets161 收藏
-
160 收藏
-
488 收藏
-
239 收藏
-
117 收藏
-
181 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习