PaddleSpeech 文本标点预测服务 text_api 模块深度解析与 RESTful 接口实战
【免费下载链接】PaddleSpeechEasy-to-use Speech Toolkit including Self-Supervised Learning model, SOTA/Streaming ASR with punctuation, Streaming TTS with text frontend, Speaker Verification System, End-to-End Speech Translation and Keyword Spotting. Won NAACL2022 Best Demo Award.项目地址: https://gitcode.com/gh_mirrors/pa/PaddleSpeech
PaddleSpeech 服务端(paddlespeech_server)内置了基于 HTTP 协议的文本处理能力,其中text_api模块负责对外暴露**标点预测(Punctuation Restoration / text task: punc)**的 RESTful 接口:接收一段无标点的中文文本,返回补全标点后的结果,可用于 ASR 转写文本的后期处理、字幕生成、聊天文本美化等场景。本文以 docs/source/api/paddlespeech.server.restful.text_api.rst 对应的 text_api.py 模块为切入点,结合请求/响应模型、引擎池、文本引擎、服务端配置与客户端实现,从接口契约到源码调用链给出完整讲解。读完本文,你将能够独立启动一个带标点预测能力的 PaddleSpeech 离线服务,并正确构造 HTTP 请求与解析响应。
text_api 模块在 PaddleSpeech 服务架构中的位置
PaddleSpeech 的服务端采用 FastAPI + Uvicorn 搭建,RESTful 层按语音任务拆分为多个独立的路由模块,text_api是其中之一。在 api.py 的setup_router中,根据启动配置传入的 api 列表动态挂载各路由:
elif api_name.lower() == 'text': _router.include_router(text_router)也就是说,只有当服务配置的engine_list中显式包含text_python时,text 路由才会被注册并对外提供标点预测能力(默认配置 application.yaml 中engine_list: ['asr_python', 'tts_python', 'cls_python', 'text_python', 'vector_python']已包含它)。
text_api模块本身非常精简,核心是一个APIRouter实例和两个接口函数(text_api.py):
| 方法 | 路径 | 作用 |
|---|---|---|
| GET | /paddlespeech/text/help | 返回接口说明与字段示例,便于探测服务是否可用 |
| POST | /paddlespeech/text | 提交待标点文本,返回补全标点后的结果 |
接口契约:请求体与响应体模型
请求体 TextRequest
标点预测的请求非常简单,只包含一个必填字段text(request.py):
class TextRequest(BaseModel): text: str该模型由 Pydantic 定义,FastAPI 会自动完成请求体的 JSON 校验与反序列化。一个合法的 POST 请求体示例:
{ "text": "我认为跑步最重要的就是给我带来了身体健康" }响应体 TextResponse
正常响应由三层结构组成(response.py):最外层包含success与code,中间message为描述信息,result中通过punc_text字段返回补全标点后的文本:
{ "success": true, "code": 200, "message": { "description": "success" }, "result": { "punc_text": "我认为跑步最重要的就是给我带来了身体健康。" } }异常响应 ErrorResponse
当请求处理失败时,接口返回统一的错误结构(response.py):
{ "success": false, "code": 509, "message": { "description": "Unknown error occurred." } }ErrorResponse只有success、code、message三层,不含result。接口的返回类型声明为Union[TextResponse, ErrorResponse](text_api.py),FastAPI 据此生成 OpenAPI 文档。
接口处理流程源码解读
/paddlespeech/text的 POST 处理函数内部逻辑分为三步(text_api.py),值得注意的一个细节是:该函数在源码中的命名为asr,这是历史遗留命名,但函数签名与行为完全服务于 text 任务,不影响接口使用。
- 提取请求文本:从
request_body.text取出原始字符串,并打印服务端日志。 - 从引擎池获取 text 引擎并执行推理:通过
get_engine_pool()拿到全局引擎池,按text键取出TextEngine实例,再包装成PaddleTextConnectionHandler调用run(text)完成一次完整的预处理—推理—后处理流程。 - 构造响应:若推理结果
punc_text为None(例如模型未输出有效标点),则回退为原始text原样返回,保证接口在任何情况下都有稳定的响应结构;随后按success/code/message/result四层结构封装 JSON 返回。
help接口则直接返回一个静态 JSON,其中result.punc_text字段标注为 "The punctuation text content",向调用方明示该服务返回的字段含义(text_api.py)。
异常与错误码映射
处理函数对异常做了两级兜底(text_api.py):
- 捕获
ServerBaseException:按异常携带的error_code与msg生成失败响应; - 兜底捕获
BaseException:统一映射为ErrorCode.SERVER_UNKOWN_ERR(值为 509)并打印完整 traceback 便于排查。
错误码枚举定义在 errors.py,failed_response会依据错误码自动填充对应的默认描述(errors.py):
| 错误码 | 常量 | 含义 |
|---|---|---|
| 200 | SERVER_OK | 成功 |
| 400 | SERVER_PARAM_ERR | 输入参数不合法 |
| 404 | SERVER_TASK_NOT_EXIST | 任务不存在 |
| 500 | SERVER_INTERNAL_ERR | 内部错误 |
| 502 | SERVER_NETWORK_ERR | 网络异常 |
| 509 | SERVER_UNKOWN_ERR | 未知错误 |
引擎池与 TextEngine 初始化链路
RESTful 层本身不持有模型,模型统一由引擎池管理。init_engine_pool遍历配置中的engine_list,将<task>_<engine_type>拆分为引擎名与类型,通过EngineFactory创建引擎并调用init(engine_pool.py)。因此text_python会被解析为engine='text'、engine_type='python',这也是text_api中engine_pool['text']能取到TextEngine的原因。
TextEngine.init(text_engine.py)完成以下工作:
设备设置:优先使用配置中的
device(如gpu:0或cpu),缺省时回退到paddle.get_device(),并调用paddle.set_device生效;失败时打印错误日志并返回False,服务启动流程随即中断。执行器创建:实例化
TextServerExecutor(它是 CLI 层TextExecutor的薄包装,见 infer.py)。模型加载分流:依据
config.model_type是否包含fast关键字选择两条初始化路径:- 含
fast(如ernie_linear_p3_wudao_fast类模型):走_init_from_path_new,使用ErnieLinear(**config["model"])从cfg_path直接构建模型并从ckpt_path加载权重,tokenizer 使用ernie-3.0-mini-zh(infer.py); - 不含
fast(如默认的ernie_linear_p3_wudao):走_init_from_path,通过task_resource自动解析模型资源,tokenizer 使用ernie-1.0(infer.py)。
无论哪条路径,都会从
vocab_file逐行读取标点符号表到self._punc_list,供后处理阶段把模型输出的标签映射回标点字符。- 含
PaddleTextConnectionHandler:一次标点预测的完整推理
PaddleTextConnectionHandler负责处理每个请求(text_engine.py),构造时从执行器中取出task、model、tokenizer、_punc_list,并用两个OrderedDict暂存中间结果。对外入口run(text)串联三步:
1. 预处理 preprocess
只支持task == 'punc',其余任务抛出NotImplementedError(text_engine.py):
- 调用
TextExecutor._clean_text清洗文本:先lower()转小写,再用正则剔除除字母、数字、汉字以外的字符,并删除输入中已存在的标点(_punc_list中除首项外的全部字符),防止干扰模型判断(infer.py); - 断言清洗后文本非空,空文本直接视为非法输入;
- 调用 tokenizer 对逐字列表做分词,
return_length=True且is_split_into_words=True,得到input_ids、token_type_ids(seg_ids)与seq_len,存入_inputs。
2. 模型推理 infer
将input_ids、seg_ids转为 Paddle Tensor 并增加 batch 维度,送入ErnieLinear模型得到logits,取最后一个维度上的argmax得到每个 token 的标点类别预测(text_engine.py)。整个过程通过@paddle.no_grad()关闭梯度计算。
3. 后处理 postprocess
把预测标签还原为带标点的文本(text_engine.py):
- 用
convert_ids_to_tokens把input_ids还原为 token 序列,同时截取对应的预测标签(去掉首尾的特殊 token); - 逐 token 拼接字符,当标签
l != 0(即非"无标点"类)时,追加标点:fast 模型使用_punc_list[l - 1](因新训练流程在_punc_list头部插入了 0 占位),非 fast 模型直接使用_punc_list[l](infer.py); - 最终返回形如"我认为跑步最重要的就是给我带来了身体健康。"的字符串。
服务端配置:application.yaml 中的 text_python
标点预测引擎的配置段位于 application.yaml:
################################### Text ######################################### ################### text task: punc; engine_type: python ####################### text_python: task: punc model_type: 'ernie_linear_p3_wudao' lang: 'zh' sample_rate: 16000 cfg_path: # [optional] ckpt_path: # [optional] vocab_file: # [optional] device: # set 'gpu:id' or 'cpu'各字段含义与作用:
| 配置项 | 说明 |
|---|---|
task | 文本任务类型,当前仅支持punc(标点预测) |
model_type | 模型标识,默认ernie_linear_p3_wudao;可选ernie_linear_p7_wudao及带fast后缀的快速版本,决定初始化路径与 tokenizer 选择 |
lang | 语言,默认zh,CLI 执行器支持zh/en两个取值(infer.py) |
sample_rate | 采样率,默认 16000(文本任务实际不消费音频,该字段为统一配置格式保留) |
cfg_path/ckpt_path/vocab_file | 模型配置、权重与标点词表路径;均标注为 optional,缺省时由task_resource按model_type-task-lang自动下载并定位预训练资源(infer.py) |
device | 推理设备,写gpu:0或cpu;留空则使用paddle.get_device() |
启动服务时使用:
paddlespeech_server start --config_file ./conf/application.yaml若在容器环境中客户端无法访问服务,可将配置中的host从0.0.0.0改为本机实际 IP。可用paddlespeech_server stats --task text查看该任务支持的全部模型清单。
客户端调用实战
命令行方式(推荐)
仓库提供的示例脚本 text_client.sh 展示了最简调用:
paddlespeech_client text --server_ip 127.0.0.1 --port 8090 --input 今天的天气真好啊你下午有空吗我想约你一起去吃饭更完整的用法(见 README_cn.md):
paddlespeech_client text --server_ip 127.0.0.1 --port 8090 --input "我认为跑步最重要的就是给我带来了身体健康"客户端参数定义在TextClientExecutor(paddlespeech_client.py):
| 参数 | 默认值 | 是否必填 | 说明 |
|---|---|---|---|
--server_ip | 127.0.0.1 | 否 | 服务端 IP |
--port | 8090 | 否 | 服务端口 |
--input | 无 | 是 | 待标点预测的文本内容 |
期望输出(服务端返回punc_text,客户端直接打印文本并统计响应耗时):
[2022-05-09 18:19:04,397] [ INFO] - The punc text: 我认为跑步最重要的就是给我带来了身体健康。 [2022-05-09 18:19:04,397] [ INFO] - Response time 0.092407 s.首次调用需要下载并加载模型资源,响应时间会略长,属正常现象。
Python API 方式
同样复用TextClientExecutor(paddlespeech_client.py):
from paddlespeech.server.bin.paddlespeech_client import TextClientExecutor textclient_executor = TextClientExecutor() res = textclient_executor( input="我认为跑步最重要的就是给我带来了身体健康", server_ip="127.0.0.1", port=8090) print(res) # 我认为跑步最重要的就是给我带来了身体健康。从源码可以看到,TextClientExecutor.__call__内部构造url = 'http://' + server_ip + ":" + str(port) + '/paddlespeech/text',以{"text": input}作为 JSON 请求体发起requests.post,再解析响应中的result.punc_text返回。这一过程与 RESTful 层text_api的接口定义严格对应,也可直接用任意 HTTP 工具(如 curl)以同样方式调用:
curl -X POST http://127.0.0.1:8090/paddlespeech/text \ -H "Content-Type: application/json" \ -d '{"text": "今天天气真好啊"}'使用场景与边界说明
标点预测接口最常见的落地场景是与 ASR 服务串联:ASR 输出的转写文本通常没有标点,将文本送入/paddlespeech/text后即可获得可读性更强的带标点文本,便于生成字幕、会议纪要与对话日志。在使用中需注意以下前提与限制:
- 服务端与客户端通过 HTTP 通信,
engine_list中必须包含text_python才会注册该接口; - 输入文本会被
_clean_text清洗(小写化、剔除标点与非中英数字符),清洗后为空会触发断言错误并返回失败响应; - 模型加载依赖网络下载预训练资源或本地配置
cfg_path/ckpt_path/vocab_file,首次启动需保持网络可达; - 推理设备通过
device配置控制,GPU 资源紧张时可显式设为cpu; - 相关模块的单元测试与集成验证集中在 tests/unit/server 目录,可作为二次开发与回归验证的参考。
小结
paddlespeech.server.restful.text_api是 PaddleSpeech 离线服务体系中"文本处理"能力的 HTTP 出口,接口设计遵循统一的success/code/message/result四层结构,内部通过引擎池 +TextEngine+PaddleTextConnectionHandler完成从文本清洗、ERNIE 序列标注到标点还原的完整链路。理解这一模块后,你既可以基于paddlespeech_client快速接入标点预测能力,也可以参照 text_api.py 的写法,在 api.py 的路由框架内扩展自己的文本类服务接口。
【免费下载链接】PaddleSpeechEasy-to-use Speech Toolkit including Self-Supervised Learning model, SOTA/Streaming ASR with punctuation, Streaming TTS with text frontend, Speaker Verification System, End-to-End Speech Translation and Keyword Spotting. Won NAACL2022 Best Demo Award.项目地址: https://gitcode.com/gh_mirrors/pa/PaddleSpeech
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考