1. 项目概述当大模型“思考”时我们能否让它“多线程”工作如果你用过ChatGPT、Claude或者国内的文心一言、通义千问这类大语言模型一定对那个“一个字一个字往外蹦”的生成过程印象深刻。无论是写代码、创作故事还是回答复杂问题模型都像一个深思熟虑的作家必须写完上一句才能构思下一句。这种“顺序解码”的方式是当前绝大多数LLM大语言模型生成文本的默认模式技术上称为“自回归生成”。但仔细想想这真的符合人类的思考方式吗当我们被问到“请写一篇关于人工智能对社会影响的短文并给出三个正面和三个负面例子”时我们的大脑并不会先想好标题再想第一段然后第二段……我们很可能会先在大脑中快速勾勒出一个“骨架”哦需要先定义AI然后分正面和负面两大块正面可能包括医疗、效率、娱乐负面可能涉及就业、隐私、伦理。这个“骨架”几乎是瞬间成型的然后我们再往里面填充血肉——具体的例子和论述。这个过程是并行的、结构化的。“Skeleton-of-Thought”SoT直译为“思维骨架”其核心思想正是借鉴了人类的这种高效思考模式。它不再强迫模型严格地从左到右、逐词生成而是引导模型先快速构建一个回答的“高层结构”或“骨架”然后并行地、独立地去生成这个骨架中各个部分的具体内容。简单来说就是把一个漫长的“顺序写作”任务拆解成一个“先列提纲再多人分工同时撰写不同章节”的并行任务。我最初接触到这个想法是在实际部署大模型API服务时。面对高并发请求即使模型本身推理速度很快但每个请求因为要顺序生成几百个token词元整体响应时间Time to First Token, TTFT 和 Time per Output Token, TPOT叠加起来用户体验和系统吞吐量就成了大问题。SoT的出现就像是为大模型的文本生成引擎装上了一台“涡轮增压器”它不改变引擎本身模型权重而是优化了“燃油喷射”和“进气”的流程从而在保持输出质量的同时显著提升生成速度。这项技术特别适合那些回答具有清晰结构性的场景比如问答与解释“解释光合作用的过程”、“列举Python的五个主要特性”。对比与分析“比较React和Vue.js的优缺点”、“分析电动汽车和燃油车的市场前景”。步骤与指南“如何重置路由器”、“烹饪一道番茄炒蛋的步骤”。创作与规划“为一个科幻小说写故事大纲”、“制定一份一周健身计划”。对于开发者、研究者和任何需要大规模、低成本调用大模型API的用户来说SoT意味着更快的响应、更低的延迟和更高的吞吐量。它不是在追求“魔改”模型以挤出最后一点精度而是在工程和算法层面对现有庞大模型资源进行一次极其聪明的“调度优化”。接下来我们就深入拆解这个“思维骨架”是如何被构建并驱动模型并行工作的。2. 核心原理拆解从“串行讲故事”到“并行填框架”要理解SoT我们必须先看清它要解决的核心矛盾大模型强大的“思考”能力与低效的“表达”方式之间的矛盾。2.1 自回归解码的瓶颈为什么模型“说话”慢当前主流LLM如GPT、LLaMA系列都采用Transformer的解码器架构。在生成文本时它们的工作流程是这样的给定一个输入提示词模型计算出第一个词的概率分布我们根据某种策略如贪心搜索、核采样选出一个词。将这个生成的词追加到输入后面形成新的输入序列。模型基于这个新的、更长的序列计算下一个词的概率分布再选出一个词。重复步骤2和3直到生成结束标记或达到最大长度。这个过程是严格自回归的即每一步的生成都依赖于之前生成的所有词。这带来了两个主要瓶颈计算无法并行生成第N个词时必须等第N-1个词生成完毕并输入模型后才能开始计算。这使得GPU强大的并行计算能力在生成阶段无法被充分利用大部分计算单元在等待。内存访问频繁每次生成一个词都需要将整个不断增长的序列Key-Value缓存加载到GPU显存中进行注意力计算。随着生成文本变长内存带宽逐渐成为限制速度的关键因素即所谓的“内存墙”。这就好比一个厨师必须切完西红柿才能打鸡蛋打完鸡蛋才能开火全程只有一个灶台在工作。SoT的思路是能不能让厨师先快速规划好“番茄炒蛋、凉拌黄瓜、米饭”这三道菜的工序然后同时开三个灶台来炒菜、拌菜、煮饭2.2 SoT的两阶段范式骨架构建与并行填充SoT将传统的单一路径生成解耦为两个清晰阶段第一阶段骨架生成在这个阶段模型的任务不是生成具体内容而是生成一个关于“如何组织答案”的元描述即“骨架”。这个骨架通常是一系列简短的、指示性的句子或短语。提示词工程这是SoT成功的关键。我们需要设计一个特殊的“骨架提示”引导模型进行高层规划。例如在原始提示后追加“请先为你的回答列出一个简要的提纲用‘1.’, ‘2.’, ‘3.’这样的编号列出主要部分每个部分用一句话概括核心点。提纲之后再展开详细内容。”模型行为在这个阶段模型以“元认知”的方式运行。它理解自己被要求先规划再执行。生成的骨架长度很短可能只占最终答案的5%-10%。例如对于问题“解释机器学习中的过拟合”骨架可能是“1. 定义过拟合现象。2. 分析过拟合产生的原因。3. 列举防止过拟合的常见方法。4. 总结。”速度优势由于骨架非常简短这个阶段的自回归生成过程很快延迟很低。第二阶段内容并行填充拿到骨架后系统将每个骨架点如“1. 定义过拟合现象”与原始问题组合形成多个独立的子问题。例如子问题1: “解释机器学习中的过拟合。首先请详细定义过拟合现象。”子问题2: “解释机器学习中的过拟合。接着请详细分析过拟合产生的原因。”……然后这些子问题被同时送入模型或模型的多个实例进行生成。因为每个子问题的生成是独立的不依赖于其他子问题的结果所以它们可以完全并行。技术实现在拥有多GPU卡或支持批量推理的推理服务器上可以将这些子问题组成一个批处理batch一次性提交给模型。模型会并行计算所有子问题的答案。质量保障每个子问题的生成仍然是自回归的保证了单个片段内的语言连贯性和逻辑性。由于每个片段都基于完整的原始问题和具体的骨架点内容不会偏离主题。注意这里的“并行”指的是任务级别的并行即多个独立的文本生成任务同时进行。它并非改变了Transformer模型内部计算下一个token的机制那仍然是顺序的而是通过组织任务的方式让GPU能够同时处理多个独立的生成序列从而压榨硬件利用率。2.3 与传统加速技术的区别SoT与一些常见的LLM加速技术有本质区别投机解码需要一个更小的“草稿模型”快速生成多个候选token再由大模型进行验证。它加速的是单个序列的生成。SoT则通过改变任务结构来实现并行。模型量化/蒸馏这些方法直接改变模型本身缩小尺寸、降低精度可能会损失一定的输出质量。SoT是一种“无损”的推理方法不修改模型权重理论上不影响模型的内在能力。仅解码器优化如PagedAttentionvLLM采用主要优化的是KV缓存的内存管理提高吞吐量。SoT可以与这些优化结合从任务编排层面进一步提速。SoT的核心创新在于它跳出了“优化单序列生成”的思维定式转而思考“如何将单序列任务重构为可并行化的多序列任务”。这需要对模型能力能否生成高质量骨架和工程架构如何高效调度并行任务有深入的理解。3. 实现方案与实操要点理解了原理我们来看看如何亲手实现一个SoT流程。这里我将提供一个基于流行开源框架如LangChain、vLLM和通用Python代码的实操方案。我们假设使用一个开源的LLM如Qwen2.5-7B-Instruct和vLLM作为推理引擎。3.1 系统架构设计一个完整的SoT系统通常包含以下组件骨架生成器接收用户原始查询调用LLM生成骨架。骨架解析器将LLM返回的文本解析成结构化的骨架点列表。任务调度器根据骨架点列表构造并行子查询并管理向推理引擎的批处理请求。并行推理引擎支持高效批处理推理的LLM服务端如vLLM、TGI。结果组装器接收所有并行生成的结果片段按照骨架顺序拼接成最终答案。用户查询 | v [骨架生成器] - 调用LLM生成骨架文本 | v [骨架解析器] - 解析为列表[点1, 点2, ...] | v [任务调度器] - 构造子查询批处理 [查询点1, 查询点2, ...] | v [并行推理引擎 vLLM] - 并行生成结果 [结果1, 结果2, ...] | v [结果组装器] - 按顺序拼接 - 最终答案3.2 关键步骤详解与代码示例步骤一环境准备与模型加载首先我们需要部署一个支持高效批处理的推理引擎。这里以vLLM为例。# 安装vLLM pip install vllm # 启动一个vLLM服务这里以本地运行为例生产环境需部署为服务 # 此命令会在本地启动一个API服务器加载Qwen2.5-7B模型 python -m vllm.entrypoints.openai.api_server \ --model Qwen/Qwen2.5-7B-Instruct \ --served-model-name qwen2.5-7b \ --max-model-len 8192 \ --tensor-parallel-size 1 # 根据你的GPU数量调整步骤二实现骨架生成与解析这是SoT的“大脑”。我们需要精心设计提示词并可靠地解析模型的输出。import openai # vLLM兼容OpenAI API协议 import re # 配置客户端指向本地vLLM服务 client openai.OpenAI( api_keytoken-abc123, # vLLM默认token可自定义 base_urlhttp://localhost:8000/v1 ) def generate_skeleton(user_query: str) - list: 根据用户查询生成回答骨架。 skeleton_prompt f 你是一个擅长结构化思考的助手。请按照以下步骤回答用户的问题 1. 首先为你的回答列出一个清晰的提纲骨架。这个提纲应该涵盖回答的所有关键部分。 2. 提纲的每一行都应该是一个完整的句子或短语明确指示该部分要阐述的内容。 3. 请使用数字编号如1., 2., 3.来列出骨架点。 用户问题{user_query} 现在请只输出提纲部分不要输出任何其他解释或详细内容。 提纲 try: response client.chat.completions.create( modelqwen2.5-7b, messages[{role: user, content: skeleton_prompt}], max_tokens150, # 骨架不需要太长 temperature0.1, # 低温度确保骨架稳定、结构化 stop[\n\n] # 可能的中止符防止生成额外内容 ) skeleton_text response.choices[0].message.content.strip() # 解析骨架文本提取编号点 # 使用正则表达式匹配 1. xxx, 2. xxx 这样的模式 points re.findall(r^\d\.\s*(.)$, skeleton_text, re.MULTILINE) if not points: # 如果正则匹配失败尝试按行分割并清理 points [line.strip() for line in skeleton_text.split(\n) if line.strip()] # 移除可能残留的编号 points [re.sub(r^\d\.\s*, , p) for p in points] return points except Exception as e: print(f骨架生成失败: {e}) # 降级策略如果生成失败返回一个简单的默认骨架 return [概述, 详细分析, 总结] # 测试骨架生成 query 请详细解释什么是区块链技术它的核心优势是什么以及面临的主要挑战。 skeleton generate_skeleton(query) print(生成的骨架, skeleton) # 可能输出[区块链技术的基本定义与原理, 区块链的核心优势分析, 区块链面临的主要挑战与问题, 总结与展望]实操心得骨架提示词的设计需要反复调试。不同的模型对提示词的敏感度不同。对于Qwen、ChatGLM等国内模型可能需要更符合中文习惯的提示比如“请首先给出回答的要点大纲”。temperature参数在骨架生成阶段建议设低如0.1-0.3以确保生成的结构稳定、可预测。一定要编写健壮的解析逻辑并准备好降级方案如返回默认骨架因为模型输出可能存在格式波动。步骤三并行任务调度与推理这是SoT的“肌肉”。我们将骨架点转化为并行任务并利用vLLM的批处理接口一次性提交。def parallel_generate_with_skeleton(user_query: str, skeleton_points: list) - list: 根据骨架点并行生成每个部分的内容。 # 1. 构造每个骨架点的完整提示 sub_prompts [] for point in skeleton_points: # 这里可以设计更精细的提示引导模型围绕该点展开 prompt f 请基于以下用户问题详细阐述“{point}”这一部分。 请确保你的回答内容聚焦、完整且是整体回答的一部分。 用户问题{user_query} 现在请详细阐述【{point}】 sub_prompts.append(prompt) # 2. 准备批量请求 # vLLM的OpenAI接口支持通过多个独立的ChatCompletion请求模拟批处理 # 但更高效的方式是直接使用其批处理推理接口这里为演示使用循环。 # 在实际生产环境中应使用异步请求或vLLM的generate函数直接处理prompt列表。 generated_contents [] for prompt in sub_prompts: try: response client.chat.completions.create( modelqwen2.5-7b, messages[{role: user, content: prompt}], max_tokens500, # 每个部分的预期长度 temperature0.7, # 内容生成可以稍高更有创造性 ) content response.choices[0].message.content.strip() generated_contents.append(content) except Exception as e: print(f生成部分 {prompt[:50]}... 时失败: {e}) generated_contents.append(f[此部分内容生成时出现错误{e}]) return generated_contents # 测试并行生成注意此示例为顺序模拟真实并行需异步或批处理API contents parallel_generate_with_skeleton(query, skeleton) for i, (point, content) in enumerate(zip(skeleton, contents)): print(f\n--- 部分 {i1}: {point} ---) print(content[:200] ...) # 打印前200字符步骤四结果组装与后处理将所有并行生成的内容按照骨架顺序拼接起来并可能进行一些润色。def assemble_final_answer(skeleton_points: list, parallel_contents: list) - str: 将骨架点和并行生成的内容组装成最终答案。 if len(skeleton_points) ! len(parallel_contents): # 安全处理长度不一致时简单拼接 return \n\n.join(parallel_contents) final_lines [] for i, (point, content) in enumerate(zip(skeleton_points, parallel_contents)): # 可以选择是否保留骨架点作为标题 final_lines.append(f**{i1}. {point}**) final_lines.append(content) final_lines.append() # 空行分隔 return \n.join(final_lines) # 组装最终答案 final_answer assemble_final_answer(skeleton, contents) print(\n *50) print(最终答案预览前500字符) print(*50) print(final_answer[:500] ...)3.3 高级优化与工程化考量上面的示例是一个简化版本。在实际生产环境中你需要考虑更多真正的并行与异步上述循环是顺序调用API并未实现真正并行。应使用asyncio和aiohttp并发所有请求或直接使用vLLM的LLMEngine类进行低层级批处理。错误处理与重试网络波动、模型服务不稳定是常态。必须为每个子任务添加重试机制和超时控制。负载均衡与多副本如果骨架点很多例如超过10个单个模型实例的批处理大小可能受限。需要考虑将任务分发给多个模型副本多GPU或多节点。骨架质量评估与回退不是所有查询都适合SoT。对于非常开放、创意性的问题如“写一首诗”强制生成骨架可能适得其反。需要设计启发式规则判断是否启用SoT或在骨架质量太差时回退到标准自回归生成。上下文管理在并行生成时每个子任务都只看到了“原始问题骨架点”看不到其他部分的内容。这可能导致跨部分的指代如“如上所述”失效。需要在后处理阶段进行轻微的文本润色或是在骨架提示中明确要求避免使用此类指代。踩坑记录在早期测试中我们曾遇到“骨架点相互重叠或遗漏”的问题。例如对于“优缺点分析”模型可能生成“1. 优点。2. 缺点。3. 优点总结。”其中点1和点3内容重复。解决方案是优化骨架提示词强调“骨架点应互斥且共同穷尽MECE原则”并在解析后加入简单的去重和逻辑检查。4. 效果评估与性能对比SoT不是“银弹”它的效果高度依赖于任务类型和实现质量。我们需要从速度和质量两个维度来评估。4.1 速度提升理论分析与实测数据理论加速比 假设一个回答需要生成N个token采用标准自回归解码耗时约为T_sequential N * t其中t是生成单个token的平均延迟。 采用SoT设骨架生成需要S个token耗时T_skeleton S * t。骨架被分为K个部分每个部分平均长度约为(N-S)/K个token。由于K个部分并行生成所以填充阶段耗时约为最长那个部分的生成时间近似为T_parallel ≈ max_i( L_i * t )其中L_i是第i部分的长度。在理想均匀分布下T_parallel ≈ ((N-S)/K) * t。 总耗时T_sot T_skeleton T_parallel ≈ S*t ((N-S)/K)*t。 加速比Speedup T_sequential / T_sot ≈ N / (S (N-S)/K)。 当N很大S相对较小K较大时加速比趋近于K。也就是说理论上最大加速比可以接近并行部分的数量K。实测考量 在实际中由于GPU硬件执行批处理时存在开销以及各部分长度不均等加速比会低于理论值。但根据原论文和我们的实验对于结构良好的问题**端到端延迟减少30%-70%**是常见范围。吞吐量提升则更为显著因为服务器可以同时处理更多用户的骨架生成和填充请求。4.2 输出质量评估速度的提升不能以牺牲质量为代价。SoT对质量的影响是双面的潜在优势结构更清晰强制性的骨架阶段使得最终答案天然具有良好的组织结构逻辑层次分明。内容更全面骨架作为一种规划有助于模型覆盖问题的所有方面减少遗漏。减少重复在标准生成中模型有时会陷入循环或重复论述。SoT的并行生成将内容限制在特定子主题内减少了这种风险。潜在风险与缓解措施连贯性损失各部分独立生成可能导致段落间过渡生硬。缓解在骨架提示中要求“考虑与上下文的衔接”或在后处理时添加连接词。风格不一致不同部分可能语气、详略程度略有差异。缓解在填充阶段的提示词中明确风格要求如“保持学术严谨口吻”。骨架偏差如果骨架本身有误如逻辑顺序混乱、遗漏要点会放大错误。缓解使用更强大的模型如GPT-4来生成骨架或对骨架进行简单的人工/规则校验。一种实用的评估方法是盲测将同一个问题用标准方法和SoT方法各生成5个答案打乱后让人工评估者从“相关性、完整性、连贯性、语言质量”等方面评分。我们的内部测试显示在事实性问答、步骤说明等结构化任务上SoT的输出质量与标准方法持平甚至略优在创意写作上标准方法略占优势。4.3 适用场景与不适用场景总结强烈推荐使用SoT的场景长文本生成生成报告、文章、详细指南等其中骨架的收益最大。结构化问答解释概念、列举项、对比分析、分步骤教程。高并发API服务需要同时处理大量用户查询对降低延迟和提升吞吐量有迫切需求。成本敏感型应用SoT可能通过减少总体生成时间尽管增加了少量骨架生成时间来降低按token计费的成本。不建议或需谨慎使用SoT的场景短文本生成生成一句话摘要、简短回复等骨架生成的开销可能抵消并行收益。高度创意性或自由对话写诗歌、编故事、开放域闲聊强制结构可能抑制创造性。强逻辑递进文本数学推导、复杂代码生成一个函数其中后续步骤严格依赖前序步骤的结果。对连贯性要求极高的文本文学创作、演讲稿其中语气、情感的流动至关重要。5. 常见问题、调试技巧与未来展望在实际部署和调试SoT系统时你会遇到各种各样的问题。这里我总结了一份“避坑指南”。5.1 常见问题与解决方案问题现象可能原因排查步骤与解决方案生成速度没有提升甚至变慢1. 骨架点数量太少K小。2. 骨架生成耗时过长S大。3. 并行调度开销大或模型批处理效率低。4. 查询本身不适合SoT输出很短。1. 分析骨架点数量对于短回答可禁用SoT。2. 优化骨架提示词限制骨架长度如max_tokens80。3. 检查推理引擎配置如vLLM的max_num_batched_tokens确保批处理大小设置合理。4. 实现一个决策器根据查询长度、类型动态开关SoT。最终答案结构混乱内容重复或缺失1. 骨架解析失败导致点与内容错位。2. 骨架本身质量差逻辑不清晰。3. 并行生成时子提示词未能有效约束内容范围。1. 加强骨架解析的鲁棒性加入多种格式匹配和fallback。2. 使用能力更强的模型如GPT-4 Turbo专门负责骨架生成即使填充用较小模型。3. 优化子提示词明确要求“仅阐述[骨架点]相关内容不要涉及其他部分”。不同部分风格或事实不一致并行生成时每个部分独立采样可能导致细微差异。1. 在并行生成时使用相同的seed值确保生成过程确定性如果推理引擎支持。2. 在后处理阶段进行简单的风格统一检查或使用一个轻量级模型进行润色。GPU内存溢出OOM并行生成时批处理大小过大或模型本身在长序列下内存占用高。1. 限制并行生成的最大批处理大小。2. 使用vLLM的PagedAttention等内存优化技术。3. 考虑将过长的骨架点分组进行多轮并行生成。对于开放性问题骨架生成效果差模型不擅长为高度开放的问题规划结构。1. 针对此类问题设计更通用、灵活的骨架提示如“请构思故事的主要情节、人物和转折点”。2. 引入分类器识别问题类型对不适合SoT的查询直接走标准流程。5.2 高级调试与优化技巧骨架提示词A/B测试不要只用一个提示词。准备3-5个不同风格的骨架提示如“用要点形式”、“用问题形式”、“用章节标题形式”在少量测试集上运行评估哪个生成的骨架最稳定、最易解析、最能引导出高质量内容。动态骨架点数量K让模型自己决定骨架的粗细。在提示词中可以说“请列出3-7个最重要的回答要点”。或者根据初始查询的长度和复杂度用规则动态设定K的范围。两阶段内容生成对于非常长的内容如万字报告可以采用“递归SoT”。即先生成一级骨架如“引言、背景、方法、结果、讨论”然后对每个一级骨架点如“方法”再将其作为新的查询用SoT生成二级骨架和内容。与流式输出结合SoT本身和流式输出Server-Sent Events并不冲突。你可以先流式输出骨架然后同时开始并行生成各部分内容。一旦某个部分生成完毕就立即流式输出该部分。这能给用户“快速看到大纲然后内容逐渐丰满”的体验比干等所有内容生成完再一次性输出体验更好。监控与度量建立关键指标监控骨架生成时间、并行填充时间、总耗时加速比、骨架解析成功率、最终答案的人工评估分数或使用LLM-as-a-Judge自动评分。用数据驱动迭代优化。5.3 未来可能的演进方向SoT为我们打开了一扇窗让我们看到大模型推理优化不只有“压缩模型”这一条路。沿着这个思路未来可能会有更多有趣的发展更智能的骨架规划不仅仅是线性列表未来骨架可能是树状结构用于超长文档、思维导图甚至是带有依赖关系的DAG有向无环图允许某些部分并行某些部分必须有先后顺序。模型原生支持与其在应用层“教”模型先列提纲不如在模型训练阶段就注入这种“规划-执行”的inductive bias。未来的模型架构或许会内置一个“规划模块”专门负责快速生成内容结构。多模态扩展SoT的思想可以扩展到多模态生成。例如生成一个视频脚本时先规划“场景1、场景2、场景3”然后并行生成每个场景的详细描述、分镜和台词。与Agent工作流结合在复杂的AI Agent任务中如“调研一个主题并写报告”SoT可以作为顶层协调器。Agent先规划任务骨架“1. 搜索资料2. 分析数据3. 撰写初稿4. 润色修改”然后并行或串行地调度子工具或子Agent去执行。从我个人的实践来看Skeleton-of-Thought更像是一种“工程哲学”的体现在资源有限的情况下通过改变任务的组织和调度方式往往能获得比单纯优化底层单元更大的收益。它不需要你等待下一代GPU也不需要你费力去微调一个巨模型只需要在调用模型的方式上多一些巧思就能立竿见影地提升性能。这种高性价比的优化在实际业务中尤其宝贵。下次当你觉得模型API调用太慢时不妨先别急着加机器试试让它先“打个草稿”吧。
Skeleton-of-Thought:大模型推理加速的并行化思维骨架技术
发布时间:2026/6/2 6:01:00
1. 项目概述当大模型“思考”时我们能否让它“多线程”工作如果你用过ChatGPT、Claude或者国内的文心一言、通义千问这类大语言模型一定对那个“一个字一个字往外蹦”的生成过程印象深刻。无论是写代码、创作故事还是回答复杂问题模型都像一个深思熟虑的作家必须写完上一句才能构思下一句。这种“顺序解码”的方式是当前绝大多数LLM大语言模型生成文本的默认模式技术上称为“自回归生成”。但仔细想想这真的符合人类的思考方式吗当我们被问到“请写一篇关于人工智能对社会影响的短文并给出三个正面和三个负面例子”时我们的大脑并不会先想好标题再想第一段然后第二段……我们很可能会先在大脑中快速勾勒出一个“骨架”哦需要先定义AI然后分正面和负面两大块正面可能包括医疗、效率、娱乐负面可能涉及就业、隐私、伦理。这个“骨架”几乎是瞬间成型的然后我们再往里面填充血肉——具体的例子和论述。这个过程是并行的、结构化的。“Skeleton-of-Thought”SoT直译为“思维骨架”其核心思想正是借鉴了人类的这种高效思考模式。它不再强迫模型严格地从左到右、逐词生成而是引导模型先快速构建一个回答的“高层结构”或“骨架”然后并行地、独立地去生成这个骨架中各个部分的具体内容。简单来说就是把一个漫长的“顺序写作”任务拆解成一个“先列提纲再多人分工同时撰写不同章节”的并行任务。我最初接触到这个想法是在实际部署大模型API服务时。面对高并发请求即使模型本身推理速度很快但每个请求因为要顺序生成几百个token词元整体响应时间Time to First Token, TTFT 和 Time per Output Token, TPOT叠加起来用户体验和系统吞吐量就成了大问题。SoT的出现就像是为大模型的文本生成引擎装上了一台“涡轮增压器”它不改变引擎本身模型权重而是优化了“燃油喷射”和“进气”的流程从而在保持输出质量的同时显著提升生成速度。这项技术特别适合那些回答具有清晰结构性的场景比如问答与解释“解释光合作用的过程”、“列举Python的五个主要特性”。对比与分析“比较React和Vue.js的优缺点”、“分析电动汽车和燃油车的市场前景”。步骤与指南“如何重置路由器”、“烹饪一道番茄炒蛋的步骤”。创作与规划“为一个科幻小说写故事大纲”、“制定一份一周健身计划”。对于开发者、研究者和任何需要大规模、低成本调用大模型API的用户来说SoT意味着更快的响应、更低的延迟和更高的吞吐量。它不是在追求“魔改”模型以挤出最后一点精度而是在工程和算法层面对现有庞大模型资源进行一次极其聪明的“调度优化”。接下来我们就深入拆解这个“思维骨架”是如何被构建并驱动模型并行工作的。2. 核心原理拆解从“串行讲故事”到“并行填框架”要理解SoT我们必须先看清它要解决的核心矛盾大模型强大的“思考”能力与低效的“表达”方式之间的矛盾。2.1 自回归解码的瓶颈为什么模型“说话”慢当前主流LLM如GPT、LLaMA系列都采用Transformer的解码器架构。在生成文本时它们的工作流程是这样的给定一个输入提示词模型计算出第一个词的概率分布我们根据某种策略如贪心搜索、核采样选出一个词。将这个生成的词追加到输入后面形成新的输入序列。模型基于这个新的、更长的序列计算下一个词的概率分布再选出一个词。重复步骤2和3直到生成结束标记或达到最大长度。这个过程是严格自回归的即每一步的生成都依赖于之前生成的所有词。这带来了两个主要瓶颈计算无法并行生成第N个词时必须等第N-1个词生成完毕并输入模型后才能开始计算。这使得GPU强大的并行计算能力在生成阶段无法被充分利用大部分计算单元在等待。内存访问频繁每次生成一个词都需要将整个不断增长的序列Key-Value缓存加载到GPU显存中进行注意力计算。随着生成文本变长内存带宽逐渐成为限制速度的关键因素即所谓的“内存墙”。这就好比一个厨师必须切完西红柿才能打鸡蛋打完鸡蛋才能开火全程只有一个灶台在工作。SoT的思路是能不能让厨师先快速规划好“番茄炒蛋、凉拌黄瓜、米饭”这三道菜的工序然后同时开三个灶台来炒菜、拌菜、煮饭2.2 SoT的两阶段范式骨架构建与并行填充SoT将传统的单一路径生成解耦为两个清晰阶段第一阶段骨架生成在这个阶段模型的任务不是生成具体内容而是生成一个关于“如何组织答案”的元描述即“骨架”。这个骨架通常是一系列简短的、指示性的句子或短语。提示词工程这是SoT成功的关键。我们需要设计一个特殊的“骨架提示”引导模型进行高层规划。例如在原始提示后追加“请先为你的回答列出一个简要的提纲用‘1.’, ‘2.’, ‘3.’这样的编号列出主要部分每个部分用一句话概括核心点。提纲之后再展开详细内容。”模型行为在这个阶段模型以“元认知”的方式运行。它理解自己被要求先规划再执行。生成的骨架长度很短可能只占最终答案的5%-10%。例如对于问题“解释机器学习中的过拟合”骨架可能是“1. 定义过拟合现象。2. 分析过拟合产生的原因。3. 列举防止过拟合的常见方法。4. 总结。”速度优势由于骨架非常简短这个阶段的自回归生成过程很快延迟很低。第二阶段内容并行填充拿到骨架后系统将每个骨架点如“1. 定义过拟合现象”与原始问题组合形成多个独立的子问题。例如子问题1: “解释机器学习中的过拟合。首先请详细定义过拟合现象。”子问题2: “解释机器学习中的过拟合。接着请详细分析过拟合产生的原因。”……然后这些子问题被同时送入模型或模型的多个实例进行生成。因为每个子问题的生成是独立的不依赖于其他子问题的结果所以它们可以完全并行。技术实现在拥有多GPU卡或支持批量推理的推理服务器上可以将这些子问题组成一个批处理batch一次性提交给模型。模型会并行计算所有子问题的答案。质量保障每个子问题的生成仍然是自回归的保证了单个片段内的语言连贯性和逻辑性。由于每个片段都基于完整的原始问题和具体的骨架点内容不会偏离主题。注意这里的“并行”指的是任务级别的并行即多个独立的文本生成任务同时进行。它并非改变了Transformer模型内部计算下一个token的机制那仍然是顺序的而是通过组织任务的方式让GPU能够同时处理多个独立的生成序列从而压榨硬件利用率。2.3 与传统加速技术的区别SoT与一些常见的LLM加速技术有本质区别投机解码需要一个更小的“草稿模型”快速生成多个候选token再由大模型进行验证。它加速的是单个序列的生成。SoT则通过改变任务结构来实现并行。模型量化/蒸馏这些方法直接改变模型本身缩小尺寸、降低精度可能会损失一定的输出质量。SoT是一种“无损”的推理方法不修改模型权重理论上不影响模型的内在能力。仅解码器优化如PagedAttentionvLLM采用主要优化的是KV缓存的内存管理提高吞吐量。SoT可以与这些优化结合从任务编排层面进一步提速。SoT的核心创新在于它跳出了“优化单序列生成”的思维定式转而思考“如何将单序列任务重构为可并行化的多序列任务”。这需要对模型能力能否生成高质量骨架和工程架构如何高效调度并行任务有深入的理解。3. 实现方案与实操要点理解了原理我们来看看如何亲手实现一个SoT流程。这里我将提供一个基于流行开源框架如LangChain、vLLM和通用Python代码的实操方案。我们假设使用一个开源的LLM如Qwen2.5-7B-Instruct和vLLM作为推理引擎。3.1 系统架构设计一个完整的SoT系统通常包含以下组件骨架生成器接收用户原始查询调用LLM生成骨架。骨架解析器将LLM返回的文本解析成结构化的骨架点列表。任务调度器根据骨架点列表构造并行子查询并管理向推理引擎的批处理请求。并行推理引擎支持高效批处理推理的LLM服务端如vLLM、TGI。结果组装器接收所有并行生成的结果片段按照骨架顺序拼接成最终答案。用户查询 | v [骨架生成器] - 调用LLM生成骨架文本 | v [骨架解析器] - 解析为列表[点1, 点2, ...] | v [任务调度器] - 构造子查询批处理 [查询点1, 查询点2, ...] | v [并行推理引擎 vLLM] - 并行生成结果 [结果1, 结果2, ...] | v [结果组装器] - 按顺序拼接 - 最终答案3.2 关键步骤详解与代码示例步骤一环境准备与模型加载首先我们需要部署一个支持高效批处理的推理引擎。这里以vLLM为例。# 安装vLLM pip install vllm # 启动一个vLLM服务这里以本地运行为例生产环境需部署为服务 # 此命令会在本地启动一个API服务器加载Qwen2.5-7B模型 python -m vllm.entrypoints.openai.api_server \ --model Qwen/Qwen2.5-7B-Instruct \ --served-model-name qwen2.5-7b \ --max-model-len 8192 \ --tensor-parallel-size 1 # 根据你的GPU数量调整步骤二实现骨架生成与解析这是SoT的“大脑”。我们需要精心设计提示词并可靠地解析模型的输出。import openai # vLLM兼容OpenAI API协议 import re # 配置客户端指向本地vLLM服务 client openai.OpenAI( api_keytoken-abc123, # vLLM默认token可自定义 base_urlhttp://localhost:8000/v1 ) def generate_skeleton(user_query: str) - list: 根据用户查询生成回答骨架。 skeleton_prompt f 你是一个擅长结构化思考的助手。请按照以下步骤回答用户的问题 1. 首先为你的回答列出一个清晰的提纲骨架。这个提纲应该涵盖回答的所有关键部分。 2. 提纲的每一行都应该是一个完整的句子或短语明确指示该部分要阐述的内容。 3. 请使用数字编号如1., 2., 3.来列出骨架点。 用户问题{user_query} 现在请只输出提纲部分不要输出任何其他解释或详细内容。 提纲 try: response client.chat.completions.create( modelqwen2.5-7b, messages[{role: user, content: skeleton_prompt}], max_tokens150, # 骨架不需要太长 temperature0.1, # 低温度确保骨架稳定、结构化 stop[\n\n] # 可能的中止符防止生成额外内容 ) skeleton_text response.choices[0].message.content.strip() # 解析骨架文本提取编号点 # 使用正则表达式匹配 1. xxx, 2. xxx 这样的模式 points re.findall(r^\d\.\s*(.)$, skeleton_text, re.MULTILINE) if not points: # 如果正则匹配失败尝试按行分割并清理 points [line.strip() for line in skeleton_text.split(\n) if line.strip()] # 移除可能残留的编号 points [re.sub(r^\d\.\s*, , p) for p in points] return points except Exception as e: print(f骨架生成失败: {e}) # 降级策略如果生成失败返回一个简单的默认骨架 return [概述, 详细分析, 总结] # 测试骨架生成 query 请详细解释什么是区块链技术它的核心优势是什么以及面临的主要挑战。 skeleton generate_skeleton(query) print(生成的骨架, skeleton) # 可能输出[区块链技术的基本定义与原理, 区块链的核心优势分析, 区块链面临的主要挑战与问题, 总结与展望]实操心得骨架提示词的设计需要反复调试。不同的模型对提示词的敏感度不同。对于Qwen、ChatGLM等国内模型可能需要更符合中文习惯的提示比如“请首先给出回答的要点大纲”。temperature参数在骨架生成阶段建议设低如0.1-0.3以确保生成的结构稳定、可预测。一定要编写健壮的解析逻辑并准备好降级方案如返回默认骨架因为模型输出可能存在格式波动。步骤三并行任务调度与推理这是SoT的“肌肉”。我们将骨架点转化为并行任务并利用vLLM的批处理接口一次性提交。def parallel_generate_with_skeleton(user_query: str, skeleton_points: list) - list: 根据骨架点并行生成每个部分的内容。 # 1. 构造每个骨架点的完整提示 sub_prompts [] for point in skeleton_points: # 这里可以设计更精细的提示引导模型围绕该点展开 prompt f 请基于以下用户问题详细阐述“{point}”这一部分。 请确保你的回答内容聚焦、完整且是整体回答的一部分。 用户问题{user_query} 现在请详细阐述【{point}】 sub_prompts.append(prompt) # 2. 准备批量请求 # vLLM的OpenAI接口支持通过多个独立的ChatCompletion请求模拟批处理 # 但更高效的方式是直接使用其批处理推理接口这里为演示使用循环。 # 在实际生产环境中应使用异步请求或vLLM的generate函数直接处理prompt列表。 generated_contents [] for prompt in sub_prompts: try: response client.chat.completions.create( modelqwen2.5-7b, messages[{role: user, content: prompt}], max_tokens500, # 每个部分的预期长度 temperature0.7, # 内容生成可以稍高更有创造性 ) content response.choices[0].message.content.strip() generated_contents.append(content) except Exception as e: print(f生成部分 {prompt[:50]}... 时失败: {e}) generated_contents.append(f[此部分内容生成时出现错误{e}]) return generated_contents # 测试并行生成注意此示例为顺序模拟真实并行需异步或批处理API contents parallel_generate_with_skeleton(query, skeleton) for i, (point, content) in enumerate(zip(skeleton, contents)): print(f\n--- 部分 {i1}: {point} ---) print(content[:200] ...) # 打印前200字符步骤四结果组装与后处理将所有并行生成的内容按照骨架顺序拼接起来并可能进行一些润色。def assemble_final_answer(skeleton_points: list, parallel_contents: list) - str: 将骨架点和并行生成的内容组装成最终答案。 if len(skeleton_points) ! len(parallel_contents): # 安全处理长度不一致时简单拼接 return \n\n.join(parallel_contents) final_lines [] for i, (point, content) in enumerate(zip(skeleton_points, parallel_contents)): # 可以选择是否保留骨架点作为标题 final_lines.append(f**{i1}. {point}**) final_lines.append(content) final_lines.append() # 空行分隔 return \n.join(final_lines) # 组装最终答案 final_answer assemble_final_answer(skeleton, contents) print(\n *50) print(最终答案预览前500字符) print(*50) print(final_answer[:500] ...)3.3 高级优化与工程化考量上面的示例是一个简化版本。在实际生产环境中你需要考虑更多真正的并行与异步上述循环是顺序调用API并未实现真正并行。应使用asyncio和aiohttp并发所有请求或直接使用vLLM的LLMEngine类进行低层级批处理。错误处理与重试网络波动、模型服务不稳定是常态。必须为每个子任务添加重试机制和超时控制。负载均衡与多副本如果骨架点很多例如超过10个单个模型实例的批处理大小可能受限。需要考虑将任务分发给多个模型副本多GPU或多节点。骨架质量评估与回退不是所有查询都适合SoT。对于非常开放、创意性的问题如“写一首诗”强制生成骨架可能适得其反。需要设计启发式规则判断是否启用SoT或在骨架质量太差时回退到标准自回归生成。上下文管理在并行生成时每个子任务都只看到了“原始问题骨架点”看不到其他部分的内容。这可能导致跨部分的指代如“如上所述”失效。需要在后处理阶段进行轻微的文本润色或是在骨架提示中明确要求避免使用此类指代。踩坑记录在早期测试中我们曾遇到“骨架点相互重叠或遗漏”的问题。例如对于“优缺点分析”模型可能生成“1. 优点。2. 缺点。3. 优点总结。”其中点1和点3内容重复。解决方案是优化骨架提示词强调“骨架点应互斥且共同穷尽MECE原则”并在解析后加入简单的去重和逻辑检查。4. 效果评估与性能对比SoT不是“银弹”它的效果高度依赖于任务类型和实现质量。我们需要从速度和质量两个维度来评估。4.1 速度提升理论分析与实测数据理论加速比 假设一个回答需要生成N个token采用标准自回归解码耗时约为T_sequential N * t其中t是生成单个token的平均延迟。 采用SoT设骨架生成需要S个token耗时T_skeleton S * t。骨架被分为K个部分每个部分平均长度约为(N-S)/K个token。由于K个部分并行生成所以填充阶段耗时约为最长那个部分的生成时间近似为T_parallel ≈ max_i( L_i * t )其中L_i是第i部分的长度。在理想均匀分布下T_parallel ≈ ((N-S)/K) * t。 总耗时T_sot T_skeleton T_parallel ≈ S*t ((N-S)/K)*t。 加速比Speedup T_sequential / T_sot ≈ N / (S (N-S)/K)。 当N很大S相对较小K较大时加速比趋近于K。也就是说理论上最大加速比可以接近并行部分的数量K。实测考量 在实际中由于GPU硬件执行批处理时存在开销以及各部分长度不均等加速比会低于理论值。但根据原论文和我们的实验对于结构良好的问题**端到端延迟减少30%-70%**是常见范围。吞吐量提升则更为显著因为服务器可以同时处理更多用户的骨架生成和填充请求。4.2 输出质量评估速度的提升不能以牺牲质量为代价。SoT对质量的影响是双面的潜在优势结构更清晰强制性的骨架阶段使得最终答案天然具有良好的组织结构逻辑层次分明。内容更全面骨架作为一种规划有助于模型覆盖问题的所有方面减少遗漏。减少重复在标准生成中模型有时会陷入循环或重复论述。SoT的并行生成将内容限制在特定子主题内减少了这种风险。潜在风险与缓解措施连贯性损失各部分独立生成可能导致段落间过渡生硬。缓解在骨架提示中要求“考虑与上下文的衔接”或在后处理时添加连接词。风格不一致不同部分可能语气、详略程度略有差异。缓解在填充阶段的提示词中明确风格要求如“保持学术严谨口吻”。骨架偏差如果骨架本身有误如逻辑顺序混乱、遗漏要点会放大错误。缓解使用更强大的模型如GPT-4来生成骨架或对骨架进行简单的人工/规则校验。一种实用的评估方法是盲测将同一个问题用标准方法和SoT方法各生成5个答案打乱后让人工评估者从“相关性、完整性、连贯性、语言质量”等方面评分。我们的内部测试显示在事实性问答、步骤说明等结构化任务上SoT的输出质量与标准方法持平甚至略优在创意写作上标准方法略占优势。4.3 适用场景与不适用场景总结强烈推荐使用SoT的场景长文本生成生成报告、文章、详细指南等其中骨架的收益最大。结构化问答解释概念、列举项、对比分析、分步骤教程。高并发API服务需要同时处理大量用户查询对降低延迟和提升吞吐量有迫切需求。成本敏感型应用SoT可能通过减少总体生成时间尽管增加了少量骨架生成时间来降低按token计费的成本。不建议或需谨慎使用SoT的场景短文本生成生成一句话摘要、简短回复等骨架生成的开销可能抵消并行收益。高度创意性或自由对话写诗歌、编故事、开放域闲聊强制结构可能抑制创造性。强逻辑递进文本数学推导、复杂代码生成一个函数其中后续步骤严格依赖前序步骤的结果。对连贯性要求极高的文本文学创作、演讲稿其中语气、情感的流动至关重要。5. 常见问题、调试技巧与未来展望在实际部署和调试SoT系统时你会遇到各种各样的问题。这里我总结了一份“避坑指南”。5.1 常见问题与解决方案问题现象可能原因排查步骤与解决方案生成速度没有提升甚至变慢1. 骨架点数量太少K小。2. 骨架生成耗时过长S大。3. 并行调度开销大或模型批处理效率低。4. 查询本身不适合SoT输出很短。1. 分析骨架点数量对于短回答可禁用SoT。2. 优化骨架提示词限制骨架长度如max_tokens80。3. 检查推理引擎配置如vLLM的max_num_batched_tokens确保批处理大小设置合理。4. 实现一个决策器根据查询长度、类型动态开关SoT。最终答案结构混乱内容重复或缺失1. 骨架解析失败导致点与内容错位。2. 骨架本身质量差逻辑不清晰。3. 并行生成时子提示词未能有效约束内容范围。1. 加强骨架解析的鲁棒性加入多种格式匹配和fallback。2. 使用能力更强的模型如GPT-4 Turbo专门负责骨架生成即使填充用较小模型。3. 优化子提示词明确要求“仅阐述[骨架点]相关内容不要涉及其他部分”。不同部分风格或事实不一致并行生成时每个部分独立采样可能导致细微差异。1. 在并行生成时使用相同的seed值确保生成过程确定性如果推理引擎支持。2. 在后处理阶段进行简单的风格统一检查或使用一个轻量级模型进行润色。GPU内存溢出OOM并行生成时批处理大小过大或模型本身在长序列下内存占用高。1. 限制并行生成的最大批处理大小。2. 使用vLLM的PagedAttention等内存优化技术。3. 考虑将过长的骨架点分组进行多轮并行生成。对于开放性问题骨架生成效果差模型不擅长为高度开放的问题规划结构。1. 针对此类问题设计更通用、灵活的骨架提示如“请构思故事的主要情节、人物和转折点”。2. 引入分类器识别问题类型对不适合SoT的查询直接走标准流程。5.2 高级调试与优化技巧骨架提示词A/B测试不要只用一个提示词。准备3-5个不同风格的骨架提示如“用要点形式”、“用问题形式”、“用章节标题形式”在少量测试集上运行评估哪个生成的骨架最稳定、最易解析、最能引导出高质量内容。动态骨架点数量K让模型自己决定骨架的粗细。在提示词中可以说“请列出3-7个最重要的回答要点”。或者根据初始查询的长度和复杂度用规则动态设定K的范围。两阶段内容生成对于非常长的内容如万字报告可以采用“递归SoT”。即先生成一级骨架如“引言、背景、方法、结果、讨论”然后对每个一级骨架点如“方法”再将其作为新的查询用SoT生成二级骨架和内容。与流式输出结合SoT本身和流式输出Server-Sent Events并不冲突。你可以先流式输出骨架然后同时开始并行生成各部分内容。一旦某个部分生成完毕就立即流式输出该部分。这能给用户“快速看到大纲然后内容逐渐丰满”的体验比干等所有内容生成完再一次性输出体验更好。监控与度量建立关键指标监控骨架生成时间、并行填充时间、总耗时加速比、骨架解析成功率、最终答案的人工评估分数或使用LLM-as-a-Judge自动评分。用数据驱动迭代优化。5.3 未来可能的演进方向SoT为我们打开了一扇窗让我们看到大模型推理优化不只有“压缩模型”这一条路。沿着这个思路未来可能会有更多有趣的发展更智能的骨架规划不仅仅是线性列表未来骨架可能是树状结构用于超长文档、思维导图甚至是带有依赖关系的DAG有向无环图允许某些部分并行某些部分必须有先后顺序。模型原生支持与其在应用层“教”模型先列提纲不如在模型训练阶段就注入这种“规划-执行”的inductive bias。未来的模型架构或许会内置一个“规划模块”专门负责快速生成内容结构。多模态扩展SoT的思想可以扩展到多模态生成。例如生成一个视频脚本时先规划“场景1、场景2、场景3”然后并行生成每个场景的详细描述、分镜和台词。与Agent工作流结合在复杂的AI Agent任务中如“调研一个主题并写报告”SoT可以作为顶层协调器。Agent先规划任务骨架“1. 搜索资料2. 分析数据3. 撰写初稿4. 润色修改”然后并行或串行地调度子工具或子Agent去执行。从我个人的实践来看Skeleton-of-Thought更像是一种“工程哲学”的体现在资源有限的情况下通过改变任务的组织和调度方式往往能获得比单纯优化底层单元更大的收益。它不需要你等待下一代GPU也不需要你费力去微调一个巨模型只需要在调用模型的方式上多一些巧思就能立竿见影地提升性能。这种高性价比的优化在实际业务中尤其宝贵。下次当你觉得模型API调用太慢时不妨先别急着加机器试试让它先“打个草稿”吧。