全书阅读:https://github.com/xiaer-ai42/infinite_archives/blob/main/books/Advanced_Prompting.md
提示工程进阶:思维链与结构化提示
书籍大纲
第一章:提示工程基础与演进
- 1.1 从命令到对话:交互范式的转变
- 1.2 提示工程的核心原则
- 1.3 Zero-shot与Few-shot学习
- 1.4 提示模板设计模式
- 1.5 常见陷阱与避坑指南
- 1.6 提示工程的理论基础
第二章:思维链推理(Chain-of-Thought)
- 2.1 思维链的发现与原理
- 2.2 标准思维链与自洽性思维链
- 2.3 零样本思维链(Zero-shot CoT)
- 2.4 思维链的适用场景与局限
- 2.5 思维链的变体:Least-to-Most、Decomposed
- 2.6 思维链的数学基础与理论解释
第三章:高级推理技术
- 3.1 思维树(Tree of Thoughts)
- 3.2 思维图(Graph of Thoughts)
- 3.3 自我反思与自评估
- 3.4 ReAct:推理与行动的结合
- 3.5 自我一致性(Self-Consistency)
- 3.6 多路径推理与集成
第四章:结构化提示设计
- 4.1 结构化提示的优势
- 4.2 角色设定与人设提示
- 4.3 任务分解与步骤化
- 4.4 输出格式控制
- 4.5 上下文窗口优化
- 4.6 模板化与参数化提示
第五章:多轮对话与上下文管理
- 5.1 对话历史管理策略
- 5.2 长对话的压缩与摘要
- 5.3 动态上下文选择
- 5.4 对话状态追踪
- 5.5 多任务对话架构
- 5.6 实战:构建智能对话系统
第六章:工具调用与外部知识
- 6.1 Function Calling原理
- 6.2 工具描述与接口设计
- 6.3 多工具编排策略
- 6.4 检索增强生成(RAG)
- 6.5 知识注入与提示融合
- 6.6 实战:构建工具使用型Agent
第七章:提示优化与自动化
- 7.1 自动提示优化(APO)
- 7.2 基于梯度的提示优化
- 7.3 提示压缩与蒸馏
- 7.4 A/B测试与迭代优化
- 7.5 提示版本管理
- 7.6 提示评估框架
第八章:行业应用与最佳实践
- 8.1 代码生成与编程辅助
- 8.2 数据分析与洞察提取
- 8.3 内容创作与营销文案
- 8.4 教育与个性化学习
- 8.5 企业知识管理与问答
- 8.6 提示工程的未来趋势
第二章:思维链推理(Chain-of-Thought)
2.1 思维链的发现与原理
2.1.1 突破性发现
2022年,Google Research团队在论文《Chain-of-Thought Prompting Elicits Reasoning in Large Language Models》中首次系统性地提出了思维链(Chain-of-Thought,简称CoT)的概念。这一发现标志着提示工程从"黑魔法"走向"科学方法"的重要转折点。
在CoT出现之前,大型语言模型(LLM)在复杂推理任务上的表现令人失望。例如,在GSM8K数学推理基准测试中,即使是最先进的模型也难以突破20%的准确率。研究者们发现,这些模型往往直接给出答案,而跳过了中间的推理步骤——就像一个学生直接写答案而不展示解题过程。
思维链的核心洞察是:让模型"展示工作过程"可以显著提升其推理能力。这听起来简单,但其影响深远。
2.1.2 认知科学背景
思维链的灵感来源于人类的认知过程。当人类面对复杂问题时,我们不会直接得出答案,而是:
- 分解问题:将复杂问题拆解为更小的子问题
- 逐步推理:按顺序解决每个子问题
- 整合结论:将中间结果组合成最终答案
认知心理学家将这种过程称为"系统2思维"(System 2 Thinking)——一种慢速、分析性、需要努力的心理过程。与之相对的是"系统1思维"——快速、直觉、自动化的反应。
大型语言模型在传统提示下倾向于"系统1"式的直觉回答,而思维链提示则强制模型进入"系统2"模式,进行逐步、分析性的推理。
2.1.3 技术原理
从技术角度来看,思维链的有效性可以从以下几个角度理解:
中间步骤的计算必要性
在神经网络的Transformer架构中,信息从输入层流向输出层需要经过多个注意力层和前馈层。当模型被要求直接给出答案时,它需要在有限的层内完成所有的"计算"。而思维链将推理过程展开到输出序列中,相当于增加了模型的"有效计算深度"。
传统模式: 输入 → [L层计算] → 直接答案 思维链模式: 输入 → [L层计算] → 步骤1 → [L层计算] → 步骤2 → ... → 答案减少复合错误
复杂推理任务需要多个步骤的正确执行。如果模型直接给出答案,任何一步的错误都会导致最终答案错误,而且难以调试。思维链的中间步骤提供了"检查点",使得:
- 错误可以在早期被发现
- 部分正确的推理可以被保留
- 调试者可以定位问题所在
激发训练时的推理模式
大型语言模型在训练时接触了大量的推理文本(教科书、论文、解释性内容)。思维链提示可能激活了这些训练时学到的推理模式,使模型能够"回忆起"如何进行系统性的推理。
2.1.4 思维链的基本形式
思维链提示有两种基本形式:
Few-shot CoT(少样本思维链)
在提示中提供几个带有详细推理步骤的问答示例:
问题:小明有5个苹果,他给了小红2个,又买了3个。小明现在有多少苹果? 解答过程: 1. 小明一开始有5个苹果 2. 他给了小红2个,所以剩下 5 - 2 = 3 个苹果 3. 他又买了3个,所以现在有 3 + 3 = 6 个苹果 答案:6个苹果 问题:[新问题] 解答过程:Zero-shot CoT(零样本思维链)
只需添加一个简单的触发短语:
问题:[问题内容] 让我们一步步思考:这两种形式各有优势,我们将在后续章节详细讨论。
2.2 标准思维链与自洽性思维链
2.2.1 标准思维链的局限性
标准思维链虽然强大,但存在一个关键问题:它只生成一条推理路径。如果这条路径上有任何错误,最终答案就会出错。
考虑以下数学问题:
问题:一辆汽车以60公里/小时的速度行驶了2.5小时,然后以80公里/小时的速度行驶了1.5小时。汽车总共行驶了多少公里?标准CoT可能生成:
解答过程: 1. 第一段路程:60 × 2.5 = 140公里(错误:应为150公里) 2. 第二段路程:80 × 1.5 = 120公里 3. 总路程:140 + 120 = 260公里 答案:260公里第一步的计算错误导致最终答案错误。更糟糕的是,我们无法仅从最终答案判断是否出错。
2.2.2 自洽性思维链(Self-Consistency CoT)
2022年底,Google Research提出了自洽性思维链(Self-Consistency with Chain-of-Thought),这是对标准CoT的重要改进。
核心思想
自洽性CoT基于一个简单而强大的观察:正确的推理路径比错误的推理路径更容易达成一致的答案。
具体做法:
- 使用温度参数(temperature > 0)让模型生成多条不同的推理路径
- 从每条路径中提取最终答案
- 选择出现次数最多的答案(多数投票)
路径1答案:270公里 路径2答案:270公里 路径3答案:260公里(某步计算错误) 路径4答案:270公里 路径5答案:270公里 最终答案:270公里(4/5多数)技术实现
def self_consistency_cot(prompt, model, num_samples=10, temperature=0.7): """ 自洽性思维链实现 Args: prompt: 输入提示 model: 语言模型 num_samples: 采样次数 temperature: 温度参数(>0以引入随机性) """ answers = [] reasoning_paths = [] for i in range(num_samples): # 生成推理路径 response = model.generate( prompt, temperature=temperature, max_tokens=512 ) reasoning_paths.append(response) # 提取最终答案 answer = extract_final_answer(response) answers.append(answer) # 多数投票 answer_counts = Counter(answers) final_answer = answer_counts.most_common(1)[0][0] return final_answer, reasoning_paths为什么有效?
自洽性有效的理论解释:
-
错误独立性:不同推理路径中的错误往往是独立的。一条路径的计算错误不太可能在另一条路径中以相同方式出现。
-
正确答案的唯一性:对于有确定答案的问题(如数学题),正确答案是唯一的。所有正确推理路径都会导向同一个答案。
-
错误路径的分散性:错误的推理路径会导向各种不同的错误答案,从而"稀释"了错误答案的票数。
2.2.3 采样策略优化
自洽性CoT的效果取决于采样策略:
温度选择
- 温度过低(<0.3):推理路径过于相似,失去了多样性的优势
- 温度过高(>1.0):推理质量下降,甚至生成无意义的内容
- 推荐范围:0.5-0.8
采样数量
- 5-10次采样通常足够
- 更多的采样会边际效益递减
- 对于高价值任务,可考虑20-40次采样
答案聚合策略
除了简单的多数投票,还可以使用:
- 加权投票:根据推理路径的长度、复杂度或置信度加权
- 置信度校准:使用模型输出的logprobs作为置信度
- 路径聚类:将相似的推理路径聚类,选择最大簇的答案
def weighted_self_consistency(answers, logprobs_list): """ 加权自洽性 """ answer_weights = defaultdict(float) for answer, logprobs in zip(answers, logprobs_list): # 使用平均log概率作为权重 confidence = np.mean(logprobs) answer_weights[answer] += confidence return max(answer_weights, key=answer_weights.get)
2.3 零样本思维链(Zero-shot CoT)
2.3.1 魔法短语的力量
2022年,东京大学和Google的研究者在论文《Large Language Models are Zero-Shot Reasoners》中发现了惊人的现象:只需添加"Let’s think step by step"(让我们一步步思考)这个短语,就能让模型显著提升推理能力。
这个发现被称为零样本思维链(Zero-shot CoT)。
传统零样本: 问题:小明有23个弹珠,他给了弟弟7个,又从朋友那里得到了12个。小明现在有多少弹珠? 答案:28 零样本CoT: 问题:小明有23个弹珠,他给了弟弟7个,又从朋友那里得到了12个。小明现在有多少弹珠? 让我们一步步思考: 1. 小明一开始有23个弹珠 2. 他给了弟弟7个,所以剩下 23 - 7 = 16 个弹珠 3. 他又得到了12个,所以现在有 16 + 12 = 28 个弹珠 答案:282.3.2 多语言版本的零样本CoT
"Let’s think step by step"的神奇效果引发了研究者对其他语言的探索:
语言 触发短语 效果 英语 Let’s think step by step ★★★★★ 中文 让我们一步步思考 ★★★★☆ 日语 ステップバイステップで考えてみましょう ★★★★☆ 法语 Pensons étape par étape ★★★☆☆ 德语 Denken wir Schritt für Schritt ★★★☆☆ 研究发现,英语版本通常效果最好,可能是因为英语是大多数LLM的主要训练语言。
2.3.3 零样本CoT的变体
除了标准的"Let’s think step by step",研究者发现其他变体也能产生类似效果:
策略性提示
- "Take a deep breath and think step by step" - "Let's work this out step by step to be sure we have the right answer" - "Break this down into small steps"角色扮演提示
- "As an expert mathematician, let me solve this step by step" - "Think like a teacher explaining to a student"自我提问提示
- "First, let me understand what the question is asking..." - "What information do I have? What do I need to find?"2.3.4 零样本CoT vs 少样本CoT
两种方法的对比:
维度 零样本CoT 少样本CoT 实现复杂度 简单(一个短语) 中等(需要设计示例) Token消耗 低 高(示例占用大量tokens) 灵活性 高(适应各种任务) 中(示例需与任务匹配) 性能上限 中等 更高 可控性 低 高(可引导推理格式) 实践建议
- 快速原型:使用零样本CoT
- 生产部署:使用少样本CoT,并进行A/B测试
- 高价值任务:结合两者,使用零样本生成示例,然后用于少样本提示
2.4 思维链的适用场景与局限
2.4.1 最适合的场景
思维链在以下场景表现出色:
数学与算术推理
思维链最初的成功案例就是数学推理。数学问题需要精确的中间步骤,每一步都可以验证。
问题:一个长方形的周长是36厘米,长是宽的2倍。求长方形的面积。 解答: 1. 设宽为w,则长为2w 2. 周长公式:2(长 + 宽) = 36 3. 代入:2(2w + w) = 36 4. 化简:6w = 36,w = 6 5. 长 = 2w = 12厘米 6. 面积 = 长 × 宽 = 12 × 6 = 72平方厘米 答案:72平方厘米常识推理
涉及日常生活知识的推理任务。
问题:如果我把一杯水放进冰箱冷冻室,几小时后会发生什么? 解答: 1. 冰箱冷冻室的温度通常在-18°C左右 2. 水的冰点是0°C 3. 当温度低于0°C时,液态水会凝固成冰 4. 水结冰时体积会膨胀(约增加9%) 5. 如果杯子是玻璃的,可能会破裂 答案:水会结成冰,如果杯子不够坚固可能会破裂符号推理
涉及逻辑和符号操作的任务。
问题:如果 A > B, B > C, C > D,那么 A 和 D 的关系是什么? 解答: 1. A > B(已知) 2. B > C(已知),结合(1)得 A > B > C 3. C > D(已知),结合(2)得 A > B > C > D 答案:A > D复杂决策分析
需要权衡多个因素的决策。
问题:一家初创公司有50万美元资金,应该全部投入研发,还是分成研发和市场两部分? 解答: 1. 分析两种方案的风险和收益 2. 全部投入研发: - 风险:没有市场推广,产品可能无人知晓 - 收益:产品可能更完善 3. 分成两部分(假设30万研发,20万市场): - 风险:研发资金可能不足 - 收益:有市场推广,产品可能获得用户 4. 考虑行业特性、竞争格局、产品类型 5. 综合分析:对于B2C产品,市场推广很重要;对于B2B产品,产品本身更重要 答案:需要根据具体产品类型决定,一般建议平衡投入2.4.2 效果有限的场景
思维链并非万能,以下场景效果有限:
知识密集型任务
当任务需要大量领域专业知识,而这些知识不在模型的训练数据中时,思维链无法弥补知识缺口。
问题:2024年第三季度某公司的具体财报数据是什么? 解答:(模型无法知道它训练后发生的具体数据) 这需要查询最新的财务数据库...需要精确记忆的任务
问题:请写出圆周率的前100位数字。 解答:(思维链对此类任务帮助不大) 3.14159265358979323846...(可能在中途出错)纯计算任务
对于纯数值计算,思维链不如计算工具精确。
问题:计算 123456789 × 987654321 解答:(模型可能在乘法步骤出错) 1. 这是一个大数乘法 2. ...(很可能在中间步骤出错)2.4.3 已知局限
幻觉问题
思维链可能产生"看似合理但实际错误"的推理。
问题:为什么天是蓝色的? 解答: 1. 太阳光穿过大气层 2. 短波长的蓝光被大气分子散射(正确) 3. 这叫做丁达尔效应(错误:应为瑞利散射) 答案:丁达尔效应...(错误传播)过度推理
有时简单的任务被过度复杂化。
问题:1 + 1 = ? 解答: 1. 首先理解加法的定义... 2. 在皮亚诺公理下... (过度复杂,反而可能出错)推理长度限制
对于需要很多步骤的复杂问题,思维链可能超出上下文窗口或因步骤过多而出错。
一致性幻觉
模型可能生成自相矛盾的推理,但用流畅的语言掩盖了矛盾。
2.5 思维链的变体
2.5.1 Least-to-Most Prompting(从少到多提示)
2022年Google提出的方法,核心思想是将复杂问题分解为一系列简单的子问题,然后按顺序解决。
工作流程
第一阶段:问题分解 输入:复杂问题 输出:子问题列表 第二阶段:逐步解决 输入:子问题1 → 回答1 输入:子问题2 + 回答1 → 回答2 ... 输入:子问题n + 回答(n-1) → 最终答案示例
原始问题:小明有5个苹果,给了小红2个,又买了3个,然后吃掉了1个, 又得到朋友送的4个。最后小明有多少苹果? 分解: 子问题1:小明有5个苹果,给了小红2个,还剩多少? 回答1:5 - 2 = 3个 子问题2:小明有3个苹果,又买了3个,现在有多少? 回答2:3 + 3 = 6个 子问题3:小明有6个苹果,吃掉了1个,现在有多少? 回答3:6 - 1 = 5个 子问题4:小明有5个苹果,得到朋友送的4个,最后有多少? 回答4:5 + 4 = 9个 最终答案:9个苹果Least-to-Most的优势在于每个子问题更简单,模型更容易正确回答。
2.5.2 Decomposed Prompting(分解提示)
与Least-to-Most类似,但更强调模块化的子任务处理。每个子任务可以由专门的"子模型"或工具处理。
架构
主模型(分解器) │ ├── 子模型1(算术)── 处理数学计算 ├── 子模型2(常识)── 处理常识问题 ├── 子模型3(搜索)── 处理知识查询 └── ... 主模型(合成器)── 整合各子模型的结果代码示例
class DecomposedPrompter: def __init__(self, main_model, sub_models): self.main_model = main_model self.sub_models = sub_models def decompose(self, question): prompt = f"将以下问题分解为子问题:{question}" return self.main_model.generate(prompt) def solve_subproblem(self, subproblem, submodel_type): return self.sub_models[submodel_type].generate(subproblem) def synthesize(self, sub_answers): prompt = f"基于以下信息给出最终答案:{sub_answers}" return self.main_model.generate(prompt) def solve(self, question): subproblems = self.decompose(question) answers = [] for sp in subproblems: model_type = classify_subproblem(sp) answers.append(self.solve_subproblem(sp, model_type)) return self.synthesize(answers)2.5.3 Plan-and-Solve(计划与解决)
这种方法首先让模型制定计划,然后执行计划。
两阶段流程
阶段1:制定计划 问题:[复杂任务] 请制定解决步骤: 1. [步骤1] 2. [步骤2] ... 阶段2:执行计划 按照上述计划,逐步解决问题: [执行过程]示例
问题:设计一个学生成绩管理系统 计划: 1. 分析需求(输入、输出、功能) 2. 设计数据结构(学生类、成绩类) 3. 设计核心功能(添加、查询、统计) 4. 考虑边界情况 5. 给出代码框架 执行: [按计划逐步展开...]2.5.4 Active-Prompt(主动提示)
动态选择最需要示例的问题,而不是随机选择few-shot示例。
方法
- 对训练集中的问题进行推理
- 识别模型"不确定"的问题
- 为这些问题提供人工标注的推理链
- 使用这些高价值示例进行few-shot提示
def select_uncertain_examples(dataset, model, k=10): """ 选择模型最不确定的示例 """ uncertainties = [] for example in dataset: # 多次采样,测量答案的一致性 answers = [model.generate(example, temperature=0.7) for _ in range(10)] # 不确定性 = 1 - 最常见答案的频率 entropy = calculate_entropy(answers) uncertainties.append((example, entropy)) # 选择最不确定的k个 return sorted(uncertainties, key=lambda x: x[1], reverse=True)[:k]
第三章:高级推理技术
本章深入探讨超越基础思维链的高级推理技术,包括思维树、思维图、自我反思、ReAct框架等,帮助读者掌握让大语言模型进行更复杂、更可靠推理的方法论。
3.1 思维树(Tree of Thoughts)
3.1.1 思维树的诞生背景
思维链(Chain-of-Thought)通过让模型逐步推理显著提升了复杂问题的解决能力。然而,思维链存在一个根本性局限:它是线性的。当面对需要探索多个可能性、回溯和比较的场景时,线性的推理路径往往会导致模型过早承诺于某个次优解。
思维树(Tree of Thoughts, ToT)正是为了解决这一局限而诞生。由Yao等人于2023年提出,ToT将问题求解过程建模为一棵搜索树,其中每个节点代表一个"思维状态"(thought state),每个分支代表一个可能的推理步骤。通过系统性地探索、评估和回溯,ToT能够在解空间中进行更有效的搜索。
3.1.2 思维树的核心架构
思维树的框架包含四个关键组件:
1. 思维分解(Thought Decomposition)
将复杂问题分解为中间思维步骤。每个思维应该是一个足够小的单元,既能被独立评估,又能与其他思维组合形成完整的解决方案。
问题:规划一次为期7天的日本旅行 思维分解示例: - 思维1:确定旅行主题(文化探索/美食之旅/自然风光) - 思维2:选择主要城市(东京/京都/大阪/北海道) - 思维3:安排交通方式(JR Pass/国内航班) - 思维4:预订住宿类型(酒店/民宿/胶囊旅馆) - 思维5:列出必看景点 - 思维6:预算分配2. 思维生成器(Thought Generator)
给定当前树状态,生成候选的下一个思维。生成策略可以分为两类:
- 采样策略:从相同的提示中独立采多个思维
- 提议策略:使用" propose "提示顺序生成多个思维
# 采样策略示例 prompt = f""" 当前状态:{current_state} 问题:{problem} 请生成{k}个不同的下一步思维。 """ # 提议策略示例 prompt = f""" 当前状态:{current_state} 问题:{problem} 请提出{k}个可能的下一步思维,编号1-{k}。 每个思维应该是: - 具体的、可执行的 - 与之前思维不同的 - 有助于解决问题的 """3. 状态评估器(State Evaluator)
评估当前思维状态的价值,判断其是否有希望通向正确解。评估方法包括:
- 独立评估:每个思维单独打分
- 比较评估:多个思维两两比较
评估维度示例(1-10分): - 可行性:这个思维在现实中是否可行? - 连贯性:与之前思维的一致性如何? - 进展性:是否向目标迈进? - 创造性:是否提供了新的视角? 评估提示模板: "评估以下思维状态解决问题的前景: [思维状态] 从1-10评分,10分表示非常有望解决问题。 输出格式:分数:X,理由:..."4. 搜索算法(Search Algorithm)
在思维树上进行搜索的核心算法。两种主要策略:
广度优先搜索(BFS):
- 每一步保留最有希望的b个状态
- 适合解空间相对均匀的问题
- 计算资源消耗可预测
def tot_bfs(initial_state, problem, steps, breadth): states = [initial_state] for step in range(steps): new_states = [] for state in states: # 生成候选思维 thoughts = generate_thoughts(state, problem, breadth) # 评估每个思维 for thought in thoughts: new_state = state + [thought] score = evaluate_state(new_state, problem) new_states.append((new_state, score)) # 保留得分最高的b个状态 new_states.sort(key=lambda x: x[1], reverse=True) states = [s[0] for s in new_states[:breadth]] return states[0] # 返回最佳路径深度优先搜索(DFS):
- 沿着最有希望的路径深入
- 配合回溯机制在遇到死胡同时返回
- 适合需要深度探索的问题
def tot_dfs(state, problem, max_depth, threshold): if len(state) >= max_depth: return evaluate_solution(state, problem) thoughts = generate_thoughts(state, problem, k=5) for thought in sorted(thoughts, key=lambda t: evaluate(state + [t]), reverse=True): new_state = state + [thought] score = evaluate_state(new_state, problem) if score >= threshold: # 有希望则继续深入 result = tot_dfs(new_state, problem, max_depth, threshold) if result is not None: return result # 否则回溯,尝试下一个思维 return None # 当前路径无解3.1.3 思维树实战:24点游戏
24点游戏是展示思维树威力的经典案例。给定4个数字,使用加减乘除运算得到24。
问题:使用数字 [4, 5, 6, 10] 得到 24 思维树搜索过程: 根节点:[4, 5, 6, 10] 分支1(选择两个数运算): ├── 4+5=9 → [9, 6, 10] │ ├── 9+6=15 → [15, 10] → 15+10=25 ✗ │ ├── 9*6=54 → [54, 10] → 54-10=44 ✗ │ └── 9-6=3 → [3, 10] → 无法得到24 ├── 6*4=24 → [24, 5, 10] │ ├── 24+5=29 → [29, 10] ✗ │ └── 24-10=14 → [14, 5] ✗ ├── 10-4=6 → [6, 5, 6] │ ├── 6*5=30 → [30, 6] → 30-6=24 ✓ │ └── ... └── 10-6=4 → [4, 4, 5] └── 4*5=20 → [20, 4] → 20+4=24 ✓ 找到两个解: 1. (10-6)*5+4 = 24 2. (10-4)*5-6 = 243.1.4 思维树提示模板
以下是一个通用的思维树提示模板:
# 思维树推理框架 你是一个使用思维树方法的问题求解专家。 ## 问题 {problem} ## 当前状态 {current_state} ## 可用数字/资源 {available_resources} ## 任务 1. 生成3个不同的下一步思维 2. 每个思维评估其前景(1-10分) 3. 选择最有希望的思维继续 ## 输出格式 ### 思维1 - 操作:[具体操作] - 理由:[为什么这个操作有意义] - 前景评分:X/10 ### 思维2 ... ### 思维3 ... ### 最优选择 选择思维X,理由:...3.1.5 思维树的适用场景与局限
适用场景:
- 需要探索多个可能性的创意任务(创意写作、头脑风暴)
- 解空间较大的规划问题(旅行规划、项目规划)
- 需要全局最优的决策问题
- 数学推理和逻辑谜题
局限性:
- 计算成本高:需要多次生成和评估
- 对评估器质量依赖大
- 可能陷入局部最优
- 对于简单问题反而增加复杂度
3.2 思维图(Graph of Thoughts)
3.2.1 从树到图:推理的更一般形式
思维树假设思维之间是严格的层级关系——每个思维只有一个父节点。然而,真实的推理过程往往更加复杂:思维之间可能存在依赖、组合、反馈等非线性关系。
思维图(Graph of Thoughts, GoT)将推理过程建模为一个有向图,其中:
- 节点代表思维或思维集合
- 边代表思维之间的转换关系
- 支持任意图拓扑,包括聚合、分支、循环
3.2.2 思维图的核心操作
GoT定义了一组基本图操作:
1. 分支(Branching)
从一个思维生成多个后继思维 A /|\ B C D2. 聚合(Aggregation)
将多个思维合并为一个综合思维 B C D \ | / \ | / E聚合是GoT相比ToT的关键优势,允许将不同推理路径的结果整合。
3. 改进(Refinement)
在现有思维基础上迭代改进 A → A' → A'' → A'''4. 回溯(Backtracking)
放弃当前路径,返回之前的思维状态 A → B → C ✗ ↓ 返回A → D → E ✓5. 循环(Looping)
思维之间形成反馈循环,持续改进 ┌──────┐ ↓ │ A → B → C ─┘3.2.3 思维图提示实现
class GraphOfThoughts: def __init__(self, problem): self.problem = problem self.graph = {} # adjacency list self.thoughts = {} # id -> thought content self.scores = {} # id -> evaluation score def add_thought(self, thought, parents=None): """添加新思维节点""" thought_id = generate_id() self.thoughts[thought_id] = thought self.graph[thought_id] = [] if parents: for parent in parents: self.graph[parent].append(thought_id) return thought_id def aggregate(self, thought_ids): """聚合多个思维""" combined_context = "\n".join([ self.thoughts[tid] for tid in thought_ids ]) aggregation_prompt = f""" 综合以下多个推理路径的结果: {combined_context} 请整合这些思路,形成一个统一、连贯的综合结论。 保留各路径的优点,消除矛盾。 """ aggregated = llm_generate(aggregation_prompt) return self.add_thought(aggregated, parents=thought_ids) def refine(self, thought_id, feedback=None): """改进现有思维""" thought = self.thoughts[thought_id] refinement_prompt = f""" 当前思维:{thought} {f"反馈意见:{feedback}" if feedback else ""} 请改进这个思维,使其更加: - 准确 - 完整 - 有见地 """ improved = llm_generate(refinement_prompt) new_id = self.add_thought(improved, parents=[thought_id]) return new_id3.2.4 思维图实战案例:文档写作
写作任务天然适合思维图建模,因为不同章节可以并行发展,最后聚合为完整文档。
写作任务:撰写一篇关于AI伦理的文章 思维图结构: [主题确定:AI伦理] | ┌────────────────┼────────────────┐ ↓ ↓ ↓ [隐私问题] [偏见与公平] [责任归属] | | | [数据收集] [训练数据偏见] [AI决策透明度] [数据使用] [算法公平性] [人类监督] | | | └────────────────┼────────────────┘ ↓ [章节聚合] | [综合讨论] | [结论与建议] 关键操作: 1. 三个主题并行探索(分支) 2. 各主题下深入展开(改进链) 3. 整合为完整文章(聚合)3.2.5 思维图与思维树的对比
特性 思维树 (ToT) 思维图 (GoT) 拓扑结构 树形(单父节点) 任意有向图 思维合并 不支持 支持聚合操作 循环 不支持 支持 复杂度 较低 较高 适用场景 探索性问题 需要综合的问题 计算成本 中等 较高
2.6 思维链的数学基础与理论解释
2.6.1 为什么思维链有效?——理论视角
思维链的有效性可以从多个理论角度解释:
计算复杂性视角
从计算复杂性理论来看,某些问题在固定计算深度下无法解决。思维链实际上将线性深度的计算"展开"到序列中,使得模型能够模拟更深的计算图。
传统前向传播: 输入 → [固定L层] → 输出 计算深度 = L 思维链: 输入 → [L层] → token1 → [L层] → token2 → ... → 输出 有效计算深度 = L × 序列长度贝叶斯推理视角
可以将思维链视为一种近似贝叶斯推理。每一步推理都更新模型对最终答案的"信念"。
P(答案|问题) = ∫ P(答案|推理路径) × P(推理路径|问题) d推理路径思维链显式地采样并评估了这些推理路径。
注意力机制视角
在Transformer中,后生成的token可以attend到之前生成的所有token。这意味着后续的推理步骤可以"看到"并利用之前的推理结果。
步骤1的输出:[计算中间值A] 步骤2的输出:[使用A计算B] ← 可以attend到步骤1 步骤3的输出:[使用B计算C] ← 可以attend到步骤1和2 ...2.6.2 思维链的局限性理论
不可判定性问题
某些问题本质上是不可计算的(如图灵停机问题)。思维链无法突破这一理论限制。
上下文窗口限制
对于需要O(n)或更多步骤的问题,思维链可能超出上下文窗口。这是一个实际问题,而非理论限制。
错误累积
思维链的每一步都有可能出错。对于需要n步的推理,假设每步正确率为p,则整体正确率为p^n。
例如:如果每步正确率p = 0.95,需要10步 整体正确率 = 0.95^10 ≈ 0.60(仅60%)2.6.3 最优思维链长度
研究者发现,思维链的长度存在最优点:
- 过短:推理不充分,容易出错
- 过长:增加出错机会,消耗更多tokens
- 最优:足够覆盖关键推理步骤,但不冗余
经验法则
最优长度 ≈ log(问题复杂度) × 关键步骤数示例
问题:23 × 47 = ? 过短的CoT: 23 × 47 = 1081(直接给出,可能出错) 适中的CoT: 23 × 47 = 23 × 40 + 23 × 7 = 920 + 161 = 1081(正确) 过长的CoT: 让我详细分析这个乘法问题。 首先,23是一个质数... 47也是一个质数... 让我使用分配律... (冗余信息增加出错概率)2.6.4 思维链与涌现能力
思维链是大型语言模型**涌现能力(Emergent Abilities)**的典型例子。研究发现,思维链的效果在模型规模超过一定阈值后才显著提升。
规模效应曲线
准确率 │ 100%├─────────────────────●●●● │ ●●● 80%├ ●● │ ● 60%├ ● │ ● 40%├ ● │ ● 20%├ ● │● 0├──┬──┬──┬──┬──┬──┬──┬── 1B 10B 30B 70B 175B 540B 模型参数量这一发现被称为"相变"现象:模型在某规模之前几乎无效,之后突然变得有效。
为什么需要大规模?
- 知识广度:大规模模型见过更多推理模式
- 模式匹配:能更好地识别问题类型并选择合适的推理策略
- 指令遵循:更可靠地遵循"一步步思考"的指令
- 错误修正:有更多能力在推理中自我修正
本章小结
思维链(Chain-of-Thought)是提示工程领域最重要的发现之一。它通过要求模型展示推理过程,显著提升了复杂推理任务的性能。
关键要点:
-
核心原理:思维链让模型从"直觉回答"转向"逐步推理",激活了更深层的计算能力。
-
主要变体:
- 零样本CoT:简单添加"让我们一步步思考"
- 少样本CoT:提供推理示例
- 自洽性CoT:多数投票提高准确率
-
适用场景:数学推理、常识推理、符号推理、复杂决策
-
局限性:知识缺口、精确记忆、纯计算、过度推理
-
高级技术:Least-to-Most、Decomposed、Plan-and-Solve等变体进一步扩展了CoT的能力
在下一章,我们将探索更高级的推理技术,包括思维树、思维图和自我反思等方法,这些方法建立在思维链的基础上,但采用了更复杂的推理架构。
参考文献:
- Wei, J., et al. (2022). Chain-of-Thought Prompting Elicits Reasoning in Large Language Models. arXiv:2201.11903
- Wang, X., et al. (2022). Self-Consistency Improves Chain of Thought Reasoning in Language Models. arXiv:2203.11171
- Kojima, T., et al. (2022). Large Language Models are Zero-Shot Reasoners. arXiv:2205.11916
- Zhou, D., et al. (2022). Least-to-Most Prompting Enables Complex Reasoning in Large Language Models. arXiv:2205.10625
- Diao, S., et al. (2023). Active Prompting with Chain-of-Thought for Large Language Models. arXiv:2302.12246
第一章:提示工程基础与演进
在人工智能的发展历程中,我们与机器的交互方式经历了深刻变革。从早期的命令行界面到图形用户界面,再到自然语言交互,每一次范式转变都极大地扩展了技术的可及性。大语言模型的出现标志着这一演进的最新里程碑——我们终于可以用自然语言与AI系统进行复杂、开放式的对话。然而,这种交互的效率和效果,在很大程度上取决于我们如何"提问"。这正是提示工程(Prompt Engineering)的核心所在。
1.1 从命令到对话:交互范式的转变
1.1.1 传统编程与自然语言交互
传统软件开发模式要求我们学习特定的编程语言和框架,用精确的语法规则表达我们的意图。一段代码要么编译通过并产生预期结果,要么因为语法错误而失败。这种交互方式虽然强大,但门槛较高,只有经过专业训练的人才能有效使用。
大语言模型改变了这一范式。我们不再需要学习正式的编程语言,而是可以用日常语言描述我们想要完成的任务。模型会尝试理解我们的意图,并生成相应的响应。这种交互更加自然,但同时也带来了新的挑战:
模糊性:自然语言天生具有歧义性。同一个词在不同上下文中可能有不同的含义,同一个请求可能被不同人理解为不同的意图。
隐含假设:我们往往有许多不言而喻的背景知识和期望,这些信息对AI模型来说并不总是显而易见的。
评估困难:不像编译错误那样明确,模型输出的"好"与"坏"往往是主观的、依赖上下文的。
1.1.2 提示的涌现
“提示”(Prompt)一词来源于戏剧中的"提词",指的是给演员的提示性词语。在LLM语境下,提示是我们提供给模型的输入文本,它引导模型生成我们期望的输出。
早期的语言模型(如GPT-2)主要被用作"续写"工具:给定一段文本,模型会继续写下去。但随着模型规模的扩大,研究人员发现,通过精心设计输入文本,可以让模型执行各种任务——翻译、摘要、问答、推理,甚至代码生成。这种现象被称为"上下文学习"(In-Context Learning),它意味着模型不需要更新参数,仅通过提示就能适应新任务。
1.1.3 提示工程的诞生
2020年,GPT-3的发布标志着提示工程作为一个研究方向的正式诞生。OpenAI的论文展示了通过设计不同的提示,GPT-3能够完成从数学推理到创意写作的各种任务。更重要的是,论文发现模型的能力会随着提示设计的改进而显著提升。
此后,提示工程迅速发展成为一个活跃的研究领域。研究人员提出了各种提示技术和设计模式,从业者分享了他们的实践经验,企业开始招聘专门的"提示工程师"。提示工程成为连接大模型能力与实际应用的桥梁。
1.2 提示工程的核心原则
1.2.1 清晰性原则
最基本的原则是:清晰地表达你的意图。这听起来显而易见,但在实践中却是最常见的失败原因。
问题示例:
写一篇关于AI的文章。这个提示过于模糊。什么样的AI?技术导向还是伦理讨论?多长的文章?什么风格?什么受众?
改进版本:
请写一篇面向高中生的科普文章,介绍生成式AI(如ChatGPT)的基本原理。 文章长度约800字,使用通俗易懂的语言,可以适当使用比喻。 结构包括:什么是生成式AI、它如何工作、有哪些应用、未来可能的发展方向。1.2.2 具体性原则
提供足够的细节和约束。细节不仅帮助模型理解你的需求,还能限制搜索空间,提高输出的一致性。
问题示例:
帮我改进这段代码。改进版本:
请帮我改进以下Python代码,重点关注: 1. 代码可读性(添加注释、改进命名) 2. 性能优化(减少不必要的循环) 3. 错误处理(添加try-except) 代码: [原始代码] 请提供改进后的完整代码,并解释主要修改点。1.2.3 上下文原则
提供必要的背景信息。模型没有你的记忆、专业知识或当前任务的上下文。你需要提供这些信息。
示例:
我正在开发一个电商网站的购物车功能(使用React + TypeScript)。 用户反馈说购物车数量更新有延迟感。 以下是相关代码: [代码] 请分析可能的原因,并提供优化建议。1.2.4 示例原则
通过示例展示你期望的输出格式。这就是"Few-shot"学习的基础。
示例:
请将以下产品描述转换为结构化的产品特性列表。 示例输入: "这款无线蓝牙耳机采用主动降噪技术,续航时间长达30小时, 支持IPX7级防水,配有Type-C快充接口。" 示例输出: - 耳机类型:无线蓝牙 - 降噪功能:主动降噪 - 续航时间:30小时 - 防水等级:IPX7 - 充电接口:Type-C快充 请处理以下输入: [你的产品描述]1.2.5 迭代原则
提示工程是一个迭代过程。第一次尝试通常不会完美,需要根据结果不断调整。
迭代策略:
- 从简单提示开始
- 观察输出,识别问题
- 添加约束、示例或更详细的指令
- 再次测试
- 重复直到满意
1.3 Zero-shot与Few-shot学习
1.3.1 Zero-shot提示
Zero-shot提示是指不给模型提供任何任务示例,仅通过指令描述任务。这种方式依赖于模型在预训练中获得的知识。
将以下英文句子翻译成中文: "The quick brown fox jumps over the lazy dog."Zero-shot的优势:
- 简单直接
- 适用于模型已经有相关能力的任务
- 不需要准备示例数据
Zero-shot的局限:
- 对于复杂或新颖的任务效果有限
- 输出格式可能不一致
- 可能误解任务意图
1.3.2 Few-shot提示
Few-shot提示通过提供少量示例,帮助模型理解任务的具体要求和期望的输出格式。
情感分析任务,判断评论的情感倾向(正面/负面/中性)。 评论:"这家餐厅的服务太差了,等了一个小时才上菜。" 答案:负面 评论:"产品质量很好,性价比很高,推荐购买。" 答案:正面 评论:"还行吧,没什么特别的。" 答案:中性 评论:"物流很快,包装也很仔细,但是尺码偏大。" 答案:Few-shot的优势:
- 明确任务格式
- 提高输出一致性
- 减少歧义理解
Few-shot的最佳实践:
- 示例数量:通常2-5个示例效果较好,过多可能引入噪声
- 示例质量:示例应该准确、一致、具有代表性
- 示例多样性:覆盖不同的输入模式和边缘情况
- 示例顺序:最近的示例对模型影响最大
1.3.3 Zero-shot与Few-shot的选择
因素 选择Zero-shot 选择Few-shot 任务常见度 常见任务(翻译、摘要) 新颖或特定任务 输出格式要求 灵活 严格格式要求 示例可用性 无示例可用 有高质量示例 上下文空间 紧张 充足 调试阶段 初步探索 精细调优 1.4 提示模板设计模式
1.4.1 角色设定模式
通过设定特定角色,引导模型采用相应的视角和专业风格。
你是一位资深软件架构师,拥有15年的分布式系统设计经验。 请从可扩展性、可用性、性能三个角度分析以下系统设计: [系统描述] 请给出详细分析报告,包括: 1. 当前设计的优势 2. 潜在的问题和风险 3. 改进建议角色设定的作用:
- 激活模型中相关的专业知识
- 设定回答的语气和风格
- 建立评估标准
1.4.2 任务分解模式
将复杂任务分解为一系列子步骤。
请按以下步骤分析这篇文章: 步骤1:识别文章的主题和核心论点 步骤2:列出作者使用的主要论据 步骤3:评估论据的可靠性和相关性 步骤4:指出可能的逻辑谬误或弱点 步骤5:给出总体评价和改进建议 文章内容: [文章]1.4.3 输出控制模式
明确指定输出的格式、结构和风格。
请分析以下代码的时间复杂度和空间复杂度。 输出格式要求: ## 函数名 - 时间复杂度:O(?) - 空间复杂度:O(?) - 分析过程:[简要说明] 代码: [代码]1.4.4 约束设定模式
明确指出应该避免什么。
请解释什么是量子计算。 要求: - 使用非技术语言,面向普通读者 - 不要使用专业术语,或使用时给出解释 - 不要超过300字 - 不要涉及复杂的数学公式1.4.5 思维链模式
引导模型展示推理过程(将在第二章详细讨论)。
请逐步思考这个问题,展示你的推理过程: 问题:[问题描述] 请按以下格式回答: 1. 理解问题:[重述问题] 2. 分析要素:[列出关键信息] 3. 推理过程:[逐步推理] 4. 最终答案:[结论]1.5 常见陷阱与避坑指南
1.5.1 过度信任
问题:假设模型总是正确的,不进行验证。
案例:模型可能会自信地给出错误的事实、编造不存在的引用、或者提供有bug的代码。
解决方案:
- 对关键信息进行交叉验证
- 要求模型提供来源或解释推理过程
- 使用"自查"提示让模型审视自己的答案
1.5.2 指令冲突
问题:提示中包含相互矛盾的指令。
案例:
请简要总结这篇文章,同时详细说明每个段落的要点。"简要"和"详细说明每个段落"相互矛盾。
解决方案:
- 检查提示中是否存在冲突的指令
- 明确优先级
- 分阶段处理复杂需求
1.5.3 隐含假设未表达
问题:假设模型知道只有你自己知道的背景信息。
案例:
帮我改进这个函数。没有说明改进的目标(性能?可读性?安全性?)。
解决方案:
- 想象你在向一个不了解项目的新同事解释
- 明确说明所有约束、目标和背景
1.5.4 过长或过短的提示
过长提示的问题:
- 模型可能"遗忘"早期部分
- 增加成本
- 可能引入噪声
过短提示的问题:
- 信息不足
- 模型需要猜测意图
解决方案:
- 找到信息密度和长度的平衡
- 将关键信息放在提示的开头或结尾
- 使用结构化格式提高可读性
1.5.5 负面约束的失败
问题:告诉模型"不要做某事"往往不如告诉它"要做什么"有效。
案例:
不要使用太专业的词汇。模型可能会先想到"专业词汇"再尝试避免,反而增加了使用概率。
解决方案:
请使用通俗易懂的语言,适合高中生阅读水平。1.5.6 顺序效应
问题:提示中信息的顺序会影响模型的理解和输出。
现象:
- 模型更关注提示的开头和结尾
- 示例的顺序可能影响模型对任务的"中心"理解
解决方案:
- 将最重要的指令放在开头
- 将关键示例放在最后
- 使用编号或结构化格式强调重要性
1.6 提示工程的理论基础
1.6.1 为什么提示工程有效?
理解提示工程的有效性需要回顾大语言模型的训练过程:
预训练:模型在海量文本上学习预测下一个token。这个过程让模型:
- 学习了语言的统计规律
- 获得了关于世界的知识
- 掌握了各种任务的隐式表示
提示作为条件:当我们提供提示时,我们实际上是在设定一个条件,告诉模型"在什么样的上下文中生成文本"。提示引导模型检索相关的知识,激活相应的"能力"。
上下文学习:提示中的示例作为上下文,让模型能够"在推理时学习"新的模式,而无需更新参数。
1.6.2 预训练-提示对齐
模型的能力与预训练数据相关。如果某个任务与预训练数据中的模式高度相似,zero-shot就能工作得很好。如果任务比较新颖,few-shot示例可以帮助模型"桥接"到已有的能力。
实践启示:
- 了解模型在什么样的数据上训练过
- 将任务表述为与预训练数据相似的格式
- 如果任务非常特殊,可能需要更多的示例或更详细的指令
1.6.3 注意力机制的影响
Transformer模型的注意力机制意味着,提示中的不同部分对输出的影响不同。模型会"关注"与当前生成最相关的部分。
实践启示:
- 确保关键信息清晰可见
- 避免冗余信息分散注意力
- 利用格式(如项目符号)引导注意力
1.6.4 采样与随机性
模型输出是通过从概率分布中采样生成的。温度(temperature)参数控制随机性:
- 低温度(如0.1):更确定性的输出,偏向高概率token
- 高温度(如0.8):更多样化的输出,增加创意但可能降低准确性
实践启示:
- 事实性任务使用低温度
- 创意性任务使用高温度
- 需要一致性输出时固定随机种子
小结
提示工程是与大语言模型有效交互的艺术和科学。它要求我们理解模型的工作原理,掌握表达意图的技巧,并通过迭代不断优化。
本章介绍了提示工程的基础:从交互范式的演进出发展,我们了解到提示工程是如何随着大语言模型的发展而自然涌现的;核心原则——清晰性、具体性、上下文、示例和迭代——为我们设计有效提示提供了指导;Zero-shot和Few-shot是两种基本的提示策略,各有适用场景;提示模板设计模式——角色设定、任务分解、输出控制、约束设定——是实践中可复用的解决方案;常见陷阱提醒我们避免过度信任、指令冲突等问题;理论基础帮助我们理解为什么提示工程有效,从而更系统地设计提示。
在接下来的章节中,我们将深入探讨更高级的提示技术,从思维链推理到工具调用,从结构化设计到自动化优化。每一章都将建立在这些基础之上,帮助你成为真正的提示工程专家。
关键要点回顾:
- 提示工程是连接大模型能力与实际应用的桥梁
- 核心原则:清晰、具体、提供上下文、使用示例、持续迭代
- Zero-shot适用于常见任务,Few-shot适用于特定或复杂任务
- 常见陷阱包括过度信任、指令冲突、隐含假设未表达
- 理解模型的工作原理有助于设计更有效的提示
