当前位置:首页 > 文章列表 > 科技周边 > 人工智能 > Hugging Face Transformers 怎样只输出生成结果而不带输入提示词

Hugging Face Transformers 怎样只输出生成结果而不带输入提示词

来源:17golang原创 2026-11-07 23:30:52 0浏览 收藏

在 Hugging Face Transformers 中调用 model.generate() 后,如果直接把返回的整行 token 交给 tokenizer 解码,decoder-only 模型通常会把输入提示词一起返回。这不是模型重复生成,而是返回序列包含了“输入 token + 新生成 token”。真正需要做的是先确定输入长度,再只解码新增部分。

官方文档:https://huggingface.co/docs/transformers/

这篇只讨论生成结果的边界,不涉及模型训练。最小原则可以先记住:decoder-only 按有效输入长度切片;encoder-decoder 不要机械套用同一个切片公式;批量输入要按行处理 padding。

问题现场:为什么输出里重复了 prompt

常见代码大致是这样:

from transformers import AutoTokenizer, AutoModelForCausalLM

model_name = "distilgpt2"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name)

prompt = "Explain why caching helps inference."
inputs = tokenizer(prompt, return_tensors="pt")

# max_new_tokens 只限制新增 token,不代表返回值只含新增 token。
output_ids = model.generate(**inputs, max_new_tokens=32)

# 直接解码整行会把 prompt 也带回结果。
full_text = tokenizer.decode(output_ids[0], skip_special_tokens=True)
print(full_text)

这里的 output_ids[0] 是完整序列。对 decoder-only 模型,它通常从输入 token 开始,后面才是模型新生成的 token。因此修复重点不是把 prompt 从字符串里做替换,而是在 token 层找到边界。

tokenizer、input_ids、generate 和完整 sequences 之间的输入与新生成 token 静态关系图
图1:生成序列边界说明图。左侧是输入 token,中间是 generate 返回的完整序列,右侧标出只应解码的新增 token;这是静态结构示意,不是运行截图。

最小修复:按输入长度截出新生成 token

单条、无 padding 的 decoder-only 输入,可以使用输入序列长度作为切片起点:

# input_ids 的长度就是完整序列中“输入提示词”占用的 token 数。
input_length = inputs["input_ids"].shape[1]
new_token_ids = output_ids[0, input_length:]

# 只解码切片后的 token,得到新增文本。
new_text = tokenizer.decode(new_token_ids, skip_special_tokens=True)
print(new_text)

这段代码的关键不是 decode 的参数,而是先在 token 序列上切片。字符串层面用 replace(prompt, "") 有两个问题:模型可能改变空格或换行,prompt 也可能在生成内容中自然出现,字符串替换无法表达 token 边界。

max_new_tokens 仍然值得保留,它控制最多生成多少个新 token;它不会改变返回序列是否包含输入,也不是“只返回新文本”的开关。

从单条输入扩展到批量输入

批量场景里,不能把第一行的长度套给所有样本。右 padding 与左 padding 还会让输入张量的形状和有效 token 位置不同,所以应先确定 tokenizer 的 padding 策略,再按每一行的有效长度切片。

prompts = [
    "Explain cache locality in one paragraph.",
    "Explain tokenizer padding in one paragraph.",
]

# padding=True 让 batch 形成矩形;attention_mask 标出每行有效输入位置。
batch = tokenizer(prompts, padding=True, return_tensors="pt")
batch_output = model.generate(**batch, max_new_tokens=32)

texts = []
for row_ids, row_mask in zip(batch_output, batch["attention_mask"]):
    # 只统计有效输入 token,避免把 padding 长度当成 prompt 长度。
    valid_input_length = int(row_mask.sum().item())
    new_ids = row_ids[valid_input_length:]
    texts.append(tokenizer.decode(new_ids, skip_special_tokens=True))

for text in texts:
    print(text)

上面的写法适合右 padding 的常见批量输入。若模型和 tokenizer 使用左 padding,完整输出序列的前缀布局需要结合模型的 padding 配置确认,不能只凭“总长度减去 padding 数量”猜切片位置。这里的检查点是:每行的有效输入长度、模型返回序列形状、解码后的新文本三者要对应。

decoder-only 和 encoder-decoder 不能混用公式

