上下文工程(Context Engineering)

最近随着大模型相关技术的演进和迭代,尤其是随着各种AI Agent的不断涌现,工程师们对AI工程技术又有了新的理解,于是“上下文工程”这个新的概念横空出世。
我非常喜欢上下文工程这个术语,它听起来更加系统和广泛,这让人以下就可以联想到,开发智能体或者知识助手时,提升AI输出质量所做的一切工作。

什么是上下文工程

那么什么是上下文工程呢?一开始我也非常好奇,但是随着我不断深入的了解,我发现它并不是完全新的技术,反而它包括的技术都是我所熟悉的,更加准确的说,“上下文工程” 是我们面向大模型开发服务时,所用的一系列技术的代名词,原来我们所用的一系列技术散落在各个角落,现在有了上下文工程的概念,这些技术被统一起来,同时有了统一的目标。

上下文工程(Context Engineering)是一个新兴的、至关重要的领域,尤其在大型语言模型(LLM)时代。它指的是系统性地设计、构建和优化输入给 AI 模型(特别是 LLM)的上下文(Context),以引导模型生成更准确、更相关、更符合预期的输出的一系列方法和实践。

你可以将其理解为一种“AI 沟通的艺术与科学”。我们不是在修改模型本身(那属于模型训练或微调),而是在优化我们与模型“对话”的方式。这个“对话”的输入,就是我们所说的“上下文”。

一个简单的类比是:向一位知识渊-博但没有特定背景信息的专家提问。

  • 糟糕的上下文: “给我写个关于车的故事。” (专家可能会写一个关于马车、F1赛车或者未来飞行汽车的故事,完全不符合你的预期)。

  • 优秀的上下文(经过上下文工程): “你是一位专业的汽车杂志编辑,为一本面向家庭读者的杂志撰写一篇短文。请以一位父亲的视角,讲述他如何选择第一辆七座家用 SUV 的经历。文章需要突出安全性、空间和燃油经济性,风格要温馨、幽默。字数在800字左右。” (专家现在有了清晰的角色、目标受众、主题、关键点、风格和格式要求,能够写出非常贴切的内容)。

上下文工程的核心组成部分

上下文工程通常包含以下几个关键部分。

提示词工程(Prompt Engineering)

