☰
PaddleNLP Taskflow 文本生成任务(text_generation)API 深度解析:基于 CPM 中文模型的问答与写诗实战
2026/10/14 22:09:17 网站建设 项目流程
  • 人工智能
  • 大模型
  • 预训练
  • 微调
  • LoRA
  • RLHF
  • 强化学习
  • 分布式训练

【免费下载链接】PaddleNLP

Easy-to-use and powerful LLM and SLM library with awesome model zoo.

项目地址:https://gitcode.com/gh_mirrors/pa/PaddleNLP
点击查看免费下载

本篇文章围绕 PaddleNLPpaddlenlp.taskflow.text_generation模块及其 API 参考页(paddlenlp.taskflow.text_generation.rst)展开,完整剖析 Taskflow 框架中文本生成任务的类设计、预置模型、few-shot 构造、静态图推理链路与结果解码机制。读完本文,你将掌握TextGenerationTask的内部工作原理,并能在实际项目中直接使用生成式问答(question_answering)与智能写诗(poetry_generation)两个开箱即用的一键预测能力。

一、text_generation 模块在 Taskflow 中的定位

paddlenlp.taskflow.text_generation是 PaddleNLP Taskflow 一键预测体系中的文本生成任务实现模块。API 参考文档 paddlenlp.taskflow.text_generation.rst 通过 Sphinx 的automodule指令自动生成该模块的成员文档,其技术主体即 text_generation.py 中的TextGenerationTask类。

在 Taskflow 的注册表 taskflow.py 中,文本生成能力被拆分为两个面向不同场景的上层任务,均由该模块提供基类实现:

任务名调用方式任务类注册行号
生成式问答Taskflow("question_answering")QuestionAnsweringTasktaskflow.py#L164-L175
智能写诗Taskflow("poetry_generation")PoetryGenerationTasktaskflow.py#L140-L151

两者共用同一个预置中文生成模型gpt-cpm-large-cn,并都继承自TextGenerationTask,因此从 question_answering.py 与 poetry_generation.py 的源码可以看到,两个子类本身几乎为空实现,仅定义各自任务的usage示例文本与模型下载 URL,全部逻辑沉淀在基类中——这正是TextGenerationTask作为"一次实现、多任务复用"的模块价值的体现。

二、TextGenerationTask 类设计与初始化流程

