LMDeploy 服务端推理内容解析:reasoning_content 流式返回与自定义 Reasoning Parser 实战
发布时间:2026/9/27 21:48:12来源:尧图网络
人工智能大模型模型推理服务推理引擎本地部署模型量化【免费下载链接】lmdeployLMDeploy is a toolkit for compressing, deploying, and serving LLMs.项目地址https://gitcode.com/gh_mirrors/lm/lmdeploy点击查看免费下载本文以 LMDeploy 的推理输出解析能力为主线讲解如何为 DeepSeek R1、Qwen3、QwQ 等具备思考reasoning能力的模型启动api_server让服务端自动剥离thinking过程并通过 OpenAI 兼容接口的reasoning_content字段单独返回推理内容同时深入内置 parser 的注册与校验机制、多轮对话中的推理内容保留策略并给出自定义 reasoning parser 的完整实现路径。读完本文你将掌握从服务启动、客户端调用到协议级源码原理的完整闭环可直接应用于生产环境中的推理模型部署与二次开发。一、什么是 reasoning_content对于 DeepSeek R1 这类先思考再回答的推理模型模型输出天然被分为两部分不可见但可审计的推理过程通常包裹在think.../think标签内与最终答案。如果原样返回客户端需要自己解析标签、自行切割内容且推理过程混在content字段中会污染对话记录与展示逻辑。LMDeploy 在服务端解决了这一问题启动api_server时指定--reasoning-parser服务端即可按模型的协议标签实时解析生成流将推理内容与正式回答拆分并分别通过reasoning_content与content两个字段返回。这一能力在协议层已固化——DeltaMessage流式增量与完整响应对应的消息结构均定义了reasoning_content: str | None字段见 protocol.py、protocol.py客户端无需任何额外扩展即可消费。二、快速开始DeepSeek R1 示例1. 启动 api_server启动方式与普通模型完全一致仅需额外传入--reasoning-parserlmdeploy serve api_server deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B --reasoning-parser default该参数由lmdeploy/cli/utils.py中的ArgumentHelper.reasoning_parser注册见 utils.py取值必须是ReasoningParserManager中已注册的名称未指定时默认为None即不做推理拆分。参数最终在 serve.py 与 serve.py 两处被传递到服务端配置。2. 客户端调用服务启动后使用 OpenAI SDK 即可消费流式与非流式两种响应from openai import OpenAI openai_api_key Your API key openai_api_base http://0.0.0.0:23333/v1 client OpenAI( api_keyopenai_api_key, base_urlopenai_api_base, ) models client.models.list() model models.data[0].id messages [{role: user, content: 9.11 and 9.8, which is greater?}] # 流式每个 delta 中同时携带 reasoning_content 与 content response client.chat.completions.create(modelmodel, messagesmessages, streamTrue) for stream_response in response: print(reasoning content: , stream_response.choices[0].delta.reasoning_content) print(content: , stream_response.choices[0].delta.content) # 非流式一次性取回完整字段 response client.chat.completions.create(modelmodel, messagesmessages, streamFalse) reasoning_content response.choices[0].message.reasoning_content content response.choices[0].message.content print(reasoning_content:, reasoning_content) print(content:, content)流式场景下reasoning_content与content通常不会同时出现在同一个 delta 中生成处于推理阶段时仅reasoning_content有值进入正式回答后仅content有值客户端按字段逐段拼接即可还原完整输出。三、多轮对话中保留推理内容部分模型支持复用先前 assistant 轮次的推理内容典型代表是 Qwen3.8以及同族的 Qwen3 系列。若希望在下一轮对话中保留上一轮的思考过程需要两步配合构造请求时把上一轮的reasoning_content以role: assistant的消息原样追加进messages通过请求体的chat_template_kwargs传入preserve_thinking: True。messages.append({ role: assistant, reasoning_content: reasoning_content, content: content, }) messages.append({role: user, content: 请换一种方式解释这个结果。}) response client.chat.completions.create( modelmodel, messagesmessages, extra_body{chat_template_kwargs: {preserve_thinking: True}}, )需要说明的默认行为与代价不传preserve_thinking时是否保留历史推理由模型的聊天模板chat template决定。Qwen3.8 默认保留历史推理显式传False可移除较早轮次已完成推理的内容Token 成本保留的推理内容会成为输入提示词的一部分直接增加输入 Token 数量。长对话场景下若不限制历史长度推理内容会持续累积需结合上下文窗口规划保留策略。四、内置 reasoning parser 一览--reasoning-parser当前支持的注册名称如下名称即ReasoningParserManager注册表中的键源码见 reasoning_parser.py 及init.py注册名称适用模型推理模式起始条件源码位置defaultQwen3、QwQ、DeepSeek R1、Intern-S1 及兼容模型始终从推理模式开始reasoning_parser.pydeepseek-v3DeepSeek V3仅当enable_thinkingTrue时进入推理模式deepseek_v3_reasoning_parser.pydeepseek-v32/deepseek-v3.2DeepSeek V3.2两个别名thinkingTrue或enable_thinkingTrue时进入deepseek_v32_reasoning_parser.pydeepseek-v4DeepSeek V4与 V3.2 parser 相同的模式开关deepseek_v4_reasoning_parser.py几个关键差异值得注意defaultparser 使用think.../think协议。基类ReasoningParser中get_reasoning_open_tag()与get_reasoning_close_tag()的默认实现分别返回think与/thinkstarts_in_reasoning_mode()恒为True意味着只要启用该 parser服务端就认为生成从推理模式开始直到遇到闭合标签才切回普通内容DeepSeek V3 的行为与 Qwen3 默认行为不同enable_thinkingNone未显式开启时模型通常不输出推理部分因此deepseek-v3只在显式开启时进入推理模式旧名称映射与弃用警告qwen-qwq、intern-s1、deepseek-r1仍会生效但会被统一映射到default并产生弃用警告。该映射由validate_parser_names实现见 response_parser.pyLEGACY_REASONING_PARSER_NAMES定义于 reasoning_parser.pyGPT-OSS 不走通用 parserGPT-OSS 不使用注册的 reasoning parserLMDeploy 会为它自动选择专用的 OpenAI Harmony response parserGptOssResponseParser注册名为gpt-oss见 _openai_harmony.py因此对 GPT-OSS 无需也不能指定--reasoning-parser。五、服务端解析原理统一 Response Parser 状态机解析工作并非由 reasoning parser 单独完成。reasoning parser 只负责协议声明起止标签、是否从推理模式开始真正对流式/非流式响应做内容拆分的是统一的BaseResponseParser注册名为default见 response_parser.py。理解这一分层对自定义 parser 至关重要。1. 三个解析模式BaseResponseParser内部维护一个三态状态机见 response_parser.pyMODE_PLAIN普通内容区输出进contentMODE_REASONING推理区输出进reasoning_contentMODE_TOOL工具调用区输出为结构化的tool_callsreasoning 与 tool 可嵌套工具块结束后自动恢复被挂起的原通道。当请求的chat_template_kwargs中enable_thinking被显式设为False时推理区内容会被降级到content通道返回见 response_parser.py这保证了关闭思考语义在输出侧的一致性。2. 分块缓冲与跨 chunk 标签生成是逐 token 流式的协议标签可能被任意切分在相邻两个 chunk 中。_consume_plain/_consume_reasoning通过_longest_open_tag_prefix_suffix判断当前缓冲尾部是否为某个协议标签的前缀是则保留尾部、只吐安全前缀等待下一个 chunk 补全标签后再切换模式见 response_parser.py。因此无论标签多长、被切多碎解析都能保持正确。3. 推理 Token 统计服务端还维护了reasoning_tokens计数在推理起止标签的 token id 区间内累加 token 数见 response_parser.py使调用方可以精确掌握推理过程消耗的 token 量用于计费或用量审计。该统计依赖validate_tokenizer校验通过的标签 token id。六、自定义 reasoning parser当模型使用非标准协议例如自定义标签、特殊模式开关时可以自行注册 parser。1. 创建 parser 模块在lmdeploy/serve/parsers/reasoning_parser/目录下创建模块继承ReasoningParser并通过ReasoningParserManager.register_module注册# lmdeploy/serve/parsers/reasoning_parser/example_reasoning_parser.py from .reasoning_parser import ReasoningParser, ReasoningParserManager ReasoningParserManager.register_module(nameexample) class ExampleReasoningParser(ReasoningParser): 解析使用 reasoning.../reasoning 协议的模型。 def __init__(self, **kwargs): super().__init__(**kwargs) self.enable_thinking kwargs.get(enable_thinking) classmethod def get_reasoning_open_tag(cls) - str: return reasoning classmethod def get_reasoning_close_tag(cls) - str: return /reasoning def starts_in_reasoning_mode(self) - bool: return self.enable_thinking is not False三个需要实现的契约方法基类签名见 reasoning_parser.pyget_reasoning_open_tag()/get_reasoning_close_tag()声明协议起止标签starts_in_reasoning_mode()声明本次生成是否从推理模式开始。它接收的**kwargs来自请求级chat_template_kwargs含归一化后的enable_thinking/thinking见 response_parser.py因此可以根据开关动态决定起始模式。2. 在包初始化时导入还需在lmdeploy/serve/parsers/reasoning_parser/__init__.py中导入该模块确保 CLI 校验参数之前注册已完成ReasoningParserManager的注册表在包加载时填充import 即触发register_module装饰器from .example_reasoning_parser import ExampleReasoningParser # noqa: F4013. Tokenizer 校验服务启动时LMDeploy 会调用validate_tokenizer检查起止标签是否为模型 tokenizer 词表中的独立 Token实现见 reasoning_parser.py缺失任一标签会抛出RuntimeError并列出缺失项。因此示例中的reasoning需替换为模型实际使用的协议 Token若模型需要不同的校验逻辑例如标签由多个 token 组成、或需要额外检查请重写validate_tokenizer类方法。4. 启动服务lmdeploy serve api_server $MODEL_PATH --reasoning-parser example七、常见问题与注意事项指定不存在的 parser 名会直接报错validate_parser_names会在引擎启动前校验注册表见 response_parser.py避免在昂贵启动后才发现拼写错误。enable_thinking顶层字段正在弃用请求体顶层的enable_thinking将被逐步移除建议统一通过chat_template_kwargs传递chat_template_kwargs_from_request会把顶层旧字段归一化到内部 kwargs 并发出弃用警告见 response_parser.py。推理内容同样消耗输入 Token多轮保留的reasoning_content会作为提示词的一部分务必关注长对话的 token 累积。GPT-OSS 无需配置LMDeploy 自动为其选择 OpenAI Harmony 专用 parser用户不应再指定--reasoning-parser。历史命名迁移qwen-qwq、intern-s1、deepseek-r1虽仍可用但会产生弃用警告新代码请直接使用default。八、参考资料本文对应的原始指南api_server_reasoning.md英文版见 api_server_reasoning.md推理 parser 注册表与 default 实现reasoning_parser.pyDeepSeek 系列 parserdeepseek_v3_reasoning_parser.py、deepseek_v32_reasoning_parser.py、deepseek_v4_reasoning_parser.py统一响应解析器状态机与 token 统计response_parser.py协议字段定义protocol.pyCLI 参数接线utils.py、serve.py赞分享人工智能大模型模型推理服务推理引擎本地部署模型量化【免费下载链接】lmdeployLMDeploy is a toolkit for compressing, deploying, and serving LLMs.项目地址https://gitcode.com/gh_mirrors/lm/lmdeploy点击查看免费下载相关推荐LMDeploy 推理输出解析Reasoning OutputsAPI Server 端 reasoning_content 的完整实践指南LMDeploy 推理输出解析Reasoning OutputsAPI Server 端 reasoning_content 的完整实践指南 本文以 LM人工智能大模型模型推理服务推理引擎本地部署模型量化LMDeploy 对话服务 Parser 设计深度解析reasoning 与工具调用协议的流式解析架构LMDeploy 对话服务 Parser 设计深度解析reasoning 与工具调用协议的流式解析架构 本文基于 docs/zh_cn/advance/par人工智能大模型模型推理服务推理引擎本地部署模型量化Agno 中的 Gemini 推理实战thinking_budget、reasoning_content 与流式事件详解Agno 中的 Gemini 推理实战thinking_budget、reasoning_content 与流式事件详解 Agno 为 Google Gemi人工智能大模型AI AgentAgent 框架多智能体工具调用RAGAgent 工作流Agent 记忆上一篇Redwood 应用接入第三方 API 的完整实战从客户端直连到服务端 GraphQL 网关下一篇Blender终极贝塞尔曲线插件从新手到专家的完整指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网