这是上下文工程最基础、最核心的部分。它专注于设计和优化直接输入给模型的指令文本(即“提示词”)。提示词工程包括了一系列相关提示词的技术:

  • 明确指令(Clear Instruction): 清晰地告诉模型要做什么,避免模糊不清的词语。
  • 角色扮演(Role-playing): 让模型扮演一个特定角色(如“你是一位资深律师…”)。
  • 提供示例(Few-shot Learning): 给出几个输入和输出的范例,让模型学习并模仿。
  • 思维链(Chain-of-Thought, CoT): 引导模型一步一步地思考,将复杂问题分解,从而得出更可靠的结论。
  • 设定输出格式(Format Specification): 要求模型以特定格式输出,如 JSON、Markdown 表格、HTML 等。

    比如以下提示词是应用了提示词工程方法的案例,用来生成校验密码强度的函数:

    # 角色
  你是一位专注于网络安全的高级 Python 工程师。

  # 任务
  编写一个名为 validate_password_strength 的 Python 函数,该函数接收一个字符串作为密码,并返回一个包含两部分的 JSON 对象:
  1. isValid (布尔值): 指示密码是否满足所有规则。
  2. reasons (字符串列表): 如果 isValid 为 false,列出所有不满足的规则。

  # 思维链 (Chain-of-Thought) 指导
  在生成代码前,请先按以下步骤思考:
  1.  **定义规则:** 密码必须满足以下所有条件:
      * 最小长度为 12 个字符。
      * 至少包含一个大写字母。
      * 至少包含一个小写字母。
      * 至少包含一个数字。
      * 至少包含一个特殊字符(例如 !@#$%^&*)。
  2.  **设计逻辑:** 创建一个 reasons 列表。逐条检查上述规则,若不满足,则将对应的失败原因(英文描述)添加到列表中。
  3.  **确定最终结果:** 如果 reasons 列表为空,则 isValid 为 true,否则为 false。
  4.  **构建 JSON 输出:** 根据 isValidreasons 的最终值,构建并返回所需的 JSON 格式。

  # 开始生成代码

检索增强生成(Retrieval-Augmented Generation, RAG)

当模型的内部知识不足(比如,对于最新的信息、私有领域的知识库或非常专业的内容)时,RAG 就显得尤为重要,它极大地减少了模型“胡说八道”(幻觉)的概率,提高了答案的准确性和时效性,并且可以引用信息来源。

  • 检索(Retrieve): 当用户提出问题时,系统首先从一个外部的知识库(如公司的内部文档、数据库、网站等)中检索最相关的信息片段。
  • 增强(Augment): 将检索到的这些信息片段,连同用户的原始问题,一起整合到提示词中。
  • 生成(Generate): 将这个“增强后”的上下文发送给 LLM,让它基于这些最新、最相关的“外部知识”来生成答案。

此处通过一个示例来展示 RAG 的工作流程:

假设你的公司有一个自研的部署平台叫“Phoenix”,任何公开的 LLM 都不可能知道它的细节。

场景: 一位新员工问:“如何用 Phoenix 平台回滚一次部署?”

RAG 工作流:

  • 查询(Query): 用户输入问题 “How to roll back a deployment with Phoenix?”。

  • 检索(Retrieve):

    系统首先将该问题通过 embedding 模型(如 text-embedding-ada-002)转换为一个向量。

    然后,在存储了公司所有内部技术文档(Confluence, Wiki 等)的向量数据库(如 Pinecone, Chroma)中,执行相似性搜索。

    搜索返回了最相关的几个文档片段,例如文档 "Phoenix CLI v2.1 Reference" 中的一段:“To initiate a rollback, use the command phoenix deployment rollback –deployment-id –target-version . You can find the deployment ID using phoenix deployment list…”

  • 增强(Augment): 系统动态构建一个新的、增强的上下文。


# 上下文信息
# 文档来源: Phoenix CLI v2.1 Reference
---
To initiate a rollback, use the command phoenix deployment rollback --deployment-id <ID> --target-version <VERSION>. You can find the deployment ID using phoenix deployment list.
---

# 用户问题
用户问:如何用 Phoenix 平台回滚一次部署?

# 指令
请仅基于以上提供的上下文信息,回答用户的问题。
  • 生成(Generate): LLM 接收到这个增强的上下文,会生成一个精准、基于事实的回答:“要使用 Phoenix 平台回滚部署,你可以使用 phoenix deployment rollback 命令…”,而不是编造一个虚假的命令。

上下文构建与管理(Context Construction & Management)

这部分关注的是如何动态地、智能地构建和维护整个上下文窗口(Context Window)。LLM 的输入长度是有限的(即上下文窗口),如何有效利用这个有限的空间至关重要。

  • 上下文压缩(Context Compression): 在保持关键信息的同时,删减不重要或冗余的内容,以节省空间。
  • 对话历史管理(Conversation History Management): 在多轮对话中,如何有效地总结和管理之前的对话历史,确保对话的连贯性,同时避免上下文窗口被陈旧信息占满。
  • 动态上下文注入(Dynamic Context Injection): 根据对话的进展或用户的行为,实时地从外部源(如用户画像数据库、实时传感器数据等)拉取信息并注入到上下文中。

记忆机制(Memory Systems)

  • 短期记忆:维护当前会话状态、任务链信息。
  • 长期记忆:保存跨会话历史、用户偏好,通过检索机制注入上下文中

工具调用

在对话中根据任务需求调用外部接口/API,例如日历查询、数据库检索等,并将结果动态注入上下文。

提示词工程过时了么?

最近看到了一种观点,有了上下文工程,提示词工程将过时了。我可以肯定的回答,至少目前来看,这是一种完全错误的认知和引导,这种观点没有建立在对上下文工程的深入理解和认知上。

提示词工程不仅不会过时,它反而是上下文工程不可或缺的基石。

更准确地说,两者的关系是“包含与演进”,而非“替代与淘汰”。上下文工程是一个更宏大、更系统化的框架,而提示词工程是这个框架中至关重要的执行层。

我们可以用一个类比来理解:可以将两者的关系类比为 SQL 查询 与 数据库架构设计。

  • 提示词工程 (Prompt Engineering) 就像是编写高效、精确的 SQL 查询。你需要懂得语法、技巧(如 JOIN, WHERE, GROUP BY),以从数据库中获取你想要的确切数据。这项技能永远不会过时,因为你总需要从数据库中拿数据。
  • 上下文工程 (Context Engineering) 则像是 数据库架构设计。它关注的是整个数据系统的搭建,包括设计表结构、建立索引(类似 RAG 中的向量索引)、管理数据关系、进行性能优化等。一个好的架构能让你更容易写出高效的 SQL,并确保整个系统的稳定和可扩展。

你不可能只懂数据库架构而不懂如何写 SQL 查询。同理,一个完整的上下文工程策略,离不开底层的提示词工程技术。

为什么提示词工程不会过时,而是被整合和升级了呢?

  • 它是与 LLM 交互的“原子操作”。无论你的系统多么复杂,在“最后一步”(The Last Mile),你总是需要将所有信息整合成一个最终的提示词(Prompt)发送给 LLM。这个最终提示词的质量,直接决定了输出的成败。

    • 在 RAG 中: 当你从知识库检索到5个相关文档片段后,如何将这些片段、用户的原始问题、以及行为指令(例如:“请仅根据以上信息回答”、“总结要点”)高效地组合成一个能让 LLM 精准理解的最终提示词?这本身就是一项高级的提示词工程任务。一个糟糕的组合方式可能会让模型感到困惑,忽略掉关键信息。
    • 在 Agent 应用中: 当一个 AI Agent 需要决定下一步使用哪个工具时,它背后往往是一个“元提示词”(Meta-Prompt)在引导它思考。这个元提示词的设计(例如,使用 ReAct 或其他思维链模式)是纯粹的提示词工程。
  • 上下文工程的“组件”需要提示词来驱动。上下文工程的很多策略,本身就是由提示词来执行的。

    • 对话历史摘要: 在管理上下文窗口时,一种常用策略是让 LLM 自身去“总结”之前的对话。那么,你用来指令 LLM 进行总结的那个请求——“请将以下对话总结为包含关键实体和用户意图的摘要”——就是一个需要精心设计的提示词。
    • 数据提取与格式化: 当你希望 LLM 从一段非结构化文本中提取信息并以 JSON 格式输出时,你用来定义 JSON 结构、提供示例、下达指令的文本,同样是提示词工程的范畴。
  • 技能的演进:从“手工作坊”到“系统化工程”。我们可以说,早期的“提示词工程”更像是一种经验性的、有点“炼丹”感觉的手工作坊模式。而“上下文工程”则是将这些成功的经验和模式, systematize(系统化)、industrialize(工业化),形成了一套更可靠、更具扩展性的工程方法论。

    • 过去: 一个“提示词工程师”可能花大量时间在一个独立的 Playground 里调试一个完美的提示词。
    • 现在与未来: 他的工作台变成了一个完整的系统。他不仅要设计单个提示词,还要思考这个提示词如何与外部知识库(RAG)、对话管理器、工具调用等其他系统模块协同工作。他的技能要求从“写好一句话”扩展到了“设计好整个对话流”。

上下文工程-面向AI的软件工程

传统的软件系统是通过程序员在键盘上飞舞的双手,一行行敲击来构筑的,为了构建稳定,可靠,强扩展的应用程序,架构师,软件工程师和测试工程师通力合作,他们应用了架构模式,设计模式,API设计规范,测试技术等一系列软件工程技术,来生产更加稳定可靠的系统。但是随着AI大模型的发展,我们正在见证着传统软件向智能化软件进化的历史进程,对于如何实现可靠的智能化软件系统,AI工程师们也在不断探索和实践。上下文工程正在基于这种可靠软件系统的诉求应用而生,这也成为一种历史必然。

通过上下文工程带来如下好处:

  • 提升模型性能和准确性: 这是最直接的好处。好的上下文可以显著减少模型的错误和幻觉,让输出结果更贴近事实和用户需求。

  • 降低成本和复杂性: 相比于重新训练(Re-training)或微调(Fine-tuning)一个庞大的语言模型,上下文工程的成本要低得多,实施起来也更快速、更灵活。它允许我们在不改变模型底层的情况下,适配各种不同的应用场景。

  • 增强可控性和可解释性: 通过 RAG 等技术,我们可以知道模型是依据哪些信息来生成答案的,这增强了系统的透明度和可信度。同时,通过精心设计的提示词,我们可以更好地控制模型的输出风格、语气和内容。

  • 实现个性化和动态适应: 上下文工程使得 AI 应用能够整合实时的、个性化的用户信息,提供千人千面的服务。例如,一个 AI 客服可以根据用户的历史购买记录(通过 RAG 检索得到)提供更有针对性的建议。

如果说大型语言模型是强大的“引擎”,那么上下文工程就是设计精良的“驾驶舱”和“导航系统”。它决定了我们如何驾驭这股强大的力量,将其引导到正确的方向,去完成具体、有价值的任务。

深入解析Reflexion提示词模式

深入解析Reflexion提示词模式

摘要

本报告旨在对Reflexion提示词模式进行深入而全面的阐述。Reflexion是一种新颖的框架,通过语言反馈而非模型权重更新来强化语言智能体,使其能够通过自我反思和经验记忆来优化决策和行为。报告将详细介绍Reflexion的核心概念、工作原理、关键组件(Actor、Evaluator、Self-Reflection)、迭代自我纠正机制,并探讨其在复杂推理、编程和决策制定等任务中的显著优势。此外,报告还将Reflexion与Chain-of-Thought (CoT) 和 Tree of Thoughts (ToT) 等相关提示词技术进行比较,并分析其潜在的局限性与挑战。最后,报告将特别探讨Reflexion及其相关反思技术在缓解LLM幻觉问题上的贡献,并对未来的发展方向进行展望。

引言

大型语言模型(LLM)在理解和生成人类语言方面取得了突破性进展,其应用已广泛渗透到文本创作、机器翻译、智能问答等多个领域。然而,尽管能力强大,LLM在处理复杂逻辑推理、执行多步骤任务、避免生成不准确或虚构信息(即幻觉)以及实现持续自主学习方面,仍面临着固有的挑战。这些挑战限制了LLM在更复杂、更关键应用场景中的可靠性和效用。

在此背景下,提示词工程作为引导和优化LLM行为的关键手段,其重要性日益凸显。通过精心设计的指令和上下文,提示词工程能够有效提升模型输出的质量,并帮助模型克服上述挑战。Reflexion提示词模式正是在这一发展趋势下应运而生的一种创新方法。它独特地通过“语言反馈”机制而非传统的模型参数更新来增强LLM的自我改进能力 ,从而模拟人类从经验中学习并不断进步的过程。

本报告将对Reflexion提示词模式进行系统性、深入的剖析。报告将首先阐述其核心定义和基本原理,随后详细解析其内部的工作机制和关键组件。接着,将探讨Reflexion在实际应用中的显著优势和典型案例,并将其与现有主流的高级提示词技术(如Chain-of-Thought和Tree of Thoughts)进行对比分析。报告还将审视Reflexion当前面临的局限性与挑战,并特别关注其在减少LLM幻觉方面的潜在贡献。最终,报告将对Reflexion的未来发展方向进行展望,旨在为读者提供一个全面、深入且具有实践指导意义的Reflexion提示词模式视图。

Reflexion提示词模式概述

定义核心概念

Reflexion提示词模式,由Shinn等人于2023年提出,是一种新颖的框架,其核心在于通过语言反馈而非直接更新模型权重来强化语言智能体 。这一范式被其提出者描述为一种“口头强化”(verbal reinforcement)机制,它将智能体的策略参数化为记忆编码与LLM参数选择的结合 。

Reflexion的核心运作方式在于其独特的语言反馈机制。它能够将来自环境的反馈信号——这些信号可以是简单的标量值(例如,任务成功或失败的二进制指示),也可以是更具描述性的自由形式语言——转化为一种特殊的语言形式,即“自我反思” 。这种自我反思随后被作为额外的上下文信息,输入到LLM智能体中,以指导其在后续尝试中做出更优的决策 。

这种机制的设计理念与人类学习和改进的方式高度相似 。正如人类会反思过去的错误、总结经验教训并将其知识融入未来的决策以持续改进表现,Reflexion也赋予了智能体类似的能力。通过这种方式,智能体能够以更具解释性的方式理解其行为的成功与失败,从而实现自我引导的性能提升。

Reflexion与传统强化学习或模型微调方法的根本区别在于其不依赖于模型权重的更新。传统的强化学习通常需要通过梯度下降等方式修改模型参数,这往往伴随着高昂的计算成本和大量数据需求 。Reflexion则提供了一种轻量级且计算效率更高的替代方案,避免了昂贵的模型重新训练或微调过程 。这种不更新权重的语言强化范式,使得AI的改进不再局限于模型训练阶段,而可以延伸到推理和交互阶段,从而显著降低了计算成本和数据需求,使得AI系统能够更快速、更灵活地适应新情境和纠正错误。

背景与目的

Reflexion的提出背景源于对LLM自我纠正能力的需求以及对传统强化学习局限性的考量 。传统的LLM在处理需要多步骤规划、复杂逻辑推理或迭代修正的任务时,往往面临挑战,因为它们缺乏明确的结构化纠错机制或长期记忆来指导其行为 。标准提示词方法通常直接生成响应,缺乏分解任务或自我修正的能力,这使其在应对复杂推理或多步骤任务时表现不佳 。

Reflexion的设计灵感来源于人类的认知过程,特别是人类如何进行自我纠正和迭代学习 。正如人类在解决问题时,通常会先尝试一个初步方案,然后根据反馈(无论是内部的自我反思还是外部的评价)进行迭代修订,直到找到满意的解决方案,Reflexion也试图赋予LLM类似的学习和适应能力 。这种对人类认知模式的模仿不仅是设计理念上的优势,也间接提升了系统的可解释性。当LLM通过语言进行“自我反思”时,这些反思文本实际上构成了其学习过程的“可解释日志”,这与传统强化学习的黑箱特性形成鲜明对比。这种透明度对于AI的信任、调试和合规性至关重要,尤其是在高风险应用领域。

Reflexion的核心目的在于通过其独特的迭代自我评估和自我反思循环,显著提升语言智能体在各种复杂任务中的性能。这些任务包括但不限于顺序决策、复杂的编程问题和高级语言推理 。其性能提升的显著性体现在具体案例中:例如,Reflexion在HumanEval编码基准测试中取得了高达91%的pass@1准确率,这一成绩显著超越了此前最先进的GPT-4所实现的80%准确率 。这不仅证明了Reflexion在代码生成方面的强大能力,也确立了其在特定任务领域的领先地位。通过这种方式,Reflexion旨在使LLM能够持续演进和学习,应对复杂动态的现实世界挑战 。

工作原理与执行流程

Reflexion框架的强大之处在于其模块化设计和迭代循环,它由三个相互协作的独立模型组成,这些模型共同实现其迭代学习和自我纠正能力 。

核心组件:Actor, Evaluator, Self-Reflection

  • Actor (执行者):
    Actor是Reflexion智能体的“执行大脑”,其核心职责是根据从环境中获得的观察生成具体的文本输出并执行相应的动作 。在一次尝试中,Actor在环境中采取行动,并接收相应的观察结果。这一系列动作和观察共同构成了一个“轨迹”(trajectory),代表了智能体在本次尝试中的完整行为序列 。值得注意的是,Reflexion并非从零开始构建新的语言模型,而是巧妙地利用了现有先进的提示词技术。具体而言,Chain-of-Thought (CoT) 和 ReAct 等技术被用作Actor模型的基础,这表明Reflexion是建立在这些有效技术之上的高级扩展 。此外,Actor内部集成了一个记忆组件,用于存储和提供额外的上下文信息。这有助于智能体在生成动作和文本时,能够利用更丰富的背景知识,从而做出更明智的决策 。

  • Evaluator (评估者):
    Evaluator是Reflexion框架的“批判性思维”部分,其核心职责是对Actor生成的输出进行客观评分 。它接收Actor生成的完整轨迹(也称为短期记忆)作为输入,并基于预设的评估标准输出一个量化的奖励分数,以衡量其表现的优劣 。根据不同任务的性质,Evaluator可以采用多种奖励函数。这包括使用LLM自身进行判断性评估(例如,让LLM判断代码是否正确,或答案是否符合预期),或者采用基于规则的启发式方法进行决策评估,以确保评估的准确性和相关性 。

  • Self-Reflection (自我反思者):
    Self-Reflection模型是Reflexion框架的“学习和改进引擎”,其主要功能是生成口头形式的强化提示(verbal reinforcement cues),以帮助Actor进行自我改进 。这一关键角色通常由另一个LLM来承担,它负责分析过去的表现并提供有价值的反馈,指导未来的尝试 。为了确保生成的反馈具体且具有指导意义,自我反思模型会综合利用评估者提供的奖励信号、当前失败或成功的轨迹细节以及其持久性记忆(长期记忆)中的历史经验 。这些存储的经验被智能体高效利用,以快速改进决策,避免重复过去的错误 。

Reflexion的模块化设计不仅提高了框架的清晰度,更重要的是赋予了其高度的可插拔性和灵活性。这意味着开发者可以根据具体任务的需求,选择或替换不同的LLM作为Actor、Evaluator或Self-Reflection模块,甚至可以为Evaluator设计特定的规则启发式函数 。例如,在金融领域,Evaluator可以集成特定的合规性检查规则。这种灵活性使得Reflexion能够适应广泛的应用场景,并且可以随着LLM技术的发展而轻松升级其内部组件,而无需重新设计整个框架。这种组件级的创新和优化,使得Reflexion成为一个面向未来的、可演进的AI架构。

迭代与自我纠正机制

Reflexion过程的关键步骤形成了一个紧密的迭代循环,使智能体能够持续地从经验中学习、适应并优化其行为 。这一循环是Reflexion实现自我纠正的基石。

整个过程可分解为以下五个核心步骤:

  • 定义任务 (Define a task):整个过程的起点是明确且精确地定义智能体需要完成的具体任务和目标 。清晰、无歧义的任务定义是有效评估和反思的前提,它为智能体的后续行为设定了方向。

  • 生成轨迹 (Generate a trajectory):在任务定义之后,Actor模型开始工作,在环境中生成一系列动作和相应的观察结果,从而形成一个完整的“轨迹”或尝试序列 。这个轨迹记录了智能体在一次尝试中的所有相关行为和环境反馈。

  • 评估 (Evaluate):紧接着,Evaluator模型介入,对Actor生成的轨迹进行分析和评分。它根据预设的成功标准(例如,代码是否通过测试,决策是否达到目标),为该轨迹提供一个量化的奖励信号,以衡量其表现的优劣 。

  • 执行反思 (Perform reflection):这是Reflexion模式最独特和关键的步骤。Self-Reflection模型接收来自Evaluator的奖励信号、当前轨迹的详细信息(包括成功或失败的原因)以及其长期记忆中的相关历史数据。基于这些信息,它生成详细的语言反馈,明确指出本次尝试中的错误、不足之处以及潜在的改进方向 。反思的触发器可以是错误、意外结果或需要重新评估的“中断” 。反思行为包括重新思考、质疑或修改想法以响应LLM反馈 。反思内容示例包括调整初始想法、响应意外结果、提出更新的问题解决结构、细化LLM提示词以获得精确需求描述、通过复制粘贴错误提醒触发LLM调试,以及向LLM寻求程序或代码解释 。

  • 生成下一轨迹 (Generate the next trajectory):最后,智能体将上一步生成的自我反思作为新的上下文信息,融入到下一次尝试的输入中。智能体利用这些反思来指导其生成新的轨迹,旨在纠正过去尝试中的错误,并以更优化的策略来解决任务 。

这个迭代循环使得Reflexion智能体能够持续地从经验中学习、适应并优化其行为 。Reflexion通过引入明确的自我评估、自我反思和记忆组件,对ReAct框架进行了显著扩展 。这使得Reflexion智能体不仅能像ReAct那样进行推理和行动,还能在此基础上进行深层次的自我纠正和持续改进,从而在复杂任务中表现出更强的适应性和鲁棒性。

Reflexion对“自由形式语言”反馈和“内部模拟”反馈的支持,意味着它能够处理比简单数值更丰富、更具语义的反馈信息 。这种细致入微的语言反馈允许智能体更深入地理解其错误,并进行更有针对性的改进 。例如,一个编程任务的反馈不仅仅是“通过/失败”,还可以是“你的代码在处理边界条件时存在逻辑错误,考虑使用循环优化性能”。这种高质量的诊断性反馈是实现高效自我纠正的关键,也反映了其对人类学习过程的深层模拟,即人类从具体、详细的指导中学习效果最佳。

优势与应用场景

关键优势

Reflexion提示词模式凭借其独特的机制,展现出多方面的显著优势,使其在复杂任务中表现卓越:

  • 从试错中高效学习: Reflexion的核心优势在于其能够使智能体通过反思过去的错误,并将这些宝贵的经验知识融入到未来的决策中,从而实现性能的持续改进。这使得Reflexion特别适合那些需要通过反复试验和错误修正来逐步收敛到解决方案的任务,例如复杂问题的调试或多步骤决策序列的优化 。

  • 轻量级替代方案: 相较于需要大量训练数据和昂贵计算资源进行模型微调的传统强化学习方法,Reflexion提供了一种显著更轻量级且高效的替代方案。它无需对底层语言模型进行微调,而是通过上下文学习和语言反馈进行强化,从而在数据收集和计算资源消耗方面都更为经济和高效 。这对于资源有限的团队或需要快速部署和迭代的场景具有重要意义。

  • 细致入微的语言反馈: Reflexion利用其独特的口头反馈机制,这种反馈比传统RL中常用的简单标量奖励(如0或1)更为细致和具体。这种丰富的语言反馈使得智能体能够更深入、更精确地理解其错误所在,例如具体的逻辑缺陷或不当的行动选择,从而在后续尝试中做出更有针对性的改进 。这种高质量的诊断性反馈是其实现高性能的根本原因,它将LLM的自我修正能力从粗粒度提升到细粒度。

  • 可解释和显式记忆: Reflexion提供了一种比传统RL方法更具可解释性且显式的事件记忆形式。智能体的自我反思过程被清晰地记录并存储在其记忆中,这极大地便利了对智能体学习过程的分析和理解 。这种透明度对于调试、审计和建立用户信任至关重要,因为它允许开发者审查模型的“思维过程”,而非仅仅依赖黑箱输出。

  • 迭代优化与持续演进: 通过定义任务、生成轨迹、评估、反思和生成下一轨迹的紧密迭代过程,Reflexion智能体能够持续地优化其行为,以解决各种复杂任务 。这种内在的适应性使得Reflexion支持的AI智能体能够持续演进和学习,从而更有效地应对复杂动态的现实世界挑战 。这种跨领域的高效性表明Reflexion不仅仅是一个针对特定任务的优化,而是一种通用的问题解决范式。其核心机制——生成、评估、反馈、再生成——可以抽象应用于任何可以明确定义“任务”、“输出”、“成功标准”和“错误诊断”的领域。这预示着Reflexion可能成为未来构建更通用、更自主的AI智能体的基础架构之一。

典型应用案例

Reflexion模式已在多个复杂领域展现出卓越的性能,证明了其作为通用问题解决框架的强大潜力:

  • 顺序决策 (Sequential Decision-Making):
    Reflexion智能体在诸如AlfWorld等顺序决策任务中表现出显著的性能改进 。这类任务通常要求智能体在复杂的环境中进行导航,并完成一系列相互依赖的多步骤目标,智能体需要连续做出决策才能最终达成目标 。在AlfWorld任务的评估中,结合了ReAct的Reflexion(ReAct + Reflexion)显著优于单独使用ReAct的方法,成功完成了134个任务中的130个,充分展示了其在复杂决策链中的卓越能力 。

  • 推理 (Reasoning):
    Reflexion显著提高了智能体在HotPotQA等推理任务上的性能 。HotPotQA是一个需要智能体对多篇文档进行深入推理和信息综合才能得出答案的问答数据集,这要求高度的逻辑分析和信息整合能力 。在仅进行推理的场景中,Reflexion与Chain-of-Thought (CoT) 结合(Reflexion + CoT)以及在添加了最近轨迹的事件记忆后,均优于单独使用CoT和带有事件记忆的CoT基线模型 。

  • 编程 (Programming):
    Reflexion智能体在HumanEval和MBPP等代码生成基准测试中展现出编写高质量代码的强大能力 。在这些编程任务中,Reflexion在某些情况下取得了最先进的成果,通常优于Python和Rust代码编写的现有最先进方法 。一个突出例子是,Reflexion在HumanEval上达到了91%的pass@1准确率,这一成就超越了此前GPT-4的80% ,凸显了其在代码生成和纠错方面的强大实力。

  • 其他潜在应用:
    Reflexion的迭代精炼特性使其适用于多种需要高精度和质量控制的场景。这包括:精炼敏感信息传递,确保输出的准确性和恰当性;对AI输出进行压力测试以发现潜在问题和漏洞;以及对初步想法进行综合和改进,从而提升创意和解决方案的质量 。

与相关提示词技术的比较

Reflexion提示词模式并非孤立存在,它与当前LLM领域内其他先进的提示词技术存在紧密的联系和显著的区别。理解这些关系有助于更全面地把握Reflexion的独特价值和适用场景。

与思维链 (CoT) 的关系

Chain-of-Thought (CoT) 提示词是一种通过引导LLM生成一系列详细的、分步的推理过程来解决复杂问题的方法 。它模仿人类的逐步思考过程,从而显著提高LLM在复杂任务(如算术、常识推理和符号问题解决)中的准确性,并增强其推理过程的透明度和可靠性,有助于调试 。

在Reflexion框架中,CoT并非被取代,而是被巧妙地整合并用作Actor模型的一部分 。这意味着Reflexion将CoT作为其基础推理和行动的构建块,在其之上叠加了更高级的自我纠正和学习机制。实验结果有力地表明,Reflexion与CoT结合(Reflexion + CoT)在推理任务中显著优于单独使用CoT或仅带有事件记忆的CoT 。这清晰地证明了Reflexion的自我反思和记忆组件能够进一步增强CoT的内在推理能力,使其在复杂问题解决中表现出更强大的鲁棒性和准确性。这表明Reflexion不是一个独立的、与CoT/ReAct并列的提示词技术,而是一个更高层次的“元框架”或“元学习”机制。它利用CoT和ReAct提供的基础推理和行动能力,并在此之上添加了一个智能体能够“学习如何改进自身表现”的循环。

与 ReAct 框架的扩展

ReAct (Reasoning and Acting) 框架是一种结合了推理(Reasoning)和行动(Acting)的提示词技术。它允许LLM在生成响应的同时,通过观察环境并采取行动来动态规划和交互,从而解决需要外部工具或多步骤交互的任务。

Reflexion被明确设计为对ReAct框架的扩展。它通过引入三个关键组件——明确的自我评估(Self-Evaluation)、自我反思(Self-Reflection)和记忆(Memory)——来增强ReAct的能力 。这使得ReAct智能体不仅能推理和行动,还能从其行动结果中学习并改进。在顺序决策任务(如AlfWorld)的评估中,结合了Reflexion的ReAct(ReAct + Reflexion)显著优于单独的ReAct基线模型,成功完成了绝大多数任务(134个任务中的130个)。这突出显示了Reflexion在ReAct基础上增加的迭代自我改进层在提升智能体决策能力方面的有效性。

与思维树 (ToT) 的异同

Tree of Thoughts (ToT) 是一种更高级的框架,它概括了CoT提示词,旨在解决需要广泛探索或战略性前瞻的复杂任务 。ToT通过维护一个“思维树”来实现这一点,其中每个“思维”都是解决问题过程中的一个连贯的语言序列中间步骤。ToT允许LLM通过深思熟虑的推理过程自我评估通过中间思维取得的进展,并结合搜索算法(如深度优先搜索DFS/广度优先搜索BFS)进行前瞻和回溯 。

尽管Reflexion和ToT都旨在解决复杂问题并超越简单的CoT,但它们在核心机制和策略上存在显著差异:

共同点:

  • 模拟人类认知: Reflexion和ToT都旨在模拟人类的认知策略,以增强LLM的推理和问题解决能力。Reflexion模仿人类的迭代学习和自我纠正 ,而ToT则模拟人类在解决复杂问题时探索多种可能解决方案的树状思考方式 。

  • 迭代与自我评估: 两者都涉及某种形式的迭代过程和对中间步骤的自我评估,以指导后续的生成或决策 。

  • 超越简单CoT: 两者都旨在超越简单的线性CoT推理,以处理更具挑战性的、需要更深层次思考和规划的任务 。

不同点:

  • 探索策略: ToT的核心在于“探索”和“战略性前瞻”,通过生成和评估多个分支路径以及利用搜索算法来探索多种潜在解决方案 。而Reflexion则更侧重于对单一轨迹的“迭代精炼”和“自我纠正”,通过语言反馈优化当前路径,使其在每次尝试中变得更好 。

  • 反馈机制: Reflexion主要依赖于将环境反馈转化为语言形式的自我反思,这种反馈通常是关于特定尝试的成功或失败 。ToT则通过对不同思维路径的自我评估和剪枝来实现进步,其反馈更侧重于路径的可行性和有效性 。

  • 学习机制: Reflexion通过“语言强化”避免权重更新,使其成为一种轻量级的、无需微调的改进方法 。而ToT的一些高级变体(如Long (2023) 提出的ToT Controller)可以通过强化学习进行训练,即使LLM固定也能持续学习新知识 。这表明ToT可以结合更深层次的训练机制,以实现更长期的、数据驱动的演进。

  • 复杂性: ToT框架通常涉及更复杂的搜索算法和状态管理,需要对思维树进行遍历和剪枝 。而Reflexion的迭代循环相对更直接,但其内部反思过程也可能涉及复杂的语言生成和分析。

ToT与Reflexion代表了两种不同的高级问题解决范式。ToT更像一个“规划者”或“探索者”,在问题空间中寻找最佳路径,适用于需要发散性思维和多方案比较的开放式问题(如创意生成、复杂规划)。而Reflexion更像一个“迭代优化器”或“自我调试器”,专注于改进当前的解决方案,适用于有明确成功标准、需要精确和高效迭代改进的问题(如代码调试、特定决策序列、客服机器人优化)。这种差异决定了它们在不同类型任务中的适用性,也暗示了未来可能出现融合两者优势的混合框架。

局限性与挑战

尽管Reflexion提示词模式展现出显著的优势和广阔的应用前景,但在实际部署和进一步发展中,它也面临着一些不容忽视的局限性与挑战。

对自我评估能力的依赖

Reflexion的有效性高度依赖于智能体自身准确评估其性能并生成有用自我反思的能力 。如果智能体无法正确识别自身错误,或者其评估不够精确,那么后续的迭代改进将无从谈起。对于高度复杂或开放式的任务而言,LLM进行准确的自我评估尤其具有挑战性 。这些任务可能没有明确的对错标准,或者错误模式过于隐蔽,使得LLM难以进行有效的自我诊断。

LLM能否有效纠正错误,其首要前提是能否检测到错误,而这正是整个自我纠正过程中的一个关键瓶颈 。研究表明,LLM在检测自身错误方面可能存在困难,尤其是在答案不明显或需要获取中间反馈的情况下 。此外,LLM可能表现出一种“自我偏见”(或“自恋”),即它们倾向于偏爱自己生成的输出,即使这些输出并非客观上更好 。这种偏见在优化过程中可能加剧,导致文本措辞改善但答案质量并未实质性提高 。这揭示了一个核心矛盾:Reflexion的力量源于其自我评估,但其最大的脆弱性也恰恰在于这种评估的内在局限性。如果LLM无法准确识别错误,或者其自我评估被“自恋”偏见所扭曲,那么迭代循环可能只是在“优化”一个次优或错误的解决方案,而非真正纠正它。尽管存在这些挑战,但随着LLM模型架构和训练数据的不断进步,预计其自我评估能力也将随之增强,从而逐步缓解这一局限性 。

长期记忆的限制

Reflexion在目前的实现中,通常使用具有最大容量的“滑动窗口”机制来管理其长期记忆 。这意味着只有最近的少量历史经验能够被智能体直接访问和利用。对于需要长时间上下文依赖或涉及大量历史信息的复杂任务而言,这种方法可能不足以存储和利用所有必要的历史经验,从而限制了智能体的学习能力和决策质量。

记忆容量和管理方式直接影响Reflexion处理长期依赖和复杂任务的能力。滑动窗口的局限性意味着智能体可能无法记住足够远的过去错误或成功经验来指导当前决策,尤其是在需要多轮复杂交互的任务中。报告建议,对于更复杂的任务,使用更高级的结构,如向量嵌入或SQL数据库,可能更有利于管理长期记忆 。引入外部数据库或向量记忆不仅增加了记忆容量,更重要的是,它允许更高效的检索和更复杂的记忆组织(如语义搜索),从而使智能体能够访问和利用更丰富、更相关的历史经验,这对于其在真实世界复杂场景中的可扩展性和鲁棒性至关重要。

特定任务的挑战

Reflexion在特定任务领域也面临着独特的挑战:

  • 代码生成限制: 在代码生成任务中,Reflexion面临与测试驱动开发相关的限制。例如,对于非确定性生成函数或其输出受硬件影响的函数,很难指定准确的输入-输出映射,这会影响自我纠正的精确性 。这意味着在这些场景下,自动化的评估和反思可能无法提供足够清晰的信号来指导模型改进。

  • 开放式任务的挑战: 对于生成开放式对话、创意写作或科学发现等任务,很难定义什么是“错误”并提供客观反馈 。在这些领域,缺乏明确的成功标准使得自我纠正的应用变得困难。目前,LLM的自我纠正主要集中在有明确答案或可量化评估的任务上 。

泛化性与误差检测

除了上述挑战,Reflexion作为一种自我纠正机制,也面临着一些普遍存在于LLM自我修正中的问题:

  • 自我偏见 (Self-Bias): LLM可能表现出“自我偏见”(或“自恋”),即它们倾向于偏爱自己生成的输出,即使这些输出并非客观上更好 。这种偏见在优化过程中可能加剧,导致文本措辞改善但答案质量并未实质性提高 。这强调了未来研究需要关注如何提高LLM的“元认知”能力,即它们如何判断自己的知识状态和输出质量,可能需要结合外部验证机制或更强大的内部一致性检查来缓解这一问题。

  • 次优提示与泛化性: 一些研究显示LLM纠正错误的成功案例使用了简单或次优的提示,导致结果容易改进,但这些有利结果可能不具泛化性,意味着LLM只能在非常具体的任务上进行自我纠正 。这提示我们,Reflexion的成功可能在一定程度上依赖于任务的特性,而非普遍适用于所有场景。

  • 反馈准确性: 自我纠正最困难的部分是获取非常准确的反馈,特别是中间反馈 。在复杂的多步骤任务中,仅仅知道最终结果的对错不足以指导有效的纠正,智能体需要知道在哪一步出了问题,以及具体原因。

减少幻觉的贡献

LLM的幻觉问题,即模型生成看似合理但事实上不准确或虚构的信息,是其在实际应用中面临的重大挑战。Reflexion及其相关的反思机制,通过其内在的自我纠正和验证循环,为缓解这一问题提供了重要的途径。

反思机制如何缓解幻觉

Reflexion通过其反馈循环和迭代自我纠正机制,使模型能够反思过去的输出并学习错误,从而间接有助于减少幻觉 。虽然没有直接声明Reflexion“减少幻觉”,但其“学习错误”和“提高准确性”的能力与减少幻觉的努力是高度一致的 。幻觉通常源于模型内部知识的不确定性或推理错误。Reflexion通过强制模型“停下来,思考,检查”其输出,并根据反馈进行调整,实际上是在其输出管道中引入了一个动态的、基于语言的“质量门”。这种内部验证和修正机制,虽然与外部知识检索(RAG)不同,但同样能提升输出的可靠性和事实一致性,因为它迫使模型对自己的“思考”负责。

Reflexion被认为通过纳入一种质量控制形式来帮助减少幻觉 。通过迭代地批判或改进自身答案,模型成为自己的编辑,重新审视逻辑、语气或清晰度并进行相应修正 。这种自我编辑过程有助于识别和修正不一致或不准确的陈述。此外,提示词驱动的自我精炼和反思方法,通过多步生成和基于置信度的答案重排,在事实一致性方面显示出模型无关的增益 。这表明反思机制能够提升模型输出的内在连贯性和事实准确性。

相关反思技术的应用

除了Reflexion本身,更广泛的“反思技术”也为幻觉缓解提供了多种策略,其中一些与Reflexion的核心思想相通:

  • 自我一致性反思 (Self-Consistency Reflection):这种技术涉及生成多个候选响应以回答同一查询。其核心思想是,虽然幻觉可能因不同的生成尝试而异,但事实正确的信息往往在多次生成中保持一致。通过识别并优先处理这些在不同尝试中保持一致的事实性声明,可以有效降低幻觉的风险 。

  • 事实核查反思 (Fact-Checking Reflection):这种方法提示模型在生成响应后立即验证其自身声明的事实准确性和置信度。模型首先生成初步响应,然后进入事实核查阶段,最后修订响应以移除或限定不确定的声明 。这为模型提供了一个内部的验证循环。

  • 对抗性自我批判 (Adversarial Self-Critique):这种方法将反思推向更深层次,提示模型采取怀疑态度,主动识别自身输出中潜在的幻觉。模型生成初步响应后,会尝试以“对抗性思维”挑战可疑声明,用具体反驳进行质询,并最终生成修订后的响应 。尽管计算密集,但在受控研究中显示出显著的幻觉率降低。

  • 结合外部知识检索的反思 (External Knowledge Retrieval with Reflection):这种技术将外部知识检索整合到反思过程中,允许模型根据权威来源验证声明,而非仅依赖其内部的参数化知识。模型首先检索相关文档,然后利用这些上下文生成初步答案,接着反思答案与检索信息的对齐程度,并最终精炼答案以消除未经验证的声明 。这显著提高了输出的事实基础。

  • 反思安全层 (Reflection Security Layer):这是一个概念性的架构,所有输出在呈现给用户前都通过专门的验证层。该系统根据置信度分数、引用验证和已知错误类型模式匹配来标记潜在幻觉,特别适用于医疗、金融和法律等高风险领域 。

尽管这些反思技术在缓解幻觉方面表现出色,但也存在挑战,例如计算开销的增加。一个更深层次的挑战是可能出现“元幻觉”(meta-hallucinations),即模型在反思过程中本身产生幻觉 。这是一个关键的观察,它揭示了AI自我纠正机制并非完美无缺,甚至可能在“纠正”的过程中引入新的错误。这表明,虽然反思机制提供了强大的自我改进能力,但其鲁棒性仍需进一步研究。未来的工作不仅要关注如何让LLM更好地反思,还要关注如何确保“反思本身”是可靠和准确的,可能需要引入独立的、更客观的验证机制来监控反思过程的质量。

结论与展望

总结Reflexion的关键贡献

Reflexion提示词模式代表了大型语言模型自我改进范式的一次重要创新。它通过语言反馈而非传统的模型权重更新来强化LLM,在复杂任务中展现出卓越的性能提升,尤其是在代码生成、语言推理和顺序决策方面 。其模块化的Actor-Evaluator-Self-Reflection架构,以及紧密的迭代自我纠正循环,使得智能体能够高效地从试错中学习,并提供可解释的记忆路径 。Reflexion并非取代Chain-of-Thought (CoT) 或 ReAct 等现有技术,而是通过引入明确的自我评估、自我反思和记忆组件,对其进行了有效的扩展 。这使得LLM智能体从简单的执行者向具备自主学习和适应能力的学习者迈进,体现了其作为一种元学习框架的潜力。此外,Reflexion及其相关的反思技术在缓解LLM幻觉问题上也展现出积极作用,通过内部的质量控制和迭代验证,提升了输出的事实一致性和可靠性 。

展望未来的发展方向和潜在研究领域

Reflexion提示词模式为LLM的自我改进和复杂问题解决开辟了新的道路,但其发展仍处于早期阶段,未来有诸多值得深入探索的方向:

  • 增强自我评估能力: 当前Reflexion的有效性高度依赖于智能体准确评估自身错误的能力,而这对于复杂任务仍是挑战 。未来的研究应聚焦于如何提高LLM的“元认知”能力,使其能够更精确地识别自身知识边界和输出缺陷,可能需要结合更先进的元学习技术或引入外部验证信号来校准其自我评估。

  • 优化长期记忆管理: Reflexion目前使用的滑动窗口记忆机制在处理长期依赖或需要大量历史经验的任务时存在局限 。探索和实现更高效、可扩展的长期记忆结构,如高级向量数据库、知识图谱或混合记忆系统,将是关键。这将使智能体能够访问和利用更丰富、更相关的历史经验,从而支持更复杂、多轮次的任务。

  • 缓解“元幻觉”: 反思过程中模型自身产生幻觉的“元幻觉”问题是一个深层次的挑战 。未来的研究应开发新的检测和缓解策略,确保反思过程本身的可靠性和准确性,可能需要引入独立的、更客观的验证机制来监控反思过程的质量。

  • Reflexion与其他高级技术的融合: 深入研究Reflexion与Tree of Thoughts (ToT) 、多智能体系统、检索增强生成(RAG)等其他高级提示词和架构的协同效应,以构建更强大、更通用的AI智能体。例如,Reflexion可以为ToT的搜索和剪枝过程提供更精细的反馈,或者与RAG结合以增强事实基础。

  • 更广泛的应用探索: 将Reflexion应用于更多开放式、需要创造性和复杂交互的领域,如开放域对话、科学发现、艺术创作等,并探索其在这些领域中的泛化能力和局限性。这将推动Reflexion从结构化任务向更广阔的非结构化领域扩展。

  • 理论基础的深化: 进一步探索Reflexion与人类认知科学、学习理论之间的深层联系,例如其与人类批判性思维、经验学习循环的对应关系 。这将为AI的自我改进机制提供更坚实的理论基础,并可能启发更多仿生智能体的设计。

Reflexion提示词模式的出现,标志着LLM在迈向真正智能和自主学习的道路上迈出了重要一步。通过持续的研究和创新,Reflexion有望在未来AI系统的设计和部署中发挥越来越核心的作用。

提示词工程-反思模式

提示词工程-反思模式

什么是 Reflexion?

Reflexion 是一种先进的 AI Agent 架构,其核心思想是让 Agent 具备自我反思和自我修正的能力。它不仅仅是简单地执行任务(像传统的 ReAct – Reason and Act 模式),而是在遇到失败或障碍时,能够停下来“复盘”自己的行为轨迹,从中吸取教训,并形成指导性的“经验”,用于下一次的尝试。

简单来说,Reflexion 赋予了 Agent 一种从失败中学习的机制,模拟了人类在解决复杂问题时的试错和总结过程。

这项技术主要源于康奈尔大学等机构在 2023 年发表的论文《Reflexion: Language Agents with Verbal Reinforcement Learning》。

Reflexion 与传统方法的区别

特性传统 ReAct AgentReflexion Agent
核心循环思考 -> 行动 -> 观察 (Thought -> Act -> Observation)尝试 -> 评估 -> 反思 -> 再次尝试 (Trial -> Evaluate -> Reflect -> Retry)
失败处理可能会在当前步骤卡住,或进行无效的重复尝试。将整个失败的“轨迹”作为学习材料,进行深入分析。
记忆通常是短期的“暂存器”(Scratchpad),记录当前任务的步骤。拥有一个长期、不断累积的“反思记忆库”(Reflexion Memory)。
学习方式主要依赖于 In-context Learning,受限于单次提示的长度和内容。通过“语言强化学习”,将反思(Verbal Feedback)作为内部奖励信号来指导后续行为。

Reflexion 的核心组件

一个完整的 Reflexion 流程包含三个关键角色,它们都可以由同一个大型语言模型(LLM)通过不同的 Prompt 来扮演:

  1. 行动者 (Actor):

    • 职责: 根据任务目标和当前的“反思记忆”,生成思考和具体行动指令。
    • 工作方式: 这是 Agent 的“手和脚”,负责与外部环境(如代码解释器、搜索引擎)交互。在后续的尝试中,Actor 的 Prompt 会包含之前失败后总结的反思,从而避免重蹈覆辙。
  2. 评估者 (Evaluator):

    • 职责: 判断行动者的输出结果是成功、失败还是部分成功。
    • 工作方式: 评估者检查 Actor 的行动轨迹(Trajectory)和最终结果。评估可以是简单的基于规则的检查(例如,代码是否成功运行),也可以是复杂的、基于 LLM 的语义判断(例如,生成的文章是否回答了问题)。
  3. 自我反思者 (Self-Reflector):

    • 职责: 这是 Reflexion 的核心。当评估者给出“失败”信号时,反思者被激活。它会分析整个失败的行动轨迹,并生成一段简洁、高度概括、具有指导意义的反思文本 (Reflection Text)
    • 工作方式: 反思者会被要求回答“为什么之前的尝试会失败?”以及“下一次应该如何做才能避免这个错误?”。生成的反思文本会被存储到“反思记忆库”中。

工作流程图

下面是 Reflexion Agent 的典型工作流程:


如何使用 Reflexion Prompt 开发 Agent

开发一个 Reflexion Agent 的本质,就是设计一套精巧的 Prompt 链,来分别驱动 Actor, Evaluator 和 Reflector 这三个角色,并管理好“反思记忆库”。

第1步:定义 Agent 的核心组件

你需要准备三个主要的 LLM 调用函数,或者说三个核心 Prompt。

1. Actor Prompt (行动者提示)

这是 Agent 执行任务的基础。与 ReAct 不同的是,你需要为它注入“反思记忆”。

  • 基础结构:

    你是一个{Agent角色,如AI程序员}。你需要解决以下任务。
    
    # 任务
    {task_description}
    
    # 思考过程
    你需要一步步思考,然后选择一个工具/行动。可用的工具有: {tool_list}。
    
    # 反思 (如果记忆库不为空)
    在之前的尝试中,你犯了一些错误。请参考以下从失败中总结的经验教训,避免重蹈覆覆:
    {reflection_memory}
    
    # 行动轨迹 (Scratchpad)
    {scratchpad}
  • {reflection_memory}: 这是一个变量,用于动态插入所有过去的反思文本。在第一次尝试时,这里是空的。
  • {scratchpad}: 用于记录当前尝试中的“Thought, Action, Observation”序列。

2. Evaluator Prompt (评估者提示)

评估可以是简单的代码检查,也可以是复杂的 LLM 判断。对于需要语义理解的评估,可以使用如下 Prompt:

  • 基础结构:

    # 角色
    你是一个严谨的评估机器人。
    
    # 原始任务
    {task_description}
    
    # Agent 的行动轨迹
    {agent_trajectory}
    
    # 评估标准
    请根据以下标准判断 Agent 是否成功完成了任务:
    1.  {criterion_1}
    2.  {criterion_2}
    
    # 你的判断
    请严格回答 "Success" 或 "Failure"。
  • {agent_trajectory}: 传入 Actor 在一次完整尝试中的所有记录。

3. Self-Reflector Prompt (自我反思提示)

这是整个 Reflexion 机制的灵魂。当 Evaluator 返回 "Failure" 时,调用此 Prompt。

  • 基础结构:

    # 角色
    你是一个善于反思和总结的 AI 导师。
    
    # 失败的尝试
    一个 Agent 在尝试解决以下任务时失败了。
    任务: {task_description}
    
    这是它失败的完整行动轨迹:
    {failed_trajectory}
    
    # 你的任务
    请仔细分析上述轨迹,找出导致失败的关键原因。然后,生成一条或几条简洁、通用、具有指导意义的反思。这条反思应该像一个警句或策略,帮助 Agent 在未来的尝试中避免同样的错误。
    
    # 输出要求
    - 直接输出反思文本。
    - 语言要精炼,不超过 50 个字。
    - 专注于策略层面,而不是具体的代码细节。
    
    # 你的反思:
  • 示例输出 (反思文本):
    • "如果一个库的某个函数不存在,应该先检查库的版本或者查阅官方文档,而不是猜测函数名。"
    • "在进行文件写入前,必须先确认目标目录是否存在,如果不存在则需要创建它。"
    • "当网页爬取不到预期内容时,应检查请求头(Headers)是否模拟了真实浏览器,以防被屏蔽。"

第2步:搭建 Agent 的主循环

有了这三个核心 Prompt,你就可以编写 Agent 的主控制逻辑了。

伪代码示例:

def run_reflexion_agent(task, max_trials=3):
    # 初始化反思记忆库
    reflection_memory = []

    for i in range(max_trials):
        print(f"--- 开始第 {i+1} 次尝试 ---")

        # 1. 执行一次完整的尝试 (Actor)
        # Actor 的 prompt 中会包含 reflection_memory
        current_trajectory = execute_trial(task, reflection_memory)

        # 2. 评估结果 (Evaluator)
        is_successful = evaluate_trial(task, current_trajectory)

        if is_successful:
            print("任务成功!")
            return current_trajectory
        else:
            print("尝试失败,开始反思...")
            # 3. 如果失败,进行反思 (Self-Reflector)
            new_reflection = generate_reflection(current_trajectory)
            print(f"新的反思: {new_reflection}")

            # 4. 更新记忆库
            reflection_memory.append(new_reflection)

    print("已达到最大尝试次数,任务失败。")
    return None

# --- Helper Functions ---
def execute_trial(task, reflections):
    # 调用 LLM (Actor Prompt) 来生成一系列的 thought-action-observation
    # ... 实现细节 ...
    return trajectory

def evaluate_trial(task, trajectory):
    # 调用 LLM (Evaluator Prompt) 或其他规则来判断成功与否
    # ... 实现细节 ...
    return True_or_False

def generate_reflection(failed_trajectory):
    # 调用 LLM (Self-Reflector Prompt) 来生成反思文本
    # ... 实现细节 ...
    return reflection_text

关键的实现细节与建议

  1. 管理记忆库和上下文窗口: 反思记忆会不断增长。如果记忆过多,可能会超出 LLM 的上下文窗口限制。你需要策略来管理它,例如:

    • 只保留最近的 N 条反思。
    • 对所有反思进行一次更高层次的总结。
    • 使用向量数据库,根据当前失败情境检索最相关的反思。
  2. 反思的质量至关重要: Self-Reflector Prompt 的设计直接决定了 Agent 的学习效率。一个好的反思应该是通用且可操作的,而不是简单地复述错误。

  3. 分层反思 (Hierarchical Reflection): 对于非常复杂的任务,可以设计两层反思。第一层针对短期策略,第二层在多次失败后进行更高层次、更长远的战略总结。

总结

Reflexion 是一种强大但实现起来也更复杂的 Agent 架构。它通过将失败转化为学习机会,极大地提升了 Agent 在需要多步推理、试错和规划的复杂任务上的鲁棒性和成功率。

要成功开发一个 Reflexion Agent,关键在于设计出能够精准驱动 Actor、Evaluator 和 Self-Reflector 这三大核心角色的 Prompt,并实现一个有效的主循环来调度它们和管理反思记忆。这不仅仅是技术实现,更是一门 Prompt Engineering 的艺术。

提示词工程-提示词链(prompt chain)

提示词工程-链式提示词(prompt chain)

罗伯特·C·马丁(Robert C. Martin),一位著名的工程师,曾经说过:“函数应该只做一件
事。它们应该做好这件事。而且只做这件事。” 同样的原则也适用于提示词工程。

提示词应该只做一件事。它们应该做好这件事。而且只做这件事。

如果在同一个提示词中包含了多个任务或者指令时,AI大模型的输出将会不敬人意。这样的
提示词会让AI大模型陷入困境,无法正确理解你的意图。因此,更好的方法是将较大的提示
分解为多个较小的提示,创建动态提示链。每个链式提示词只包含一个任务或者指令。

提示链通过让模型专注于链中每个子任务,实现了对输出的更细粒度控制。

什么是提示词链?

提示词链将一个任务拆解为一系列较小的子任务,每个子任务由独立的提示词处理。

提示词链可以通过多种方式实现,包括结合其他提示工程方法,例如自动链式思维提示
(automatic chain-of-thought prompting)、由易到难提示(least-to-most
prompting)以及自一致性提示(self-consistency prompting)。

例如,在文本摘要任务中,可以通过提示链实现以下步骤:

  1. 创建初步摘要草稿
  2. 对摘要进行批评与改进建议
  3. 检查摘要是否存在事实错误
  4. 根据批评和反馈生成精炼后的摘要

每个步骤都由独立的提示处理,使模型能够完全专注于单个子任务,从而提高整体输出质量。

提示链对于完成复杂任务非常有用,因为这些任务如果使用一个非常详细的单一提示,LLM
可能难以应对。在提示链中,每个链式提示都会对生成的响应进行转换或额外处理,直到最
终达到期望的结果。

除了获得更好的性能,提示链还能提高LLM应用的透明性、可控性和可靠性。这意味着你可
以更轻松地调试模型响应中的问题,并分析和改进需要优化的各个阶段的性能。

提示链在构建基于LLM的对话助手、改善应用的个性化和用户体验方面尤其有用。

提示链的工作原理

下图展示了提示链的基本工作原理。首先使用提示链时,需要将任务拆解为多个子任务,子
任务的粒度足够小,每个子任务都由独立的提示处理。上一个提示词的输出作为下一个提示
词的输入。

提示链的好处

  • 增强专注力:通过将庞大的提示拆解为有针对性的子提示,模型可以将注意力集中在
    每个任务上,一次只处理一个任务。

  • 更高质量的输出:如后续研究所示,提示链的效果明显优于庞大的提示。研究结果表
    明,提示链能够提供更精确和有效的输出。

  • 更易理解:理解复杂的庞大提示非常具有挑战性,这也使得团队协作变得困难,输出
    质量难以提升。通过利用提示链,所使用的提示更加专注,因此更容易理解。

  • 广泛适用:提示链几乎可以提高任何复杂任务的输出质量。无论是摘要、问题解决还
    是创意写作,通过提示链将过程拆解为更小的步骤都能帮助模型提高表现。

提示链在生成长篇输出或处理包含大量上下文的提示时特别有益。

何时使用提示词链

提示链本身其实也是模拟了人类思维的链式思考过程。在人类思维中,我们会将一个大的
任务拆解为多个小的子任务,然后逐个完成。这种思维方式使我们能够更好地处理复杂的问题。

但是当你的任务非常简单或者只包含一个步骤时,使用提示链可能会增加不必要的复杂性。

如果你在决定是创建提示链还是使用单个提示时,可以考虑以下四个问题:

  • 我的任务涉及多个指令吗? 例如,“阅读这篇文章并生成摘要,然后创建一个相关的
    LinkedIn帖子。”

  • 我的任务需要多次转换吗? 比如,如果输出需要以多种方式进行处理或重新格式
    化。

  • 我对单一提示的结果不满意吗? 将任务拆解为子任务,并通过提示链逐个处理,可
    以帮助你找出问题所在,从而更容易修复。

  • 模型是否似乎失去焦点或忘记上下文? 如果是这样,将单个提示转化为提示链可以
    确保每个步骤都能得到模型的全神贯注。

提示链的典型示例

数据分析任务

通常在做数据分析时,我们需要进行数据提取、数据清理、数据分析和数据可视化等多个步骤。
而且每一步都要基于上一步的结果进行。因此这是一种典型的适合使用提示链的场景。

提示1:提取数据
从我们公司的数据库的导出数据 {{ 数据库数据 }} 中提取收入和用户参与数据,重点关注第一季度到第四季度的数据。

提示 2:数据转换
清理提取的数据 {{ 提取的数据 }} ,去除异常值,处理缺失值,并标准化数值字段。

提示 3:数据分析
分析清理后的数据 {{ 转换后的数据 }},以识别收入增长和用户参与度随时间的主要趋势。

提示 4:数据可视化
根据 {{ 数据分析结果 }} 创建可视化图表,突出分析中识别的趋势,重点展示收入增长和参与度激增。

代码编写任务

软件的代码编写是一个相当复杂的过程,通常需要多个步骤,例如需求分析、设计、编码、测试和部署等等。
如何将编写代码的任务交给AI大模型呢?这时候提示链就派上用场了。

如下提示链的示例,将代码编写拆解为:根据需求生成代码-》生成测试用例 -》代码检视 -》解决问题。

提示1:生成代码
请根据用户的 {{ 功能需求 }} 使用 {{ 编程语言 }} 生成相应的代码,保证生成的代码和用户需求一致。
始终使用注释来解释代码片段,如果是函数和类,请添加函数和类的注释,函数的注释包括函数名、参数、
返回值、功能描述。始终保持代码的整洁和可读性。

提示2:生成测试用例
请根据生成的代码 {{ 生成的代码 }} 生成相应的测试用例,保证测试用例能够覆盖生成的代码。

提示3:代码检视
请对 {{ 代码和测试用例 }} 进行检视,找出代码中存在的问题,并给出改进建议。

提示4:解决问题
请根据检视建议对 {{ 生成的代码 }} 和测试用例 {{ 生成的测试用例 }} 进行改进优化,同时保证测试
用例能够通过。

复杂任务拆解

如果你一开始还不太清楚如何将一个任务拆解为多个子任务,那么你也可以提示链技术借助LLM的能力,
将任务拆解为多个子任务。

系统提示词:
你是一个任务拆解专家,请根据用户的需求,将任务拆解为多个子任务。目标是尽可能的将任务拆解为
细粒度的子任务。

提示词1:
这是一个复杂任务 {{ 任务描述 }} ,将任务拆解为多个子任务或者执行步骤。

提示词2:
根据 {{ 任务拆解 }} ,列出每个子任务的具体目标和预期结果。

提示词3:
根据 {{ 任务拆解 }} ,列出每个子任务需要完成指定目标所需要使用的方法或者解决方案。

提示词4:
请根据 {{ 任务拆解 }} 和 {{ 子任务目标 }} ,列出每个子任务的执行优先级。

提示词5:
请根据 {{ 任务优先级 }} ,列出每个子任务的执行顺序。

提示词6:
请根据 {{ 任务拆解 }} 列出每个子任务需要依赖的外部资源。

参考文章:

https://www.prompthub.us/blog/prompt-chaining-guide
https://www.ibm.com/topics/prompt-chaining
https://docs.anthropic.com/en/docs/build-with-claude/prompt-engineering/chain-prompts
https://www.promptingguide.ai/techniques/prompt_chaining

提示词工程-ReAct提示词(反应式)-让智能体像人一样思考和行动

文章会实时同步到我的公众号,有兴趣的童鞋扫码关注我的公众号噢:

提示词工程-ReAct

提示词工程的魅力就在于,让你可以变成现代版的祭师,能够让大模型言听计从,控制大模型做你想做的事情。

我不太确定超级智能会在未来的哪一天出现,但是从AI的快速迭代和进化来看,我们似乎可以预测,这一天不会遥远。一直以来,创造一个能够自主思考,自主学习和进化的智能体应该是AI发展的终极目标,而在这样的发展进程中,提示词工程也许只是这个进程中的一小段旅程,也许有一天,这项技术会成为历史,不过至少现在,它能够让我们对AI大模型有更加深入的了解,并且助力大模型变得更加聪明和务实。

起初,很难相信,生成模型会具有思考的能力,可当研究人员不断的探索出新的提示词技术时,这种怀疑逐渐得到了清晰的答案。

ReAct 提示词

ReAct 是 "Reasoning and Acting" 的缩写,旨在通过结合推理和行动来提高模型在复杂任务中的表现。

起初该框架由Yao 等人于2022年提出。

ReAct提示词实际上是one-shot或者few-shot提示词的一种(对于什么是one-shot,few-shot提示词,请阅读《提示词工程-少样本提示》)。
简单的说,就是给AI大模型一个思考-行动的例子,通过该例子,表明完成一件特殊任务时,思考和行动的基本框架和逻辑。ReAct本身是拟人化的,模拟人类思考和行动的基本方式,这里我可以举一个非常简单的例子,比如肚子饿了,非常想吃蛋糕:

问题:俺肚子饿了,非常想吃蛋糕。
思考:看看家里有没有买了蛋糕啊?
行动:去冰箱里看看,去厨房看看,发现没有。
思考:想吃自己做的蛋糕呢,还是去点外卖呢,哎,最近有点懒,不想动,还是外卖吧!
行动:打开手机APP,搜索蛋糕,得到种类繁多的蛋糕。
思考:我到底想吃哪一种呢,好像提拉米苏更加诱人一些。
行动:下单购买提拉米苏。
......

以上只是一个非常简单的例子,对人类来说,看起来是件非常普通和自然的事情,可是将思考方式分解,用来提示AI大模型时,会出现非常神奇的效果。

与链式思维推理类似,ReAct 是一种提示工程方法,使用少量样本学习来教模型解决问题。CoT 旨在模仿人类思考问题的方式,ReAct 也包含了这种推理元素,但更进一步地允许智能体通过文本操作与其环境进行交互。人类通过语言推理(说话或思考)来帮助制定策略和记忆事物,但我们也可以采取行动来获取更多信息并实现目标。这就是 ReAct 的基础。

ReAct 提示包括包含行动的示例,通过行动获得的观察,以及人类在过程中不同阶段的书面思考(推理策略)。LLM 学会模仿这种交替进行思考与行动的方法,使其成为环境中的智能代理。下方是 ReAct 智能体如何运作的示例,(按“思考 -> 行动 -> 观察 -> 思考”顺序)。

ReAct智能体的任务执行的大致过程:

  • 用户提出问题。
  • 思考,第一步应该做什么,决定执行动作和环境互动。
  • 行动,使用外部工具,从环境中获取需要的信息。
  • 观察,将行动的结果和收集的信息作为下一步思考的输入。
  • 思考,判断是否问题得到解决,基于上一步观察的结果,重新制定下一步需要执行的动作。
  • 重复以上循环,直到问题解决,或者得到了最终的答案,并结束。

ReAct 提示词是一种思考和行动的模版和范式,教AI大模型按照这种思维框架进行学习和解决问题,与其他提示工程不同的是,ReAct需用通过和环境的互动,获取信息,做动态的调整和规划。因此使用ReAct提示词时,同时需要实现智能体,或者智能代理,能够让智能体使用工具和外部环境进行交互。

更多ReAct提示词的例子

以下是一个来自论文的 ReAct 提示示例

你是知识问答机器人,你会帮助用户回答科学,地理等相关科普知识,给用户提供准确的答案,请以以下例子为参考,以思考-行动-观察 迭代的方式,确保你的答案是实时准确的,你可以通过搜索引擎获取外部知识。

问题:科罗拉多造山运动的东部区域延伸到的区域的海拔范围是多少? 
思考 1:我需要搜索“科罗拉多造山运动”,找出其东部区域延伸到的地方,然后找出该区域的海拔范围。 
行动 1:搜索[科罗拉多造山运动] 
观察 1:科罗拉多造山运动是科罗拉多及周边地区发生的造山事件。 
思考 2:资料中没有提到东部区域,因此我需要查找“东部区域”。 
行动 2:查找[东部区域] 
观察 2:(结果 1 / 1)东部区域延伸到大平原,被称为中央平原造山运动。 
思考 3:科罗拉多造山运动的东部区域延伸到大平原。因此,我需要搜索“大平原”的海拔范围。 
行动 3:搜索[大平原] 
观察 3:“大平原”指的是两种不同的土地区域之一。 
思考 4:我需要改为搜索“美国大平原”。 
行动 4:搜索[美国大平原] 
观察 4:大平原是大平原的一个子区域。从东到西,大平原的海拔从约 1,800 英尺(550 米)上升到 7,000 英尺(2,130 米)。 
思考 5:大平原的海拔范围是从约 1,800 英尺到 7,000 英尺,因此答案是 1,800 英尺到 7,000 英尺。 
行动 5:完成[1,800 英尺到 7,000 英尺]

通用ReAct智能体提示词模版

以下提供的提示词模版是对ReAct的抽象和总结,通过以下模版,开发人员可以定义 AI Agent的基本角色和用户场景,以及智能体能够和外界交互的可用工具集。同时指导智能体在执行特定任务时,需遵从“思考-》执行任务-》观察-》思考”的迭代过程。

以下的ReAct通用提示词可以使用在任何任务场景,程序员只要稍加调整和修改就可以应用在自己的工具和用例里。

TOOL_DESC = """{name_for_model}: Call this tool to interact with the {name_for_human} API. What is the {name_for_human} API useful for? {description_for_model} Parameters: {parameters} Format the arguments as a JSON object."""

REACT_PROMPT = """Answer the following questions as best you can. You have access to the following tools:

{tool_descs}

Use the following format:

Question: the input question you must answer
Thought: you should always think about what to do
Action: the action to take, should be one of [{tool_names}]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Action Input/Observation can be repeated zero or more times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question

Begin!

Question: {query}"""

以下是该提示词模板的中文翻译:

TOOL_DESC = """{name_for_model}:调用此工具以与{name_for_human} API 交互。{name_for_human} API 有什么用途?{description_for_model} 参数:{parameters} 将参数格式化为 JSON 对象。"""

REACT_PROMPT = """请尽可能准确地回答以下问题。你可以使用以下工具:

{tool_descs}

使用以下格式:

问题:你必须回答的输入问题
思考:你应该始终考虑要做什么
行动:要采取的行动,应为 [{tool_names}] 之一
行动输入:行动的输入
观察:行动的结果
...(此思考/行动/行动输入/观察可以重复零次或多次)
思考:我现在知道最终答案了
最终答案:对原始输入问题的最终答案

开始!

问题:{query}"""

写在最后

由于ReAct需要通过环境来获取信息,因此从环境中获取的信息的准确性会严重影响最终的输出结果。因此开发者需要考虑环境信息的准确和可靠,才能保证ReAct应用的性能和可靠性。

ReAct的推理并不完美,但仍然是一种强大的提示工程方法,它克服了链式推理中的幻觉问题,并使大型语言模型能够成为可以与环境互动的智能体。此外,这是一种非常可解释的方法,因为智能体在行动时会输出其思维过程。

ReAct提示词可以让智能体变的更加聪明,帮助我们解决更加复杂的问题,探索ReAct智能体是一件非常有趣的过程。

我相信你一定好奇,如何使用以上的提示词模版实现一个能够自主思考的智能体,接下来后续的文章我将分析如何通过不同的Agent框架,快速的构建智能体,希望持续关注我的博客文章。

参考文章:

智能体实战之autogen:智能体生成shell脚本并执行

使用智能体生成脚本并执行

智能体如何使用工具,是研究智能体非常重要的一部分。通过使用脚本,可以赋予智能体使用Linux系统的各式各样的命令行工具来执行特定任务,本文提供非常简单的例子,使用autogen生成脚本并执行用户指定的任务。

智能体介绍

参考文章:什么是智能体

Autogen

AutoGen是一个开源编程框架,用于构建AI智能体并促进多个智能体之间的合作以解决任务。AutoGen旨在提供一个易于使用且灵活的框架,以加速智能体AI的开发和研究,类似于深度学习中的PyTorch。它提供的功能包括能够与其他智能体对话的智能体、支持LLM和工具使用、自治和人机协作工作流程以及多智能体对话模式。

主要功能

  • AutoGen使得基于多智能体对话构建下一代LLM应用程序变得轻松便捷。它简化了复杂LLM工作流程的协调、自动化和优化,最大化LLM模型的性能,并克服其弱点。
  • 它支持多种对话模式以应对复杂工作流程。通过可定制且可对话的智能体,开发人员可以使用AutoGen构建与对话自主性、智能体数量和智能体对话拓扑相关的各种对话模式。
  • 它提供了一系列具有不同复杂性的工作系统。这些系统涵盖了来自各种领域和复杂性的广泛应用,展示了AutoGen如何轻松支持多样的对话模式。

环境准备

  • Linux or Windows WSL
  • python 3.10+
  • 安装 anaconda

本文使用anaconda构建python虚拟环境:


#创建autogen的虚拟环境
conda create --name autogen python=3.11

#进入该虚拟环境
conda activate autogen

# 安装autogen
pip install autogen-agentchat~=0.2

导入相关的依赖库

import os
import tempfile

from autogen import ConversableAgent
from autogen.coding import LocalCommandLineCodeExecutor

构建系统提示词

使用系统提示词定义智能体的角色,指导行为,提供一定的背景信息,同时也可以约束智能体,当用户行为超出智能体能力边界时,提示用户。

以下提示词指导智能体通过生成脚本,来收集Linux系统的一些信息。该提示词为one-shot提示词。提供代码块的样例给大模型。

以下系统提示词将传递给代码生成智能体,指导代码生成智能体生成脚本代码。


script_executor_message = """You are shell script assistant, a expert of linux and shell script, and you will generate shell script and get information according to user's prompt.
Gnerate a script according user's requirments with below format:

    #```bash  此处因为显示格式的原因加了注释,实际使用时请删除#
    #!/bin/bash

    # query all files information in current directory
    ls -la

    #``` 此处因为显示格式的原因加了注释,实际使用时请删除#
Always thinking step by step to about users questions, make sure your answer is correct and helpful.
If user did not ask question about Linux system, then please response like:

Please ask me question about Linux system, I only could help you on that.

"""

创建和脚本执行器

代码执行器是autogen智能体的一个组件,在创建autogen智能体实例之前需要先初始化代码执行器,并作为参数传递给autogen智能体的实例,代码执行器主要用来执行代码。

# Create a temporary directory to store the code files.
temp_dir = tempfile.TemporaryDirectory()

# Create a local command line code executor.
script_executor = LocalCommandLineCodeExecutor(
    timeout=10,  # Timeout for each code execution in seconds.
    work_dir=temp_dir.name,  # Use the temporary directory to store the code files.
)

创建代码生成智能体实例

ConversableAgent class 是对智能体的抽象,autogen中使用该类来创建智能体实例。通常你需要提供一些参数,max_consecutive_auto_reply=1 配置智能体只能回复一次,system_message用来配置系统提示词。llm_config 用来配置大模型作为后端,我选择使用deepseek-chat模型,国产模型性价比非常高,api调用也没有太多限制。代码生成方面,deepseek已经非常优秀了。code_execution_config=False 配置关闭代码执行功能。human_input_mode="NEVER"配置智能体自动回复,不需要人的介入。

以下代码创建了一个负责生成脚本代码的智能体实例。

script_generate_agent = ConversableAgent(
    "code_writer_agent",
    max_consecutive_auto_reply=1,
    system_message=script_executor_message,
    llm_config={"config_list": [{"model": "deepseek-chat", "api_key": os.environ["OPENAI_API_KEY"], "base_url":"https://api.deepseek.com"}]},
    code_execution_config=False,  # Turn off code execution for this agent.
    human_input_mode="NEVER",
)

创建代码执行智能体

以下代码创建了代码执行的智能体实例,只负责解析和执行代码,因此该智能体不需要接入大模型,配置llm_config=False。code_execution_config={"executor": script_executor} 用来配置代码执行器。

# Create an agent with code executor configuration.
code_executor_agent = ConversableAgent(
    "code_executor_agent",
    max_consecutive_auto_reply=1,
    system_message=script_executor_message,
    llm_config=False,
    code_execution_config={"executor": script_executor},  # Use the local command line code executor.
    human_input_mode="NEVER", 
)

初始化任务

以下代码最终将会启动两个智能体,首先脚本生成智能体将根据输入信息生成相应的脚步,代码执行智能体接受脚本生成智能体的输出作为输入,解析脚本,并执行。

chat_result = code_executor_agent.initiate_chat(
    script_generate_agent,
    message="Get Linux OS information",
)

执行结果如下:

$ python simple_script_executor.py
flaml.automl is not available. Please install flaml[automl] to enable AutoML functionalities.
code_executor_agent (to code_writer_agent):

Get Linux OS information

--------------------------------------------------------------------------------
[autogen.oai.client: 10-07 11:47:55] {349} WARNING - Model deepseek-chat is not found. The cost will be 0. In your config_list, add field {"price" : [prompt_price_per_1k, completion_token_price_per_1k]} for customized pricing.
code_writer_agent (to code_executor_agent):

    #```bash 此处因为显示格式的原因加了注释,实际使用时请删除#
    #!/bin/bash

    # Get Linux OS information

    # Display the Linux distribution information
    echo "Linux Distribution Information:"
    lsb_release -a 2>/dev/null || cat /etc/*release 2>/dev/null || cat /etc/issue 2>/dev/null
    echo ""

    # Display kernel version
    echo "Kernel Version:"
    uname -r
    echo ""

    # Display system architecture
    echo "System Architecture:"
    uname -m
    echo ""

    # Display CPU information
    echo "CPU Information:"
    lscpu
    echo ""

    # Display memory information
    echo "Memory Information:"
    free -h
    echo ""

    # Display disk usage
    echo "Disk Usage:"
    df -h
    echo ""

    # Display network interfaces
    echo "Network Interfaces:"
    ip a
    echo ""

    # Display hostname
    echo "Hostname:"
    hostname
    echo ""

    # Display uptime
    echo "Uptime:"
    uptime
    echo ""
    #``` 此处因为显示格式的原因加了注释,实际使用时请删除#

This script will provide a comprehensive overview of your Linux system, including distribution information, kernel version, system architecture, CPU information, memory usage, disk usage, network interfaces, hostname, and uptime.

--------------------------------------------------------------------------------

>>>>>>>> EXECUTING CODE BLOCK (inferred language is bash)...
code_executor_agent (to code_writer_agent):

exitcode: 0 (execution succeeded)
Code output: Linux Distribution Information:
Distributor ID: Ubuntu
Description:    Ubuntu 22.04.4 LTS
Release:        22.04
Codename:       jammy

Kernel Version:
5.15.153.1-microsoft-standard-WSL2

System Architecture:
x86_64

CPU Information:
Architecture:                       x86_64
CPU op-mode(s):                     32-bit, 64-bit
Address sizes:                      39 bits physical, 48 bits virtual
Byte Order:                         Little Endian
CPU(s):                             12
On-line CPU(s) list:                0-11
Vendor ID:                          GenuineIntel
Model name:                         12th Gen Intel(R) Core(TM) i5-12400
CPU family:                         6
Model:                              151
Thread(s) per core:                 2
Core(s) per socket:                 6
Socket(s):                          1
Stepping:                           2
BogoMIPS:                           4991.99
Flags:                              fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon rep_good nopl xtopology tsc_reliable nonstop_tsc cpuid pni pclmulqdq vmx ssse3 fma cx16 pdcm sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow vnmi ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdseed adx smap clflushopt clwb sha_ni xsaveopt xsavec xgetbv1 xsaves avx_vnni umip waitpkg gfni vaes vpclmulqdq rdpid movdiri movdir64b fsrm md_clear serialize arch_lbr flush_l1d arch_capabilities
Virtualization:                     VT-x
Hypervisor vendor:                  Microsoft
Virtualization type:                full
L1d cache:                          288 KiB (6 instances)
L1i cache:                          192 KiB (6 instances)
L2 cache:                           7.5 MiB (6 instances)
L3 cache:                           18 MiB (1 instance)
Vulnerability Gather data sampling: Not affected
Vulnerability Itlb multihit:        Not affected
Vulnerability L1tf:                 Not affected
Vulnerability Mds:                  Not affected
Vulnerability Meltdown:             Not affected
Vulnerability Mmio stale data:      Not affected
Vulnerability Retbleed:             Mitigation; Enhanced IBRS
Vulnerability Spec rstack overflow: Not affected
Vulnerability Spec store bypass:    Mitigation; Speculative Store Bypass disabled via prctl and seccomp
Vulnerability Spectre v1:           Mitigation; usercopy/swapgs barriers and __user pointer sanitization
Vulnerability Spectre v2:           Mitigation; Enhanced IBRS, IBPB conditional, RSB filling, PBRSB-eIBRS SW sequence
Vulnerability Srbds:                Not affected
Vulnerability Tsx async abort:      Not affected

Memory Information:
               total        used        free      shared  buff/cache   available
Mem:            15Gi       695Mi        14Gi       3.0Mi       591Mi        14Gi
Swap:          4.0Gi          0B       4.0Gi

Disk Usage:
Filesystem      Size  Used Avail Use% Mounted on
none            7.8G     0  7.8G   0% /usr/lib/modules/5.15.153.1-microsoft-standard-WSL2
none            7.8G  4.0K  7.8G   1% /mnt/wsl
drivers         451G  282G  169G  63% /usr/lib/wsl/drivers
/dev/sdc        251G   24G  215G  10% /
none            7.8G   84K  7.8G   1% /mnt/wslg
none            7.8G     0  7.8G   0% /usr/lib/wsl/lib
rootfs          7.8G  2.2M  7.8G   1% /init
none            7.8G  780K  7.8G   1% /run
none            7.8G     0  7.8G   0% /run/lock
none            7.8G     0  7.8G   0% /run/shm
tmpfs           4.0M     0  4.0M   0% /sys/fs/cgroup
none            7.8G   76K  7.8G   1% /mnt/wslg/versions.txt
none            7.8G   76K  7.8G   1% /mnt/wslg/doc

Network Interfaces:
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet 10.25.25.254/32 brd 10.25.25.254 scope global lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0:  mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:15:5d:dd:f0:b7 brd ff:ff:ff:ff:ff:ff
    inet 111.21.22.44/20 brd 111.21.22.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::215:5dff:fedd:f0b7/64 scope link
       valid_lft forever preferred_lft forever

Hostname:
PC-XXXXXXYY

Uptime:
 11:47:56 up 1 min,  1 user,  load average: 0.54, 0.16, 0.05

提示词工程-少样本提示词

少样本提示词(few-show-prompt)

少样本提示(Few-shot Prompting)是一种用于大语言模型(LLM)的技术,通过提供少量示例来引导模型生成更符合预期的输出。这种方法在处理复杂任务时相较于零样本提示(Zero-shot Prompting)表现更佳,有时候会出现事半功倍的效果,因为它为模型提供了上下文和具体的示例,有助于模型理解用户的需求。

定义与原理

少样本提示的核心在于通过给定一小部分示例,帮助模型在特定任务上进行学习和推理。与零样本提示不同,后者不提供任何示例,完全依赖模型的预训练知识。例如,在少样本提示中,可以提供一个新词的定义及其使用示例,以帮助模型理解如何在句子中正确使用该词[1][2][3]。

应用场景

少样本提示适用于多种场景,尤其是那些需要特定领域知识或复杂推理的任务。以下是一些典型应用:

  • 语言生成:通过提供语境和示例,改善文本生成的质量。
  • 情感分析:使用标记示例帮助模型识别文本中的情感倾向。
  • 特定领域任务:如法律、医学等领域,可以通过少量高质量示例来提高输出的准确性[3][4].

少样本或多样本提示词已经成为其他提示词工程的基础,比如思维链提示词就是通过少样本演变来的提示词工程技术,除了思维链提示词,其他提示词技术都涉及到提供示例来引导大模型输出更加准确可控的信息。

另外当我们使用提示词工程相关的技术应用到编程领域时,可以通过少样本提示词,精确的控制模型的输出,这样的话,程序就可以很容易的解析输出格式,增强软件的鲁棒性。

技巧与注意事项

在实施少样本提示时,有几个技巧可以提高效果:

  • 使用标签:在示例中添加标签可以帮助模型更好地理解任务要求,即使标签格式不统一也能有效提升性能[1][2]。
  • 多样性与质量:所提供示例的多样性和质量直接影响模型的输出效果。垃圾进则垃圾出,低质量的示例可能导致错误的结果[3][4]。
  • 思维链技术:结合思维链(Chain of Thought)提示,可以引导模型进行逻辑推理,从而提高复杂问题的回答准确性[4][5].

局限性

尽管少样本提示具有许多优点,但它也存在一些局限性:

  • 依赖于示例质量:如果提供的示例不够清晰或相关,可能会导致模型输出不准确或不相关的信息。
  • 过拟合风险:模型可能会过度依赖给定的示例,而无法泛化到新的、未见过的情况[2][3]。

总之,少样本提示是一种强大的工具,可以显著提升大语言模型在复杂任务中的表现,但成功实施这一技术需要精心设计和选择高质量的示例。

少样本提示词的一些实例:

  • JSON格式输出:
输入: 创建一个包含姓名和年龄的人员信息
输出: 
{
  "name": "张三",
  "age": 30
}

输入: 创建一个包含书名和作者的图书信息
输出: 
{
  "title": "三体",
  "author": "刘慈欣"
}

输入: 创建一个包含产品名称和价格的商品信息
输出:
  • 函数定义格式:
输入: 创建一个计算两数之和的Python函数
输出:
def add_numbers(a, b):
    return a + b

输入: 创建一个判断字符串是否为回文的Python函数
输出:
def is_palindrome(s):
    return s == s[::-1]

输入: 创建一个计算给定数字阶乘的Python函数
输出:
  • SQL查询格式:
输入: 从users表中选择所有用户的名字和邮箱
输出:
SELECT name, email FROM users;

输入: 从products表中选择价格高于100的所有产品
输出:
SELECT * FROM products WHERE price > 100;

输入: 从orders表中选择2023年1月1日之后的所有订单
输出:
  • HTML模板格式:
输入: 创建一个包含标题和段落的HTML结构
输出:
<div class="content">
  <h1>标题</h1>
  <p>这是一个段落。</p>
</div>

输入: 创建一个包含图片和描述的HTML结构
输出:
<figure>
  <img src="image.jpg" alt="描述">
  <figcaption>图片描述</figcaption>
</figure>

输入: 创建一个包含无序列表的HTML结构
输出:

这些例子展示了如何使用少样本提示来指导AI生成特定格式的代码或输出。通过提供一两个例子,AI可以学习并推断出所需的格式和结构。

参考文章

[1] https://www.sohu.com/a/788035576_120635785
[2] https://www.promptingguide.ai/zh/techniques/fewshot
[3] https://www.53ai.com/news/qianyanjishu/2024061397638.html
[4] https://learn.tishi.top/docs/advanced/few-shot-prompting/
[5] https://www.woshipm.com/share/6111304.html
[6] https://sspai.com/post/91879
[7] https://v2-ai.tutorial.hogwarts.ceshiren.com/ai/aigc/L2/tutorial/%E5%B0%91%E6%A0%B7%E6%9C%AC%E6%8F%90%E7%A4%BA/
[8] https://cloud.baidu.com/qianfandev/topic/267310
[9] https://www.promptingguide.ai/techniques/fewshot
[10] https://www.prompthub.us/blog/the-few-shot-prompting-guide

大语言模型时代,聊聊自然语言编程

大语言模型时代,聊聊自然语言编程

计算机及编程语言的发展历史,其实就是从机器语言发展到接近人的自然语言编程的发展过程,这种发展,从来没有停歇。可是过去所有从低级到高级的编程语言,都不是真正的自然语言编程,直到今天,大语言模型横空出世,使得达到这一目标,向前迈了一大步。

在计算机的早期阶段,人们主要通过机器语言与计算机进行沟通。最初的计算机如ENIAC,只能通过插拔电线和设置开关来进行编程。随着时间的推移,汇编语言出现了,它用一些简短的符号(助记符)代表机器指令,这在一定程度上简化了编程工作,人们可以通过简单的指令来控制计算机执行流程,按照人类预想的流程执行。可以汇编还是接近计算机的机器指令,需要编程人员对硬件,指令集有良好的掌握,汇编语言非常难以理解,普通人很难阅读。

到了1950年代,高级编程语言如FORTRAN、COBOL和LISP开始出现。与纯粹的机器代码相比,这些语言更接近人类的思维方式,但仍然是程序员们为计算机量身定制的“新语言”,需要学习和掌握特定的语法和逻辑结构。相比于汇编,这些编程语言容易学习,屏蔽了底层计算指令,程序员只需要关注到编程本身的任务。

进入1970年代,C语言的诞生进一步推动了编程的普及。C语言不仅功能强大,还因其可移植性成为编程世界中的“通用语言”。此后,Python、Java等更高层次的编程语言相继出现,随着它们语法的简化和功能的增强,编程的门槛逐渐降低,更多的人能够参与到编程世界中来。

然而,这些语言尽管更加简洁和直观,仍然要求使用者具备一定的编程思维和逻辑能力,离我们平常使用的自然语言还有相当的距离。

自然语言编程的概念由来已久,但真正的实现却受限于技术的发展。20世纪末和21世纪初,随着计算能力的提升和人工智能的进步,基于自然语言的编程逐渐成为可能。

早期的尝试主要集中在有限领域的自然语言处理(NLP)上,比如通过简单的命令行工具让计算机理解基本的语句。此时的自然语言编程更多是一种“增强”的脚本编程,依然要求使用者遵循特定的语言结构。

随着深度学习技术的发展,特别是大语言模型(如GPT系列)的出现,自然语言编程迎来了质的飞跃。这些模型能够处理复杂的语言任务,理解并生成符合人类表达习惯的语句。这意味着,人们可以用更接近自然语言的方式与计算机互动,甚至可以通过简单的描述生成完整的代码段。

今天,开发者已经可以通过像ChatGPT这样的模型,将自然语言直接转化为代码。这不仅降低了编程的难度,也打开了非程序员进入编程世界的大门。比如,你可以直接描述你想要实现的功能,AI会自动生成相关代码,极大地提升了开发效率。

未来,自然语言编程有望彻底改变我们与计算机的互动方式。编程可能不再是少数人的专利,而是人人都能掌握的一种技能。我们可能只需要用自然语言描述问题或需求,计算机就能自动生成解决方案。这种技术不仅能够简化编程过程,还能推动跨学科的创新,让更多领域的人士能够利用编程工具解决他们领域中的问题。

自然语言编程的发展不仅是技术的进步,更是人类对语言和思维方式的探索与重塑。随着大语言模型的不断进化,编程将变得更加普及和智能,最终实现人人皆能编程的愿景。

什么是自然语言编程?

自然语言编程的定义:

自然语言编程(Natural Language Programming, NLP)是一种编程范式,允许程序员使用自然语言(如英语,甚至是其他各种人类语言)编写代码,而不是使用传统的编程语言语法。这种方法旨在使编程更加直观和易于理解,从而降低编程的学习曲线。

自然语言编程的核心思想是让计算机能够理解和执行用自然语言表达的指令。这需要自然语言处理(NLP)技术来分析和解释人类语言,并将其转换为计算机可执行的形式。

自然语言编程的一些特点包括:

  • 使用接近人类语言的语法和词汇,而不是传统编程语言的严格语法规则
  • 允许使用更多的上下文和隐含信息,而不是显式指定每个细节
  • 支持更自然的交互方式,如问答、对话式编程等
  • 提供更人性化的错误提示和反馈

自然语言编程的实现方式:

  • 代码自动生成:用户通过自然语言描述想要实现的功能,编程工具或系统会自动生成相应的代码。例如,在描述一个计算任务时,系统会将描述转换为Python、JavaScript或其他语言的代码。

  • 编程辅助:自然语言编程也可以作为一种编程辅助工具,帮助程序员快速编写代码段或调试代码。例如,开发者可以用自然语言描述要实现的逻辑,系统提供相应的代码建议或直接生成代码。

  • 多语言支持:自然语言编程不局限于单一的自然语言,它可以支持多种语言,用户可以使用自己熟悉的语言与计算机互动。

  • 人机语音交互:自然语言编程的终极目标就是通过自然语言交互,实现计算机自主理解及执行相应的任务,在可见的未来,人类不需要额外的输入,就可以通过自然语言的交互,实现计算机自主执行任何任务。

大模型时代的自然语言编程技术

在大模型技术出现之前,编程始终是程序员的技术活,每一种语言都存在一定的学习曲线,尤其像C++这种成熟的面向对象语言,灵活的语法,以及非常复杂的规范和标准,成为C++语言的熟练工,可真不是件容易的事,这需要数年甚至数十年的积累和经验。据不完全统计,目前至少有超过700种编程语言,而这个数字还在不断增长。但是接近纯自然语言的编程语言至今还未出现。

如今,大语言模型的出现,可以预见的是正在改变计算机编程的游戏规则,大模型时代的自然语言编程技术代表着计算机与人类互动方式的一次重大变革。在大规模预训练语言模型(如GPT系列、BERT等)的推动下,计算机能够以更加智能和自然的方式理解和处理人类的自然语言描述。这一技术的发展极大地简化了编程过程,使得更多的人能够以自然语言的方式进行编程,降低了技术门槛,提升了开发效率。

大语言模型的核心优势在于:

  • 强大的理解能力:大语言模型可以理解复杂的自然语言描述,包括上下文、隐含意义和复杂的逻辑结构。这使得用户可以用接近日常交流的语言与计算机互动,而不需要掌握传统编程语言的语法和规则。
  • 多领域知识:这些模型不仅懂得编程语言,还拥有广泛的背景知识,涵盖多个领域。这使得它们能够生成与特定领域相关的代码,并且在复杂应用中提供有价值的帮助。
  • 记忆:大模型具有一定的记忆,能够根据交互的上下文背景和人进行交互,这和人类的交谈是相似的,因此大模型在编程领域可以模拟人的行为。

基于大语言模型进行自然语言编程的不同方法

提示词工程

提示词工程无疑是和大语言模型交互的重要技术,这种技术完全可以应用到编程领域。

  • 描述: 用户通过自然语言描述要执行的任务,并将该描述(prompt)传递给大语言模型。模型会根据提示生成相应的代码或直接执行操作。Prompt的设计至关重要,它需要足够明确和具体,以便模型理解用户的意图。
  • 应用场景: 代码生成(如自动生成Python脚本)、任务执行(如数据库查询)、问题回答等。
使用提示词生成代码

目前市面上几乎所有的通用大模型都支持prompt生成代码,比如ChatGPT,Claude, Gemini等,也包括一些开源大模型,例如llama, qianwen等等,另外还有一些专业模型专门针对编程领域,例如llama coder,deepseek coder等等。

使用这些大模型,你可以通过自然语言描述特定的需求,直接使用大模型生成期望的代码。

例如我使用以下提示词生成了一个检查密码强度的工具:

请扮演软件工程师的角色,您擅长分析需求、设计软件和编码,您能否帮助我按照以下步骤一步一步设计和实现密码强度检查器:
步骤 1:列出密码强度检查器的可能功能和要求。
步骤 2:设计此密码强度检查器的软件。
步骤 3:根据您的设计实现功能和要求。
请帮助一步一步完成。请使用Golang,生成命令行应用程序
请用中文书写。

讲该prompt输入至ChatGPT时,GPT可以帮我做简单的分析和设计,并生成相应的代码:


package main

import (
    "fmt"
    "unicode"
)

func main() {
    var password string
    fmt.Print("请输入密码: ")
    fmt.Scanln(&password)

    strength := checkPasswordStrength(password)
    fmt.Printf("密码强度评分: %d/10\n", strength)

    if strength < 7 {
        fmt.Println("建议:请使用更复杂的密码,包括大小写字母、数字和特殊字符。")
    } else {
        fmt.Println("密码强度良好。")
    }
}

func checkPasswordStrength(password string) int {
    score := 0

    // 长度检查
    if len(password) >= 8 {
        score += 2
    } else {
        fmt.Println("密码长度应至少为8个字符。")
    }

    // 字符种类检查
    var hasUpper, hasLower, hasDigit, hasSpecial bool
    for _, char := range password {
        switch {
        case unicode.IsUpper(char):
            hasUpper = true
        case unicode.IsLower(char):
            hasLower = true
        case unicode.IsDigit(char):
            hasDigit = true
        case unicode.IsPunct(char) || unicode.IsSymbol(char):
            hasSpecial = true
        }
    }

    if hasUpper {
        score += 2
    }
    if hasLower {
        score += 2
    }
    if hasDigit {
        score += 2
    }
    if hasSpecial {
        score += 2
    }

    return score
}
大模型智能体应用

基于提示词工程,不仅仅可以通过自然语言生成代码。大模型时代的应用,将基于智能体编程模式,开启智能应用时代。基于智能体模式,相比传统应用程序,智能应用的交互模式发生了革命性的变化,应用程序完全可以理解人的自然语言输入,智能应用程序将通过理解人的语言进行思考,并以一定的自主能力来执行复杂的任务。

因此,自然语言编程的范畴并不仅仅是通过自然语言来生成代码,广义含义也包含了使用自然语言直接执行任务。

同时智能体应用本身的程序也将不再完全由程序代码来构建的,程序的核心部分将基于提示词工程的自然语言部分,比如react提示词模式,和COT(chain-of-thought)模式。剩余的部分包括大模型的API,数据库交互,记忆模块,以及工具的使用,将使用传统的编程模式。基于prompt的编程将是自然语言编程的重要组成部分。

通过智能体应用,应用程序将会更加智能化,人机交互方式将会发生革命性的转变,任务和指令将通过自然语言的方式进行输入,程序的反馈也将更加人性,更符合人与人的交流方式。

辅助编程

辅助编程技术,实际上是编程IDE诞生以来,一直在发展的技术,在生成式模型出现之前,传统的辅助编程工具可以帮助程序员建立代码索引,通过联想,自动补全等功能帮助程序员更加快速的找到已有函数,接口,变量等,提示编程效率。

辅助编程技术通过生成模型技术,已经发生了革命性的转变。用户可以通过自然语言与大模型进行互动,逐步引导模型生成代码。用户可以实时修正或者调整模型生成的代码,以确保最终结果符合预期。

辅助编程工具一般都是基于编程IDE来实现的,比如当下著名的编程助手 Github Copilot,Cursor 等,程序员仅仅通过自然语言提示,就可以生成代码,测试及文档,大大的提高了编程效率。这些工具除了可以编程外,还可以帮助重构,调试代码。

代码翻译

由于专业的大模型熟悉不同编程语言的语法和语义,因此程序员可以用自然语言描述现有代码段的逻辑或意图,指示大模型将一种语言的代码片段,翻译成其他语言的代码片段,这种特性将在跨语言的代码迁移、旧代码重构、多语言项目的代码管理等领域得到重要的应用。

写在最后

自然语言编程将是我未来的一个主要研究方向,我相信未来,越来越多的人会使用自然语言方式进行编程,未来的应用程序也将更加智能,编程将不在是程序员的专利,更多的人将参与到数字化世界的构筑,使得这个世界更加丰富多彩。

参考文章:

https://arxiv.org/html/2405.06907v1
https://arxiv.org/abs/2405.06907
https://juejin.cn/post/7348648095015567412
https://www.yunwei37.com/2023/06/14/natual-language-program/

提示词工程-零样本提示词

零样本提示词

什么是零样本提示词

零样本提示词,顾名思义就是在人和大模型之间交互时,提示词中可以不使用任何样例,大模型只根据提示词中的指示以及预训练的固有知识生成内容或回答问题。

零样本提示词可以是一句话,一个问题,或者一条指令,但是如果期望大模型生成准确有效的信息,零样本提示词也需要遵循一定的结构,具体的信息可以参考另一篇文章:高效提示词的基本结构

假设你想使用一个语言模型来判断一段文本的情感是积极、消极还是中性。你可以向模型提出这样的问题:

“请对这段文本进行情感分类:‘我在海滩度过了一个很棒的一天!’它是积极的、消极的还是中性的?”

指令微调已经被证明可以提高零样本学习的效果(Wei et al., 2022)。指令微调本质上是指在通过指令描述的数据集上对模型进行微调。此外,RLHF(从人类反馈中进行强化学习)已被用于扩展指令微调,其中模型被调整以更好地符合人类偏好。这种最近的发展推动了像ChatGPT这样的模型的出现。我们将在接下来的章节中讨论所有这些方法。

当零样本不起作用时,建议在提示中提供演示或示例,这就是所谓的少样本提示。

零样本提示词的优缺点

优点:零样本提示在需要快速回答而无需准备示例时非常有用。它还有助于测试模型的一般语言理解能力。

缺点:与少样本或微调模型相比,零样本提示的准确度可能较低,尤其对于复杂任务或与训练数据差异很大的任务。

参考文章

Zero-shot and Few-shot prompting in LLMs
zeroshot
zeroshot prompting

思维链提示词工程(Chain-of-Thought Prompting)

思维链提示词工程

扩大大型语言模型(LLMs)的规模在情感分析和机器翻译方面已经显示出了良好的结果,即使没有提供任何示例。然而,它们在解决复杂的多步骤问题,如算术和常识推理方面却表现不佳。为了解决这个问题,LLMs可以针对特定任务进行微调,或者通过少量示例提示(few-shot prompting)来教授。然而,这两种方法都有其局限性。微调在创造高质量推理方面成本较高,而仅使用少量示例提示对于任务来说效果不够好。

思维链(Chain-of-Thought,简称CoT)提示可以同时解决这两个问题。在本文中,我们将探讨CoT提示以及如何实施它来提升您的业务技能。

什么是提示工程?

提示工程是一种编写结构良好、精心设计的提示的实践,这些提示能被生成性AI模型更好地理解。提示告诉大型语言模型(LLM)需要执行什么任务以及生成什么样的输出。它可以包含指令、上下文、输入数据和输出指标。通过使用提示工程,我们可以利用LLM来完成各种任务,从简单的问题回答到复杂的创意文本生成。它基于一种新兴属性——上下文学习,允许LLM从提示中学习。提示工程提高了LLM在手头任务上的表现。它使用了前文提到的零样本、少样本、主动和思维链提示等技术。

零样本提示

在零样本提示中,我们给大型语言模型(LLM)一个描述任务的提示,但这个提示本身并不提供任何任务的示例。然后,我们要求LLM针对这个提示生成一个回答。这种方法增强了LLM的灵活性和泛化能力。它可以用来在多个任务上训练LLM,而无需为每个任务收集训练数据。例如,ChatGPT可以在没有任何写诗示例的情况下,根据提示工程写出一首诗。然而,零样本提示在处理复杂任务时是有限的。

少样本提示

少样本提示可以通过提供示例来引导模型获得更好的表现。这是一种向大型语言模型提供少量期望输出示例的技术,除了主要提示之外还包括这些例子。这些示例帮助模型更好地理解任务,从而生成更准确、更有信息量的回答。我们应该向模型提供丰富多样的例子,而不是多个相似的例子。这样做可以确保模型尽可能多地学习关于任务的知识。标准的少样本提示对许多任务来说是一种不错的技术,但对于复杂的推理任务则不太可靠。因此,我们需要更高级的提示技术,比如思维链、主动提示和微调等。

主动提示

主动提示通过不断给予大型语言模型(LLM)反馈来提高它们在复杂任务上的表现。这种反馈可以帮助LLM从错误中学习,生成更准确、更有价值的回答。
主动提示的过程是这样的:首先给LLM一个提示和一些期望输出的例子。然后LLM生成一个回答。接着,人类评估者会评价这个回答,并就其准确性和信息量给出反馈。LLM再利用这些反馈来改进自己生成回答的能力。这个过程会不断重复,直到LLM能够生成足够准确和有价值的回答,让人类评估者满意为止。
主动提示对于思维链(CoT)提示特别重要,因为它可以:

  • 找出需要重点标注的问题
  • 减少人工标注的工作量
  • 提高CoT提示的准确性和信息量

下图展示了如何通过主动提示配合CoT来提升性能。这是一个包含四个阶段的过程:

  • 通过多次查询LLM来估计一个问题的不确定性
  • 通过排序选出最不确定的问题进行标注
  • 由人类评估者对这些问题进行详细反馈标注
  • 利用LLM生成答案,并使用标注阶段的反馈来提高新问题答案的质量

什么是思维链提示?

思维链提示是一种提示工程技术。通过这种技术,我们能让大型语言模型(LLM)输出一系列中间步骤,最终得出所需的答案。这种方法能提高LLM的推理能力。

思维链提示的好处有:

  • 让模型能专注于一次解决一个步骤,而不是一下子考虑整个问题。
  • 对于那些难以或无法一步解决的复杂问题特别有帮助。
  • 为我们提供了一个可解释的窗口,让我们能看到模型的行为。我们可以通过跟随模型采取的步骤序列,了解它是如何得出答案的。

总的来说,思维链提示让我们能更好地理解和控制LLM的思考过程,从而得到更准确、更可靠的结果。

思维链(CoT)提示可以用于参数量很大(大约1000亿个参数)的大型语言模型,适用于多种推理任务,包括数学应用题、常识推理和符号运算。

举个例子,在PaLM模型中使用CoT提示,而不是标准的少样本提示,显著提高了在GSM8K基准测试中的表现,
从17.9%提升到了58.1%。

有趣的是,对于足够大的语言模型来说,不需要特殊训练或微调,就可以轻松引出CoT推理过程。这个特点使得CoT提示成为一种可扩展且容易使用的技术。

简单来说,CoT提示就像是给模型一个"思考的框架",让它能像人类一样一步步推理,而不是直接给出答案。这种方法特别适合大型模型,因为它们有足够的"智力"来理解和执行这种复杂的思考过程。而且,因为不需要额外训练,任何人只要有权限使用这些大模型,就可以尝试CoT提示技术。

少样本思维链

少样本提示是指给大型语言模型(LLM)提供一个问题和答案。然后,再给LLM几个解决类似问题的例子。这些例子的呈现方式会鼓励LLM对问题进行思考,形成一条通向答案的思维链。

少样本思维链比普通的少样本基准更有效地提高了LLM的推理能力,因为它为LLM提供了类似问题的例子。不过,少样本思维链的实施可能会比普通少样本基准更复杂,因为它需要创建示例提示。

尽管如此,少样本思维链带来的好处还是超过了额外的复杂性。它让LLM不只是简单地回答问题,而是学会了如何思考和推理。这种方法可以让LLM处理更复杂的问题,给出更详细、更准确的答案。

简单来说,少样本思维链就像是给LLM提供了一些"解题思路"的例子,而不仅仅是答案。这样,LLM就能学会如何一步步地思考问题,而不是只会简单地背诵答案。虽然准备这些例子可能会多花些时间,但最终得到的结果会更好,更有价值。

零样本思维链

零样本思维链是指在原始提示中加入"让我们一步步思考"这句话。它通过两个步骤来提取推理过程和答案。

  • 推理提取:
    在这一步,语言模型思考问题,形成一条通向答案的推理链。我们给语言模型一个包含问题和触发句"让我们一步步思考"的提示。然后,语言模型会生成一个解释它如何得出答案的句子。

  • 答案提取:
    在第二步,我们从语言模型的回答中提取最终答案。我们把提示、生成的句子和一个触发句"答案是"连在一起。这告诉语言模型给我们答案。然后,语言模型会生成一个包含问题答案的句子。

相比之下,零样本基准使用"答案是"这样的提示来提取答案。而少样本提示,无论是标准的还是思维链的,通过设计以正确格式结尾的示例答案,避免了使用这种答案提取提示的需要。

研究人员比较了零样本思维链和其他两种评估大型语言模型零样本推理能力的方法。结果发现,在各种推理任务中,零样本思维链的表现优于其他方法。

如果你想找一个经过思维链提示训练的较小模型,可以考虑Flan-T5模型。它可以用于零样本自然语言处理任务,包括文本摘要、自然语言推理、翻译和常识推理。

思维链能力何时出现?

思维链推理是大型语言模型(LLM)的一种涌现能力,可能是由于模型参数超过1000亿而产生的。对于较小的LLM,思维链并不能提高性能,只有在使用这种规模的模型时才能带来性能提升。这有两个原因:

  • 较小的LLM无法生成既流畅又合乎逻辑的长思维链。这导致其表现不如标准提示。
  • 思维链推理对更复杂的问题更有效。它要求LLM能够识别解决问题的关键步骤,然后生成一连串思考过程,最终得出解决方案。较小的LLM可能无法像大型LLM那样有效地做到这一点。

大型LLM出现思维链推理能力的另一个原因可能与它们的预训练数据有关。大型LLM通常在包含逐步推理的海量数据集上训练,这可能有助于它们发展出以思维链方式推理的能力。

有趣的是,遵循指令的能力似乎并不是思维链能力所必需的。研究显示,使用未经过遵循指令微调的LLM,也能展现零样本和少样本思维链推理。不过,遵循指令的能力可能会提高思维链推理的质量。

如何进行思维链提示?

要进行思维链提示,你只需在提示的末尾加上"让我们一步步思考"这句话。这会迫使模型分步思考,将问题分解成更小的部分。下面是一个例子,展示了不使用和使用思维链提示的区别:

你可以看到,使用思维链让大型语言模型(LLM)给出了更好、更复杂且正确的输出。没有分步思考的提示立即导致了错误的答案。

如果你有一个非常严格的问题,你知道只能用特定的推理模式来解决,那就是你应该使用少样本思维链的时候。你可以提供一些针对你特定问题集所需的推理步骤的例子,然后LLM会尝试用类似的步骤来解决给定的问题。或者,你可以用这种技术为你的用户以特定方法解决问题。比如,如果学生要使用你的应用,你可能想用少样本思维链以有趣、简单且易懂的方式解决问题。

这些少样本例子应该展示中间步骤和最终解决方案。一旦你开发了思维链提示和例子,你就可以将它们整合到模型中。最后,测试模型并反复调整思维链提示和例子,直到模型的表现令人满意。

思维链提示的关键方面

在这部分,我们将探讨影响大型语言模型中思维链提示性能和可靠性的重要维度。我们将深入研究敏感性、自一致性、鲁棒性和连贯性如何在塑造思维链提示技术的有效性中发挥关键作用。

自一致性

自一致性是一种提高语言模型在需要多步推理任务上表现的技术。在思维链提示的背景下,自一致性可以通过为同一个问题采样多个不同的思维链来提高模型的性能。然后,模型可以被训练从这些思维链中选择最一致的答案。

自一致性显著提高了思维链提示在许多流行的算术和常识推理基准测试上的表现。例如,在GSM8K基准测试中,自一致性将思维链提示的性能提高了17.9%。在SVAMP基准测试中提高了11.0%,在AQuA基准测试中提高了12.2%。

这是一种完全无监督的技术,可以直接在预训练的语言模型上使用。它不需要额外的人工标注,也避免了任何其他训练、模型或微调。它对采样策略和参数具有鲁棒性。在PaLM-540B上改变温度采样中的T、top-k采样中的k和核采样策略中的p时,自一致性始终能提高性能。

鲁棒性

研究人员进行了三组不同的思维链标注实验,每组由不同的标注者完成。他们发现,无论是哪个标注者,思维链提示的表现始终优于标准基准。这表明思维链提示不依赖于特定的语言风格。

研究人员还进行了使用从GSM8K训练集随机抽样的样本的实验,这是一个独立的来源。他们发现,使用这些样本的思维链提示与使用手动编写的样本的思维链提示表现相当。这表明思维链提示不依赖于使用的具体样本。

研究人员还进行了使用不同数量样本的实验。他们发现思维链提示对不同数量的样本保持稳定。这表明思维链提示不需要大量样本就能有效。

研究人员还使用了各种语言模型进行实验,包括LaMDA 137B。他们发现思维链提示对所有这些语言模型都有效。这表明思维链提示不依赖于使用的特定语言模型。

总的来说,这些实验结果表明,思维链提示是一种可以提高语言模型在各种任务上表现的稳健技术。它不依赖于特定的语言风格、标注者、样本集或语言模型。

敏感性

思维链提示中的敏感性指的是提示的设计对模型性能的影响程度。如果提示设计不好,模型的性能可能会下降。提示应该清晰、简洁,易于模型理解。应避免使用模型可能不熟悉的行话或技术术语。提示应该与模型试图解决的特定任务相匹配。如果提示与任务不匹配,模型可能无法生成正确的答案。任务越复杂,模型对提示设计的敏感性可能越高。

当提示示例问题类型和任务问题类型不匹配时,少样本思维链的性能下降。这表明少样本思维链对提示的设计高度敏感,需要仔细将提示与特定任务匹配才能获得良好的性能。

连贯性

连贯性指的是思维链推理步骤的正确顺序程度。这意味着后面的步骤不应该是前面步骤的先决条件,前面的步骤也不应该基于后面的步骤。例如,在引入"32"或"42"之前出现"32 + 42 = 74"的推理就不具有连贯性。这是因为"32 + 42 = 74"这个等式是一个后面的步骤,依赖于引入数字"32"和"42"的前面步骤。

研究人员设计了一组消融设置,以检验连贯性对类似思维链推理不同组成部分的影响。消融设置是一种测试系统不同部分重要性的方法,通过移除它们并观察对系统性能的影响。研究发现,连贯性对类似思维链推理的所有组成部分都很重要。当移除连贯性时,系统的性能会下降。

研究人员还发现,语言模板的连贯性对思维链提示的性能特别重要。语言模板是用来连接思维链推理不同步骤的短语。如果语言模板不连贯,模型可能无法理解推理过程并生成正确的答案。

思维链提示的类型

在思维链(CoT)提示领域中,有两种显著的变体作为有影响力的策略:多模态CoT和从少到多提示。让我们详细探讨这些技术。

多模态CoT

传统的CoT专注于语言模态,这意味着它只使用文本为模型提供推理背景。多模态CoT将文本和视觉整合到一个两阶段框架中。

第一步涉及基于多模态信息的推理生成。这意味着模型同时接收文本和图像,然后被要求生成一个解释文本和图像如何相关的推理。

框架的第二阶段是答案推断。在这里,模型使用第一步生成的信息丰富的推理来推断出问题的正确答案。

1B多模态CoT的表现超过GPT-3.5 16个百分点(75.17%对91.68%的准确率),并在ScienceQA基准测试中超过了人类表现。在8个问题类别中,我们的模型将带配对图像的问题的表现从67.43%提高到88.80%。

像UnifiedQA和GPT-3.5这样的方法使用图像说明来理解图像显示的内容,然而,使用图像特征更有效。未来的研究可以通过使用更好的图像特征、添加常识知识和过滤掉无关信息来改进CoT推理。

从少到多提示

思维链提示是一种强大的自然语言推理技术,但在处理比提示中显示的例子更难的问题时可能会遇到困难。为了解决这个挑战,我们提出了一种新的提示策略,称为从少到多提示。

从少到多提示的工作原理是将一个复杂问题分解成一系列更简单的子问题,然后按顺序解决它们。每个子问题都由前面子问题的答案促进。

例如,要解决一个数学应用题,我们可能首先询问语言模型将问题分解成子问题,比如"第一件物品的成本是多少?"和"总成本是多少?"然后我们会询问语言模型依次解决子问题,使用前面子问题的答案来指导我们的查询。

从少到多提示在符号操作、组合泛化和数学推理任务上可以推广到更困难的问题。使用从少到多提示的GPT-3 code-davinci-002可以用14个示例解决SCAN,准确率达到99%,而思维链提示只能达到16%的准确率。

下表显示了不同提示方法在GSM8K和DROP基准测试中仅包含数值问题的子集上的准确率。基础语言模型是code-davinci-002。

下表显示了不同提示方法在最后字母连接任务上的准确率。

自动CoT

自动CoT是一种自动创建带有问题和推理链的演示的方法。它使用大型语言模型为每个演示生成推理链,使用"让我们一步步思考"的提示。自动CoT有两个主要步骤:

  1. 将给定数据集中的问题分成几个集群。
  2. 从每个组中选择一个代表性问题,并使用零样本CoT和简单的启发式方法生成推理链。

演示问题的多样性对于减少零样本CoT在推理链中的错误很重要。通过将问题聚类成几个组,自动CoT可以确保每个演示代表不同类型的问题。这有助于减少零样本CoT在推理链中犯错的机会。

自动CoT在10个推理任务上进行了测试,包括算术推理(MultiArith, GSM8K, AQUA-RAT, SVAMP)、常识推理(CSQA, StrategyQA)和符号推理(最后字母连接,硬币翻转)。在GPT-3中,自动CoT的表现始终与手动CoT相当或超过手动CoT。

这里是自动CoT与四种基线方法的比较:零样本、零样本CoT、少样本和手动CoT。

CoT的应用

CoT的应用涉及各种领域,包括算术、常识、符号推理、自然语言推理和问答。CoT提示为大型语言模型提供了解决这些领域复杂问题的能力。

算术推理

当与540B参数的语言模型一起使用时,思维链(CoT)提示在各种任务上的表现与针对特定任务微调的模型相当,包括算术推理。解决数学应用题对语言模型来说是一项具有挑战性的任务。

为了评估大型语言模型解决数学问题的能力,使用了两个基准测试:MultiArith和GSM8K。标准提示显示这些基准测试的扩展曲线相对平坦,这意味着增加模型大小并不会显著提高性能。然而,当使用CoT提示时,增加模型规模显著提高了性能,特别是对于大型模型。

PaLM(一个540B参数的语言模型)结合CoT提示,在GSM8K基准测试中达到了58%的最高性能。自一致性技术进一步提高了CoT提示的性能,在GSM8K上达到74%的准确率。CoT提示在数学应用题解决方面达到了最高水平,超过了微调的GPT-3基线。

常识推理

思维链提示也可以用于常识推理任务。这些任务需要基于一般知识对物理和人类互动进行推理。常识推理对当前的自然语言理解系统来说是具有挑战性的。

CoT提示在常识推理基准测试上进行了评估,如CommonsenseQA、StrategyQA、日期理解和体育理解。这些任务的性能通常随着模型规模的增加而提高。CoT提示比常规提示有小幅改进。CoT提示在提高体育理解任务的性能方面最为有效。

使用CoT的PaLM 540B在体育理解方面以95%对84%的分数超过了未经辅助的体育爱好者,在StrategyQA上以75.6%对69.4%的分数超过了先前的最高水平,在体育理解上以95.4%对84%的分数超过了先前的最高水平。但在CommonsenseQA(CSQA)上看到的改进很小。

符号推理

思维链提示使语言模型能够执行标准提示难以完成的符号推理任务。它还支持长度泛化,允许模型处理比少样本示例中看到的更长的推理时间输入。

在研究过程中,为了测试CoT提示,使用了两个玩具任务进行评估。第一个是最后字母连接,模型将名字中单词的最后字母连接起来。第二个是硬币翻转,模型确定在人们翻转硬币后,硬币是否仍然正面朝上。

使用域内和域外测试集来评估使用思维链提示(CoT)和标准提示的PaLM 540B在这两个任务上的表现。对于域内评估,示例的步骤数与训练/少样本示例相同。对于域外评估,示例的步骤数比示例中的多。

在域内评估中,使用CoT的PaLM 540B几乎达到100%的解决率。标准提示在域内和域外评估中都失败了。CoT提示导致性能提高,但低于域内评估。

问答

CoT提示通过将复杂问题或提示分解成一系列更简单的逻辑步骤来改进问答(QA)。这种方法帮助语言模型理解问题的结构和其组成部分之间的关系。每个步骤都专注于问题的一个特定方面,帮助模型更有效地识别相关信息。

CoT鼓励模型执行多跳推理,在这种推理中,它迭代地从不同来源或文档中收集和组合信息。这使模型能够执行改进的推理,并将单独的知识片段连接起来,得出准确的答案。

通过明确指定推理步骤,CoT提示可以帮助防止语言模型在回答复杂问题时可能引入的常见错误或偏见。此外,CoT提示允许用户理解模型是如何得出特定响应的。

思维链(CoT)与其他方法的比较

在这部分,我们深入比较思维链提示与其他方法,特别是标准提示和思维树提示。评估它们的优缺点可以为选择最适合你的业务应用的方法提供有价值的见解。

思维链vs标准提示

标准提示使用输入-输出对作为例子。这些对以问题和答案的形式呈现。模型根据这些对预测答案。它在有效处理多步推理任务方面有限制,但适合直接的任务,如单轮问答。它需要较少的计算资源。它通常使用单次提示进行训练,对于复杂任务往往需要更多数据来微调。标准提示可能不会随着模型规模的增加而显著提高性能。

而思维链提示涉及生成中间推理步骤。这些步骤在提供最终答案之前进行。它擅长复杂推理,使模型能够逐步思考。它versatile应用于广泛的需要复杂推理的任务。它需要对一系列提示进行训练,并有效利用数据进行多步推理。它在更大的模型上表现更好,因此需要更多的计算能力。它在复杂推理基准测试和需要多步问题解决的任务中表现出色。

MAWPS基准测试的比较:

长度泛化任务的比较:

对于直接的任务,你可以选择标准提示;对于需要深入、多步推理和可解释性的应用,思维链提示是更好的选择。GitHub上有一个与思维链推理相关的开源数据和工具库。它有各种任务的数据集,如数学问题和常识推理。它还有一个社区论坛供讨论。

思维链vs思维树提示

思维链遵循线性方法,每个新词或想法直接与前一个相连,形成一个链条。它代表了一种顺序的思维组织。

另一方面,思维树(ToT)采用层次方法。想法组织成树状结构,每个想法分支成多个相关想法。它代表了一种更复杂和分支的思维组织。

像GPT-3这样的思维链模型通常擅长在短跨度内生成连贯和与上下文相关的文本。像Transformer模型这样的思维树模型通常更擅长在更长的文本中保持连贯性,并且可以同时跟踪多个相关想法。

由于思维树的层次性,思维链模型在结构上更简单,计算强度也较低。此外,思维树引入了通过强化学习(RL)训练的"ToT控制器"概念。这个控制器可以潜在地从新数据或自我对弈中学习,允许思维树系统在固定语言模型的情况下进化和获取新知识。

思维链-SC(带有思维链的自一致性)使用简单的提示技术。它没有明确提到使用搜索算法。思维树采用广度优先搜索(BFS)和深度优先搜索(DFS)等搜索算法,以实现系统的思维探索。它将这些算法与树结构结合用于问题解决。因此,思维树的表现显著优于其他方法。

对于简单、较短的文本,你可以选择思维链;对于复杂、较长的文本和问题解决任务,思维树可能更合适。

本文翻译自该原文:
https://www.mercity.ai/blog-post/guide-to-chain-of-thought-prompting

本文系本站原创文章,著作版权属于作者,未经允许不得转载,如需转载或引用请注明出处或者联系作者。