TextGenerationTask继承自 Taskflow 的抽象基类Task(定义于 task.py),类注释明确说明其职责是"predict the question or chinese poetry"(生成式问答或中文诗歌续写)。构造函数 text_generation.py#L43-L54 的关键流程如下:

  1. 默认走静态图推理:self._static_mode = True,优先使用 Paddle Inference 静态模型执行预测,以获得更好的部署性能。
  2. 下载预置模型参数:当处于静态模式时,调用download_file从 URLS 字典 中声明的地址下载gpt-cpm-large-cn_params.tar,并以 md5 值5aad6f81053cfdbba4797f044fcf66d1做完整性校验;文件会被解压到~/.paddlenlp/taskflow/下的任务路径中(路径拼装逻辑见 task.py#L79-L85)。
  3. 构建推理模型或加载静态模型:静态模式调用_get_inference_model()读取/转换 Paddle Inference 模型;动态模式则调用_construct_model构建动态图模型。
  4. 构建 Tokenizer:见下文"分词器选择"小节。
  5. 记录生成任务类型:self.kwargs["generation_task"] = task,这是后续 few-shot 模板选择的关键依据。

2.1 分词器选择(_construct_tokenizer)

text_generation.py#L71-L80 中,分词器按模型名分派:

  • gpt-cpm-large-cn→GPTChineseTokenizer(基于 SentencePiece + jieba 的中文 GPT 分词器,定义于 tokenizer.py#L87);
  • 其他模型 → 通用GPTTokenizer。

GPTChineseTokenizer值得注意的细节:它内部用 jieba 对中文文本进行粗切分,再把空格与换行分别映射为特殊字符(" \n"→"\u2582\u2583"),最后由 SentencePiece 模型完成子词编码。其eol_token默认取"\u2583"(换行 token),对应的eol_token_id属性(tokenizer.py#L156-L160)会被 GPT 解码模型用作"终止生成"的判定信号。

2.2 模型构建(_construct_model)

text_generation.py#L62-L69 在动态模式下构造GPTForGreedyGeneration.from_pretrained(self.model, max_predict_len=32),即最大预测长度固定为 32 个 token,并置为eval()模式。GPTForGreedyGeneration是定义于 modeling.py#L1366 的贪心解码专用模型,我们将在第五节详细展开。

2.3 静态图输入规格(_construct_input_spec)

text_generation.py#L56-L60 声明了静态图转换时的输入规格:

self._input_spec = [paddle.static.InputSpec(shape=[None, None], dtype="int64", name="token_ids")]

即模型只接收一个形状为[batch_size, seq_len]的int64型 token id 矩阵作为输入,这与后文_run_model中通过self.input_handles[0].copy_from_cpu(ids)喂入的数据完全对应。

三、基于 CPM 的预置模型:gpt-cpm-large-cn

文本生成任务唯一预置模型为gpt-cpm-large-cn。根据 GPT 模型汇总表 的官方说明,该权重为中文 GPT 模型,结构为32 层、2560 hidden、32 头、约 2.6B 参数,在中文语料上预训练。官方文档在 taskflow.md 中将其描述为"最大中文开源 CPM 模型",用于完成问答与写诗两个生成任务。

模型权重与 SentencePiece 词表资源分别在 text_generation.py#L26-L31 的URLS与 tokenizer.py#L119-L127 的pretrained_resource_files_map中登记,均通过from_pretrained/download_file机制自动获取。

四、核心推理链路:_preprocess → _run_model → _postprocess

与其他 Taskflow 任务一致,TextGenerationTask通过 task.py#L567-L571 的__call__把输入依次送入预处理、模型运行、后处理三个抽象方法,完成"原始文本 → 模型结果 → 任务结果"的端到端转换。

4.1 预处理:few-shot 模板与批处理(_preprocess)

text_generation.py#L82-L126 实现了预处理,包含三个关键步骤:

(1)输入合法性检查:调用基类的_check_input_text(task.py#L434-L452),支持单个字符串或字符串列表,空文本会被拒绝。

(2)few-shot 模板构造:核心函数select_few_shot_input(text_generation.py#L93-L102)按generation_task选择不同的前缀模板:

  • 生成式问答(question_answering):

    问题:中国的首都是哪里?答案:北京。 问题:{} 答案:
  • 智能写诗(poetry_generation):

    默写古诗: 大漠孤烟直,长河落日圆。 {}

    generation_task的取值直接来自构造时写入的self.kwargs["generation_task"](即调用 Taskflow 时的任务名),若传入question_answering、poetry_generation之外的值会抛出ValueError("The generation task must be question or poetry")。随后每个输入文本通过pre_input.format(input_text)拼入模板,再经 tokenizer 编码为input_ids,并记录序列长度len(ids)。

(3)批处理与 Padding:通过 batchify_fn 将同一个 batch 内的样本统一处理:

batchify_fn = lambda samples, fn=Tuple( Pad(axis=0, pad_val=0, dtype="int64"), Stack(dtype="int64"), # seq_len ): fn(samples)

其中Pad(axis=0, pad_val=0)沿序列维度(axis=0,即第 0 维为序列长度)用 0 补齐到 batch 内最大长度,Stack负责堆叠序列长度张量。batch 的划分由batch_size控制,默认值为 1(从self.kwargs读取),最终输出字典中包含text(原始输入)与data_loader(分好 batch 的样例列表)。

4.2 模型运行:静态图 Paddle Inference(_run_model)

text_generation.py#L128-L144 以static_mode_guard()上下文(utils.py#L116-L120,内部先paddle.enable_static()后paddle.disable_static())切换到静态图模式,逐 batch 执行:

self.input_handles[0].copy_from_cpu(ids) # 把 batch token ids 拷贝进输入句柄 self.predictor.run() # 运行 Paddle Inference 预测器 result = self.output_handle[0].copy_to_cpu().tolist()

预测器本身由基类_prepare_static_mode(task.py#L216-L262)按设备类型配置:CPU 上会enable_mkldnn()、GPU 上enable_use_gpu(100, device_id),同时统一开启 IR 优化、新执行器与内存优化。推理得到的是生成 token id 序列,连同每条样本的真实输入长度lens一起存入inputs,供后处理使用。

4.3 后处理:token id 解码为文本(_postprocess)

text_generation.py#L146-L158 完成最终解码:

single_result["text"] = inputs["text"][index] # 原始输入 single_result["answer"] = self._tokenizer.convert_ids_to_string( preds[index][seq_len:-1] # 截掉输入部分,丢弃最后的终止符 )

关键点在于preds[index][seq_len:-1]的切片逻辑:

  • preds[index]是模型输出的完整 token id 序列(输入 + 生成部分);
  • seq_len是当前样本的输入长度,preds[index][seq_len:-1]只保留新生成的 token;
  • 末尾的-1丢弃最后一个 token——它通常是eol_token_id(换行终止符)。

最终每条样本返回{"text": 原问题/上句, "answer": 生成的答案/下句}结构的字典,批量输入则返回字典列表。

五、底层解码机制:GPTForGreedyGeneration

TextGenerationTask的文本生成能力最终由 GPTForGreedyGeneration 承担。类注释明确指出它"use the greedy strategy and generate the output sequence with highest probability"(贪心策略,逐步生成概率最高的 token)。

其forward(modeling.py#L1434-L1458)的循环结构清晰展示了贪心解码过程:

  1. 对输入input_ids做一次前向,得到 logits 与cached_kvs;
  2. 取output[:, -1, :](最后一个位置的 logits),paddle.argmax得到当前步最可能的 tokennid,拼接到src_ids;
  3. 以nid为输入、携带past_key_values=cached_kvs继续前向(即KV Cache 增量解码,避免重复计算已生成部分);
  4. 循环直到生成长度达到max_predict_len(此处为 32),或当前 token 等于self.eol_token_id(换行符,对应中文 CPM 模型的"\u2583")提前终止。

从 modeling.py#L1416-L1432 还可以看到,语言模型头直接复用word_embeddings.weight做paddle.matmul(..., transpose_y=True),即典型的tied embedding / weight tying设计——输出词表概率分布由嵌入矩阵转置点乘得到。

六、实战:生成式问答与智能写诗

Taskflow 官方文档 taskflow.md 以及 question_answering.py、poetry_generation.py 中的usage文档字符串给出了可直接运行的官方示例。

6.1 生成式问答

from paddlenlp import Taskflow qa = Taskflow("question_answering") # 单条输入 qa("中国的国土面积有多大?") # [{'text': '中国的国土面积有多大?', 'answer': '960万平方公里。'}] # 批量输入(多条样本一次推理,平均速度更快) qa(["中国国土面积有多大?", "中国的首都在哪里?"]) # [{'text': '中国国土面积有多大?', 'answer': '960万平方公里。'}, # {'text': '中国的首都在哪里?', 'answer': '北京。'}]

6.2 智能写诗

from paddlenlp import Taskflow poetry = Taskflow("poetry_generation") # 单条输入:给定上句,续写下句 poetry("林密不见人") # [{'text': '林密不见人', 'answer': ',但闻人语响。'}] # 批量输入 poetry(["林密不见人", "举头邀明月"]) # [{'text': '林密不见人', 'answer': ',但闻人语响。'}, # {'text': '举头邀明月', 'answer': ',低头思故乡。'}]

示例中模型的输出实际上是在"问题 + 答案模板"或"古诗续写模板"基础上做续写,再由_postprocess剥离输入前缀与终止符得到纯答案文本。

6.3 可配置参数

根据 taskflow.md 的说明与源码实现,本任务主要支持以下参数:

参数默认值说明
batch_size1批处理大小,批量输入多条样本可提升推理吞吐,请结合机器内存/显存调整
modelgpt-cpm-large-cn任务使用的模型名,不传则使用注册表默认值
task_pathNone自定义本地模型路径,传入后跳过自动下载,改用用户模型
device_id0GPU 等设备 ID,由Taskflow统一透传

其中batch_size在 text_generation.py#L90 从self.kwargs读取;model与task_path的默认/自定义逻辑位于 taskflow.py#L834-L867 与 task.py#L79-L85。任务注册表同时记录了task_flag(如question_answering-gpt-cpm-large-cn)与task_priority_path(gpt-cpm-large-cn),前者用于资源下载校验,后者决定本地缓存目录布局。

七、从源码理解任务扩展方式

虽然TextGenerationTask当前只服务问答与写诗两个场景,但模块结构天然支持扩展新的生成式任务:

  1. 子类化TextGenerationTask:像QuestionAnsweringTask(question_answering.py#L42)与PoetryGenerationTask(poetry_generation.py#L41)一样,只需提供usage与模型URLS;
  2. 在TASKS注册表登记:在 taskflow.py#L48 的TASKS字典中新增任务名,指向任务类、task_flag与可选task_priority_path;
  3. 在select_few_shot_input中补充模板:在 text_generation.py#L93-L102 的模板选择逻辑中为新任务增加 few-shot 前缀(注意需同步放开 L95-L96 的任务名校验白名单)。

由此可见,few-shot 模板 + 通用 GPT 续写模型的组合是文本生成任务可复用的核心范式:模型本身不区分任务,任务语义全部由输入模板编码。

八、小结

paddlenlp.taskflow.text_generation模块以TextGenerationTask为统一基类,封装了"静态图推理优先 + CPM 中文生成模型 + few-shot 模板 + 贪心解码 + 结果解码"的完整文本生成链路,并向上派生出question_answering(生成式问答)与poetry_generation(智能写诗)两个开箱即用的 Taskflow 任务。对于开发者而言,既可以直接调用Taskflow完成中文问答与古诗续写,也可以参照 text_generation.py、question_answering.py 的写法快速扩展新的生成式应用场景。相关官方示例与参数说明还可进一步参考 docs/zh/model_zoo/taskflow.md 与 GPT 模型汇总。

  • 人工智能
  • 大模型
  • 预训练
  • 微调
  • LoRA
  • RLHF
  • 强化学习
  • 分布式训练

【免费下载链接】PaddleNLP

Easy-to-use and powerful LLM and SLM library with awesome model zoo.

项目地址:https://gitcode.com/gh_mirrors/pa/PaddleNLP
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询