GPT 类 decoder-only 模型把输入作为生成序列的前缀,因此按输入长度截取通常成立。T5、BART 这类 encoder-decoder 模型的输入先进入 encoder,decoder 生成自己的序列,返回序列一般不等于“encoder 输入 token 加上 decoder 新 token”。

因此写通用封装时,先根据模型架构决定规则:

模型形态返回序列的关注点处理建议
decoder-only输入 token 常位于返回序列前缀按每行有效输入长度切片后 decode
encoder-decoderdecoder 输出有自己的序列边界直接解码生成序列,并按特殊 token 规则处理
批量输入padding 会改变张量形状读取 attention_mask,逐行处理
批量 input_ids、padding、attention_mask 与两种模型输出边界的静态关系图
图2:批量解码边界说明图。上层对比 decoder-only 与 encoder-decoder 的序列关系,下层展示 batch、padding、attention_mask 和逐行切片的对应关系;这是静态结构示意,不是运行截图。

什么时候用 return_dict_in_generate

如果只要文本,默认返回的序列就够用;如果还要分数、hidden states、attentions 或 cache,可以打开结构化返回:

# 结构化返回用于同时读取 sequences 和可选的 scores 等字段。
generation = model.generate(
    **inputs,
    max_new_tokens=32,
    return_dict_in_generate=True,
    output_scores=True,
)

# sequences 仍然需要按模型类型判断边界,不会自动替你删除 prompt。
sequence_ids = generation.sequences[0]
input_length = inputs["input_ids"].shape[1]
new_text = tokenizer.decode(sequence_ids[input_length:], skip_special_tokens=True)

return_dict_in_generate=True 解决的是“返回哪些结构化字段”,不是“返回值是否只含新文本”。把这两个问题分开,排查会简单很多。

Pipeline 返回值为什么看起来不一样

如果改用 pipeline("text-generation"),pipeline 可能根据参数把完整文本或只包含新增文本的结果整理成字典。这里要以当前 Transformers 版本对应的 pipeline 参数和返回结构为准,不要把 pipeline 的行为直接推断到底层 model.generate()。

from transformers import pipeline

generator = pipeline("text-generation", model="distilgpt2", tokenizer="distilgpt2")

# return_full_text 是 pipeline 层的结果整理选项;它不是 generate 的参数。
result = generator(
    "Explain cache locality.",
    max_new_tokens=32,
    return_full_text=False,
)
print(result[0]["generated_text"])

如果你的项目已经封装了 pipeline,可以优先使用它提供的结果选项;如果项目直接调用模型,则保留 token 级切片逻辑。两层 API 不要混着猜。

一张表排查“仍然带 prompt”

现象优先检查处理方向
输出从输入句子开始是否直接 decode 完整 sequencesdecoder-only 按有效输入长度切片
批量结果互相错位是否复用了第一行长度按 attention_mask 逐行计算
打开结构化返回后仍带输入是否误把 return_dict_in_generate 当裁剪开关仍然处理 sequences 的边界
pipeline 与底层结果不同是否混用了 pipeline 与 generate 的参数分别按对应 API 处理

结论

“只输出生成结果”的稳定做法是先辨认模型架构,再在 token 层处理边界。对 decoder-only,单条输入通常从 input_ids.shape[1] 开始切;对批量输入,要结合每行的 attention_mask;对 encoder-decoder,不要把 encoder 输入当成 decoder 输出前缀。最后再调用 tokenizer 解码,得到的文本才不会因为字符串替换而留下边界问题。

相关问题

max_length 和 max_new_tokens 有什么区别? max_new_tokens只计算新增 token,更适合限制生成长度;max_length描述完整序列长度,旧代码里更容易和输入长度混淆。

为什么生成结果有时多一个空格? token 合并和 tokenizer 的空格规则可能让解码后的文本出现自然的前后空白。应先完成 token 切片,再按业务需要处理首尾空白。

能不能用字符串 replace 删除 prompt? 不建议。prompt 可能在答案中再次出现,字符串替换也无法可靠处理 token 化后的空格、换行和特殊 token。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Holo4 这类计算机使用代理怎样划分工具权限Holo4 这类计算机使用代理怎样划分工具权限
上一篇
Holo4 这类计算机使用代理怎样划分工具权限
LoRA 适配器怎样与基础模型分离加载
下一篇
LoRA 适配器怎样与基础模型分离加载
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    932次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    937次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    1046次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    1016次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    844次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码