DLAI-智能体笔记-全-
<h1 id="dlai-智能体笔记全">DLAI 智能体笔记(全)</h1><h1 id="001欢迎与课程概述-">001:欢迎与课程概述 🚀</h1>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/e6729d36a2d19fb34193ebdc6d38b475_1.png"></p>
<p>在本课程中,我们将学习代理式AI的核心概念与最佳实践,了解如何构建有价值的AI应用。</p>
<p>欢迎来到这门关于代理式AI的课程。当我创造“代理式”这个术语来描述我所看到的人们构建基于AI应用的一个重要且快速增长的趋势时,我并未意识到许多营销人员会抓住这个词,将其作为一个标签贴到几乎所有事物上。这导致了代理式AI的热度急剧飙升。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/e6729d36a2d19fb34193ebdc6d38b475_1.png"></p>
<p>好消息是,抛开炒作不谈,使用代理式AI构建的真正有价值且实用的应用数量也在快速增长,即使速度不如炒作那么快。在本课程中,我将向您展示构建代理式AI应用的最佳实践,并为您开启许多新的机会领域。</p>
<p>如今,代理工作流正被用于构建各种应用,例如客户支持代理、协助撰写深度研究报告的研究工具、处理复杂法律文档,或分析患者输入以提供可能的医疗诊断建议。在我的许多团队中,如果没有代理工作流,很多项目根本无法完成。因此,掌握如何用它们构建应用是当今AI领域最重要、最有价值的技能之一。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/e6729d36a2d19fb34193ebdc6d38b475_3.png"></p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/e6729d36a2d19fb34193ebdc6d38b475_4.png"></p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/e6729d36a2d19fb34193ebdc6d38b475_5.png"></p>
<p>事实证明,我观察到真正懂得如何构建代理工作流的人与不太擅长的人之间最大的区别之一,是推动一个严谨开发流程的能力。具体来说,是专注于<strong>评估</strong>和<strong>错误分析</strong>的流程。在本课程中,我将解释这意味着什么,并向您展示如何能真正擅长构建这些代理工作流。</p>
<p>掌握这项技能是当今AI领域最重要的能力之一,它将为您开启更多机会,无论是工作机会还是自己构建出色软件的机会。</p>
<p>接下来,让我们进入下一个视频,更深入地探讨单代理工作负载。</p>
<h1 id="002什么是代理式ai-">002:什么是代理式AI 🤖</h1>
<p>在本节课中,我们将要学习什么是代理式AI,以及为什么代理式AI工作流如此强大。</p>
<h2 id="概述">概述</h2>
<p>许多人在使用大型语言模型时,习惯于直接给出一个指令,例如“请就某个主题X为我写一篇文章”。这种方式类似于要求一个人(或AI)从第一个字到最后一个字,一气呵成地完成整篇文章,并且不允许使用退格键。事实证明,无论是人类还是AI模型,在这种完全线性的、受约束的写作方式下,都难以发挥最佳水平。然而,尽管存在这种困难,当前的模型表现已经相当不错。</p>
<p>相比之下,代理式工作流则采用了不同的方式。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/7d53b2c3dab94bf0423a511dffff9c71_1.png"></p>
<h2 id="代理式工作流详解">代理式工作流详解</h2>
<p>上一节我们介绍了传统提示方式的局限性,本节中我们来看看代理式工作流的具体过程。</p>
<p>代理式工作流的过程可能如下:首先,你可以要求AI就某个主题撰写一份大纲;接着,询问它是否需要进行研究;在进行一些网络研究并可能下载一些网页后,让它撰写初稿;然后,让它阅读初稿并提出修改建议;最后,根据建议修订草稿,如此循环。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/7d53b2c3dab94bf0423a511dffff9c71_1.png"></p>
<p>这种工作流更接近于人类的创作过程:进行一些思考和研究,然后进行修订,再进行更多思考,等等。通过这种迭代过程,代理式工作流虽然耗时更长,但能产出质量高得多的工作成果。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/7d53b2c3dab94bf0423a511dffff9c71_3.png"></p>
<p>因此,<strong>代理式AI工作流是一个过程,其中基于LLM的应用程序执行多个步骤以完成任务</strong>。</p>
<p>以下是该过程可能涉及的步骤分解:</p>
<ol>
<li>使用LLM撰写文章大纲。</li>
<li>使用LLM决定调用网络搜索API时应使用的搜索词,以获取相关网页。</li>
<li>将下载的网页内容输入给LLM,让其撰写初稿。</li>
<li>可能使用另一个LLM进行反思,决定哪些部分需要进一步修订。</li>
</ol>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/7d53b2c3dab94bf0423a511dffff9c71_3.png"></p>
<p>根据工作流的设计,你甚至可以加入“人在回路”的步骤,让AI可以选择请求人类审查一些关键事实。基于此,AI再修订草稿。这个过程最终能产生更好的输出成果。</p>
<p>在本课程中,你将学习的一项关键技能是:如何将一个复杂任务(如写文章)分解为更小的步骤,以便代理式工作流一次执行一步,最终获得你想要的输出。知道如何将任务分解为步骤,以及如何构建组件来很好地执行各个步骤,是一项棘手但重要的技能,它将决定你为大量激动人心的应用构建代理式工作流的能力。</p>
<h2 id="课程实践示例研究代理">课程实践示例:研究代理</h2>
<p>为了具体说明,本课程将使用一个研究代理作为示例,你可以跟随我一起构建它。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/7d53b2c3dab94bf0423a511dffff9c71_5.png"></p>
<p>以下是该研究代理的工作示例:你可以输入一个研究主题,例如“我如何建立一家新的火箭公司来与SpaceX竞争?”。研究代理会开始规划需要进行的调研,包括调用网络搜索引擎下载相关网页,然后综合并排序发现的信息,起草大纲,让另一个代理审查连贯性,最后生成一份全面的Markdown格式报告。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/7d53b2c3dab94bf0423a511dffff9c71_6.png"></p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/7d53b2c3dab94bf0423a511dffff9c71_7.png"></p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/7d53b2c3dab94bf0423a511dffff9c71_5.png"><br>
<img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/7d53b2c3dab94bf0423a511dffff9c71_6.png"><br>
<img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/7d53b2c3dab94bf0423a511dffff9c71_7.png"></p>
<p>报告会包含引言、背景、发现等部分。它甚至可能恰当地指出,这将是一家难以建立的初创公司。通过查找和下载多个来源并深入思考,这种代理最终能生成一份比直接要求“写一篇文章”更具思想深度的报告。</p>
<p>我对此感到兴奋的原因之一是,在我的工作中,我已经构建了不少专门的研究代理,无论是用于法律文件合规、医疗健康领域,还是商业产品研究。我希望通过这个示例,你不仅能学会如何为许多其他应用构建代理工作流,而且如果你需要构建自己的定制研究代理,其中的一些思路也能直接对你有用。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/7d53b2c3dab94bf0423a511dffff9c71_9.png"></p>
<h2 id="关于自主性的说明">关于自主性的说明</h2>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/7d53b2c3dab94bf0423a511dffff9c71_9.png"></p>
<p>关于AI代理,一个经常被讨论的领域是它们的自主性程度。你刚才看到的便是一个相对复杂、高度自主的代理式AI工作流。但也存在其他更简单却极具价值的工作流。</p>
<p>在下一节视频中,我们将探讨代理工作流可以实现的自主程度,并为你提供一个框架,帮助你思考如何构建不同的应用程序,以及它们的难易程度。</p>
<p>本节课中我们一起学习了代理式AI的基本概念,理解了其通过多步骤迭代提升输出质量的核心原理,并预览了课程中将构建的研究代理示例。</p>
<h1 id="003模块1-5代理的自主程度-">003:模块1-5|代理的自主程度 🎯</h1>
<p>在本节课中,我们将要学习代理式AI系统的一个核心概念:自主程度。我们将探讨为何“代理式”这一术语有助于避免不必要的争论,并理解不同自主程度的代理如何运作,以及它们在实践中的应用价值。</p>
<hr>
<h2 id="自主程度的概念">自主程度的概念</h2>
<p>几年前,AI社区中关于“何为真正代理”的争论日益激烈。一些人撰文讨论代理,而另一些人则反驳称那并非真正的代理。我认为这场争论并无必要,因此我开始使用“代理式”这个形容词。如果我们将其视为一个程度问题,而非非此即彼的二元判断,我们就能承认系统可以具有不同程度的代理特性。这被称为“代理式”,从而让我们能专注于构建这些系统的实际工作,而非争论某个系统是否足够自主到能被称为代理。</p>
<p>我记得在准备关于代理推理的演讲时,一位团队成员曾对我说:“我们不需要另一个新词,我们已经有‘代理’了,为什么还要用‘代理式’?”但我还是决定使用它。后来,我在《The Batch》通讯和社交媒体上撰文提出,与其争论哪些系统应被纳入“真正代理”的范畴,不如承认系统可以具有不同程度的代理特性。我认为这有助于我们超越关于“何为真正代理”的争论,转而专注于实际构建它们。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/72abe1dd846c525cf4d3ece3b784e3c9_1.png"></p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/72abe1dd846c525cf4d3ece3b784e3c9_2.png"></p>
<hr>
<h2 id="低自主性代理示例">低自主性代理示例</h2>
<p>上一节我们介绍了自主程度的概念,本节中我们来看看一个低自主性代理的具体例子。</p>
<p>以撰写一篇关于黑洞的文章为例。你可以构建一个相对简单的代理,其步骤如下:</p>
<p>以下是该代理的确定性执行步骤:</p>
<ol>
<li>生成几个网络搜索关键词或查询。</li>
<li>通过硬编码方式调用网络搜索引擎。</li>
<li>获取网页内容。</li>
<li>利用获取的内容撰写文章。</li>
</ol>
<p>这是一个低自主性代理的例子,它遵循完全由程序员预先确定的线性步骤序列。用本课程的符号约定表示,其流程如下:</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/72abe1dd846c525cf4d3ece3b784e3c9_4.png"></p>
<pre><code>用户输入: "撰写一篇关于黑洞的文章"
↓
↓
[工具调用: 执行网络搜索]
↓
[工具调用: 获取网页内容]
↓
</code></pre>
<p><strong>符号说明</strong>:</p>
<ul>
<li><strong>红色</strong>:代表用户输入(例如查询)。</li>
<li><strong>灰色框</strong>:代表对大语言模型的调用。</li>
<li><strong>绿色框</strong>:代表调用其他软件执行操作(例如API调用或代码执行)。</li>
</ul>
<p>这种方式可以正常工作。</p>
<hr>
<h2 id="高自主性代理示例">高自主性代理示例</h2>
<p>了解了低自主性代理后,我们来看看更高自主性的代理如何运作。</p>
<p>对于同样的“撰写一篇关于黑洞的文章”请求,一个更高自主性的代理可能让大语言模型自行决定:是进行网站搜索,还是搜索最近的新闻源,抑或是去网站存档中查找近期的研究论文。在这个例子中,不是人类工程师,而是大语言模型选择了调用网络搜索引擎。</p>
<p>之后,你可能继续让大语言模型决定:它想获取多少个网页?如果获取到PDF文件,是否需要调用函数或工具将其转换为文本?在这个案例中,它可能获取排名靠前的几个网页,然后撰写文章草稿,接着进行反思和改进,甚至可能返回去获取更多网页,最终产生输出。</p>
<p>因此,即使对于“研究代理”这个例子,我们也能看到:有些代理自主性较低,执行由程序员确定的线性步骤序列;有些则自主性更高,你信任大语言模型做出更多决策,具体的步骤序列甚至可能由大语言模型而非程序员预先决定。</p>
<hr>
<h2 id="自主程度谱系与应用">自主程度谱系与应用</h2>
<p>基于以上例子,我们可以将代理的自主程度理解为一个谱系。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/72abe1dd846c525cf4d3ece3b784e3c9_6.png"></p>
<p>对于自主性较低的系统,通常所有步骤都是预先确定的,它所调用的任何函数(如网络搜索)——正如你将在本课程第三模块学到的“工具使用”——可能是由人类工程师硬编码的。其大部分自主性仅体现在大语言模型最终生成的文本上。</p>
<p>谱系的另一端是高度自主的代理,这种代理能自主做出许多决策。例如,它可以自行决定撰写文章所需执行的具体步骤序列。一些高度自主的代理甚至能够编写新函数,或者有时被称为“创造新工具”以供执行。</p>
<p>介于两者之间的是半自主代理,它们可以做出一些决策、选择工具,但这些工具通常是预先定义好的。</p>
<p>当你查看课程中的不同示例时,你将学习如何构建这个谱系上从低到高任何自主程度的应用程序。你会发现,在谱系的低自主性一端,有大量为当今众多企业构建的、非常有价值的应用。同时,谱系的高自主性一端也有许多应用正在开发中,但这些应用通常较难控制、有点不可预测,并且如何构建这些高度自主的代理也是当前活跃的研究领域。</p>
<hr>
<h2 id="总结与过渡">总结与过渡</h2>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/72abe1dd846c525cf4d3ece3b784e3c9_8.png"></p>
<p>本节课中,我们一起学习了代理式AI系统的自主程度概念。我们探讨了使用“代理式”一词如何帮助我们聚焦于实际构建,而非语义争论。通过具体示例,我们对比了低自主性与高自主性代理的工作方式,并将代理的自主性理解为一个连续的谱系,其中不同位置都有其有价值的应用场景。</p>
<p>理解了代理的自主程度后,接下来让我们进入下一个视频,更深入地探讨使用代理的好处,以及它们为何能让我们实现早期基于大语言模型的应用所无法完成的任务。</p>
<h1 id="004代理式ai的优势-">004:代理式AI的优势 🚀</h1>
<p>在本节课中,我们将学习代理式AI工作流带来的主要优势。我们将探讨它如何实现以往难以完成的任务,以及它在并行处理、模块化设计等方面的额外好处。</p>
<hr>
<h2 id="概述-1">概述</h2>
<p>代理式AI工作流不仅能够显著提升任务执行的效果,还能通过并行处理加快速度,并通过模块化设计整合最优组件。接下来,我们将详细分析这些优势。</p>
<hr>
<h2 id="核心优势实现不可能的任务">核心优势:实现不可能的任务</h2>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/7e4988c3c45f6ef552a49539c3061e13_1.png"></p>
<p>我认为代理工作流最大的一个好处是,它让你能够有效地完成许多以前根本不可能实现的任务。</p>
<h2 id="并行处理大幅提升速度">并行处理:大幅提升速度</h2>
<p>除了实现新任务,代理工作流还有其他好处,包括<strong>并行处理</strong>,它能让你非常快速地完成某些事情。</p>
<p>例如,如果你要求一个代理工作流撰写一篇关于黑洞的文章,你可以让多个代理并行运行,以生成用于网络搜索的关键词。基于第一次网络搜索的结果,系统可能会识别出三个顶级结果来获取;基于第二次搜索,可能会识别出第二组网页来获取,依此类推。</p>
<p>事实证明,当人类进行此类研究时,必须按顺序或逐个阅读这九个网页。然而,在使用代理式工作流时,你实际上可以<strong>并行下载所有九个网页</strong>,最后将所有内容输入给一个代理来撰写文章。</p>
<p>因此,尽管代理式工作流确实比纯粹的非代理工作流或仅通过单次提示的直接生成耗时更长,但如果你将这种代理工作流与人类执行任务的方式进行比较,其<strong>并行下载多个网页的能力</strong>实际上可以让它在某些任务上快得多,远胜于人类处理数据的非并行、顺序方式。</p>
<h2 id="模块化设计整合最优组件">模块化设计:整合最优组件</h2>
<p>另一个好处是<strong>模块化</strong>,它让你能够结合来自许多不同地方的最佳组件,以构建一个高效的工作流。</p>
<p>基于这个例子,我在构建代理式工作流时经常做的一件事是查看各个组件(如大语言模型),并添加或更换组件。</p>
<p>例如,我可能会查看这里的网络搜索引擎,并决定在构建代理式工作流时换入一个新的搜索引擎。实际上,有多个网络搜索引擎可供选择,包括Google(可通过Serper访问)、Bing、DuckDuckGo、You.com等。实际上,有很多专为AI模型使用而设计的网络搜索引擎选项。</p>
<p>或者,也许不仅仅是进行三次网络搜索,你可以在这一步换入一个新的新闻搜索引擎,以便查找关于黑洞大小的最新突破性新闻。</p>
<p>最后,我通常会尝试使用不同的大语言模型,而不是在所有不同步骤中都使用同一个模型。我可能会尝试不同的AI提供商,看看哪个能为这个系统的不同步骤提供最佳结果。</p>
<hr>
<h2 id="性能对比代理工作流的威力">性能对比:代理工作流的威力</h2>
<p>我的团队收集了一些关于编码基准测试的数据,该测试评估不同AI模型编写代码以执行特定任务的能力。这个基准测试在本例中被称为HumanEval。</p>
<p>结果表明,GPT-3.5(这是GPT最初公开版本所基于的模型)如果被要求直接编写代码,仅通过提示输出计算机程序,在这个基准测试上的正确率为<strong>40%</strong>(这是一个被动的、非代理的指标)。</p>
<p>GPT-4是一个好得多的模型,性能跃升至<strong>67%</strong>,但这同样是在非代理工作流下的表现。</p>
<p>然而,事实证明,尽管从GPT-3.5到GPT-4的改进已经很大,但<strong>这种改进幅度还比不上在上一代模型上实施代理工作流所能实现的提升</strong>。</p>
<p>通过将GPT-3.5包装在代理工作流中,并使用你在课程后面将学到的不同代理技术(例如,你可以提示GPT-3.5编写代码,它可能会反思代码并找出改进方法),你实际上可以让GPT-3.5达到更高的性能水平。</p>
<p>同样地,在代理工作流的背景下使用GPT-4,其表现也会好得多。因此,即使使用当今最好的大语言模型,代理工作流也能让你获得更好的性能。</p>
<p>事实上,我们在这个例子中看到的是,从一代模型到另一代模型的巨大改进,仍然比不上在上一代模型上实施代理工作流所带来的差异。</p>
<hr>
<h2 id="总结">总结</h2>
<p>本节课中,我们一起学习了代理式AI工作流的核心优势。</p>
<p><strong>总结来说,我使用代理工作流的主要原因是,它能在许多不同的应用上提供更好的性能。</strong> 此外,它还可以并行处理一些人类原本必须顺序执行的任务。许多代理式工作流的模块化设计也让我们能够添加、更新工具,有时甚至可以更换模型。</p>
<p>我们已经深入探讨了构建代理式工作流的关键组件。现在,让我们来看看一系列代理式AI的应用,以便让你了解人们已经在构建的东西,以及你自己可以构建的东西。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/7e4988c3c45f6ef552a49539c3061e13_3.png"></p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/7e4988c3c45f6ef552a49539c3061e13_4.png"></p>
<p>让我们进入下一个视频。</p>
<h1 id="005任务分解识别工作流中的步骤">005:任务分解——识别工作流中的步骤</h1>
<p>在本节课中,我们将要学习如何将人类或企业执行的复杂任务,分解为可由AI代理执行的离散步骤。我们将通过具体示例,探讨如何构建和迭代优化代理工作流。</p>
<h2 id="概述-2">概述</h2>
<p>人们和企业会执行许多任务。如何将这些有用的任务分解为可供AI代理工作流遵循的离散步骤?让我们一起来探讨。</p>
<h2 id="任务分解的核心思路">任务分解的核心思路</h2>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/1304eb033bd0a15f2922c9a0a7e73f38_1.png"></p>
<p>上一节我们介绍了代理工作流的基本概念,本节中我们来看看如何将一个宏观任务拆解为可执行的步骤。核心方法是:观察人类如何执行任务,并将其分解为可由大型语言模型(LLM)或特定工具(如API调用、代码执行)完成的子步骤。</p>
<h2 id="示例一构建研究型代理撰写论文">示例一:构建研究型代理(撰写论文)</h2>
<p>假设你需要一个AI系统来撰写关于主题X的论文。一种直接的方法是提示LLM直接生成最终输出。</p>
<p>然而,对于需要深度研究的主题,你可能会发现直接生成的输出仅停留在表面,或只涵盖显而易见的事实,未能达到你期望的深度。</p>
<p>在这种情况下,你可以反思人类撰写论文的过程:你会直接坐下来开始写吗?还是采取多个步骤,例如:</p>
<ol>
<li>首先撰写论文大纲。</li>
<li>然后进行网络搜索。</li>
<li>最后基于网络搜索结果撰写论文。</li>
</ol>
<p>这就是将任务分解为步骤。我经常问自己的一个问题是:<strong>步骤1、2、3中的每一个,是否都能由LLM、一小段代码或通过工具进行的函数调用来完成?</strong></p>
<p>在这个案例中:</p>
<ul>
<li><strong>步骤1(撰写大纲)</strong>:我认为LLM可以为许多主题写出不错的大纲,所以这一步可行。</li>
<li><strong>步骤2(生成搜索词并搜索)</strong>:我知道如何使用LLM生成搜索词并进行网络搜索,所以这一步也可行。</li>
<li><strong>步骤3(基于搜索结果撰写论文)</strong>:我认为LLM可以输入网络搜索结果并撰写论文,所以这一步也可行。</li>
</ul>
<p>这将是构建一个比直接生成更深入的论文写作代理工作流的合理初步尝试。</p>
<p>但是,如果我实现这个工作流并查看结果,可能会发现结果仍然不够好,思考深度不足,或者论文读起来有些脱节。这确实在我身上发生过:我曾用这个工作流构建了一个研究代理,但每当我阅读输出时,都感觉文章的开头、中间和结尾不完全一致。</p>
<p>此时,你可以反思:如果作为人类,你发现论文脱节,会如何修改工作流?</p>
<p>一种做法是将第三步“撰写论文”进一步分解为更多子步骤。与其一次性写完,不如:</p>
<ol>
<li>撰写初稿。</li>
<li>评估哪些部分需要修改。</li>
<li>修订草稿。</li>
</ol>
<p>这就是我作为人类可能会采取的方式:不是第一次尝试就写出终稿,而是先写初稿,然后通读(这是另一步),再基于对自己文章的批评来修订草稿。</p>
<p><strong>回顾一下</strong>:我从直接生成(一步)开始,认为效果不佳,于是分解为三步。之后可能仍不满意,于是将其中一步进一步分解为三个更小的步骤,从而形成了一个更复杂、更丰富的论文生成流程。根据你对这个流程结果的满意程度,你甚至可以选择进一步修改这个论文生成过程。</p>
<h2 id="示例二处理客户订单咨询">示例二:处理客户订单咨询</h2>
<p>让我们看看第二个如何将复杂任务分解为最小步骤的例子。以回复基本的客户订单咨询为例。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/1304eb033bd0a15f2922c9a0a7e73f38_3.png"></p>
<p>人类客服可能执行的<strong>第一步</strong>是提取关键信息,例如:这封邮件来自谁?他们订购了什么?订单号是多少?这些是LLM可以完成的。</p>
<p><strong>第二步</strong>是查找相关的客户记录,即编写并执行相应的数据库查询,以调取客户订购了什么、何时发货等信息。我认为一个能够调用函数来查询订单数据库的LLM应该可以做到这一点。</p>
<p><strong>第三步</strong>,在调取客户订单记录后,撰写并发送回复给客户。我认为,在提供了调用API发送邮件的选项后,LLM利用我们获取的信息也能完成这一步。</p>
<p>这是将“回复客户邮件”任务分解为三个独立步骤的另一个例子。我可以审视每个步骤并说:我认为一个能够调用函数来查询数据库或发送邮件的LLM应该能够完成。</p>
<h2 id="示例三处理发票">示例三:处理发票</h2>
<p>最后一个例子是发票处理。在PDF发票被转换为文本后,<strong>第一步</strong>是提取所需信息:账单名称、地址、到期日、应付金额等。LLM应该能够做到这一点。</p>
<p><strong>第二步</strong>,如果我想检查信息是否已提取并保存到新的数据库条目中,那么我认为LLM可以帮助我调用函数来更新数据库记录。</p>
<p>因此,要实现一个代理工作流来执行这两个基本步骤。</p>
<h2 id="构建代理工作流的积木">构建代理工作流的“积木”</h2>
<p>在构建代理工作流时,我将自己视为拥有一些“积木块”。</p>
<ul>
<li><strong>一个重要积木是大型语言模型(LLM)</strong>,或者如果需要处理图像或音频,也可以是大型多模态模型。LLM擅长生成文本、决定调用什么、从某些文本中提取信息。</li>
<li><strong>对于某些专门任务,我可能还会使用其他AI模型</strong>,例如用于将PDF转换为文本、文本转语音或图像分析的AI模型。</li>
<li><strong>除了AI模型,我还可以访问许多软件工具</strong>,包括可以调用的不同API,用于网络搜索、获取实时天气数据、发送电子邮件、检查日历等。</li>
<li><strong>我可能还有用于检索信息的工具</strong>,例如从数据库调取数据,或进行检索增强生成(RAG),即可以查询大型文本数据库并找到最相关的文本。</li>
<li><strong>我可能还有执行代码的工具</strong>。这是一个让LLM编写代码然后在你的计算机上运行以完成大量工作的工具。</li>
</ul>
<p>如果其中一些工具对你来说有些陌生,请不要担心,我们将在后续模块中更详细地介绍最重要的工具。</p>
<p>我认为,构建代理工作流时,我的很多工作是观察个人或企业正在做的工作,然后尝试弄清楚:<strong>如何将这些“积木块”按顺序组合在一起,以执行我希望系统完成的任务?</strong></p>
<p>这就是为什么充分了解有哪些可用的“积木块”非常重要(我希望在本课程结束时你也能有更好的认识),这将使你能够更好地设想可以通过组合这些“积木块”来构建哪些代理工作流。</p>
<h2 id="总结与迭代改进">总结与迭代改进</h2>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/1304eb033bd0a15f2922c9a0a7e73f38_5.png"></p>
<p><strong>本节课中我们一起学习了</strong>,构建智能代理工作流的一项关键技能是:观察某人可能做的一系列事情,并识别出可以用于实现的离散步骤。</p>
<p>当我审视各个离散步骤时,我经常问自己的一个问题是:<strong>这个步骤是否可以用LLM或我拥有的某个工具(如API或函数调用)来实现?</strong></p>
<p>如果答案是否定的,我通常会问自己:作为人类,我会如何做这一步?是否有可能将其进一步分解或拆分成更小的步骤,从而更易于用LLM或我拥有的某个软件工具来实现?</p>
<p>我希望这能让你对如何思考任务分解有一个大致的了解。如果你觉得还没有完全掌握,请不要担心,本课程中将会有更多示例,到课程结束时你会有更好的理解。</p>
<p>事实证明,在构建代理工作流时,你经常会先构建一个初始的任务分解和初始代理工作流,然后希望多次迭代和改进它,直到它达到你想要的性能水平。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/1304eb033bd0a15f2922c9a0a7e73f38_7.png"></p>
<p>为了推动这个对许多项目都很重要的改进过程,一项关键技能是知道如何评估你的代理工作流。</p>
<h2 id="过渡到下一主题">过渡到下一主题</h2>
<p>在下一节视频中,我们将讨论评估(evals),这是一个关键组成部分,关乎你如何构建并持续改进工作流以获得想要的性能。让我们在下一个视频中谈谈评估。</p>
<h1 id="006评估代理式ai工作流-">006:评估代理式AI工作流 🧪</h1>
<p>在本节课中,我们将要学习如何为代理式AI工作流构建评估体系。评估是衡量和提升AI代理性能的关键,一个严谨的评估过程能显著影响你构建高效工作流的能力。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/fa620e0664184a84e889840639d6c185_1.png"></p>
<p>我曾与许多团队合作构建代理式工作流,发现决定其效率高低的一个关键因素,在于能否执行一个严谨的评估流程。因此,掌握为代理工作流进行评估的能力,对于有效构建它们至关重要。本节将快速概述如何构建评估,这个主题将在课程后续模块中深入探讨。</p>
<h2 id="从观察输出开始-">从观察输出开始 🔍</h2>
<p>在构建了一个代理工作流(例如用于处理客户订单咨询)之后,我们很难提前预知所有可能出错的地方。</p>
<p>因此,与其试图提前构建评估,我建议你直接观察输出结果,并手动找出你希望它改进的地方。例如,你可能在阅读大量输出后发现,它意外地过多提及了你的竞争对手。企业通常不希望其代理提及对手,因为这可能造成尴尬局面。你可能会看到这样的回复:“很高兴您联系我们,我们比竞争对手CompCo好得多”,或者“我们会退款,不像对手RivalCo,我们退货很容易”。这时你可能会想,我真的不希望它提及竞争对手。</p>
<p>这是一个在构建代理前很难预见的问题范例。因此,最佳实践是先构建代理,然后检查其输出,找出尚不满意之处,再设法通过评估来改进系统,消除这些不足。</p>
<h2 id="评估客观标准-">评估客观标准 📊</h2>
<p>假设你的业务认为以这种方式提及竞争对手是一个错误,那么在你努力消除这些提及时,一种追踪进展的方法是添加一个评估,来追踪此类错误发生的频率。</p>
<p>如果你有一个竞争对手名单,例如 <code>[“CompCo”, “RivalCo”, “OtherCo”]</code>,你可以编写代码来搜索输出文本,统计它提及这些竞争对手名称的频率,并计算其占所有回复的比例。</p>
<p>关于“提及竞争对手”这个问题的一个优点是,它是一个<strong>客观指标</strong>,即要么提及了,要么没有。对于这类客观标准,你可以编写代码来检查特定错误的发生频率。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/fa620e0664184a84e889840639d6c185_3.png"></p>
<h2 id="评估主观标准-">评估主观标准 🤖</h2>
<p>然而,由于大语言模型的输出是自由文本,也会存在一些你希望评估的、但更为主观的标准,很难直接用代码输出一个非黑即白的分数。</p>
<p>在这种情况下,<strong>使用另一个大语言模型作为评判者</strong>是评估输出的常用技术。例如,如果你正在构建一个研究代理来研究不同主题,你可以使用另一个模型,并提示它:“请为以下文章在1到5分之间分配一个质量分数,1分最差,5分最好”,这里我使用一个Python表达式来表示你将生成的文章粘贴进去。</p>
<p>你可以提示大语言模型阅读文章并分配质量分数。然后,你让研究代理撰写多份不同的研究报告,例如关于黑洞科学的最新进展或使用机器人采摘水果。在这个例子中,评判模型可能给关于黑洞的文章打了3分,给关于机器人采摘的文章打了4分。随着你不断改进研究代理,你希望看到这些分数随时间推移而上升。</p>
<p>顺便提一下,大语言模型其实不太擅长进行1到5分的评分。你可以给它一个提示,但我个人不常使用这种技术。在后续模块中,你将学习一些更好的技术,让大语言模型输出比1到5分制更准确的分数,尽管有些人可能会在初步尝试时使用这种“模型作为评判者”的评估方法。</p>
<h2 id="评估类型预览-">评估类型预览 🧩</h2>
<p>为了让你提前了解一些将在课程后期学习的代理式AI评估类型,你已经听我介绍了如何编写代码评估客观标准(例如是否提及了竞争对手),以及如何使用大语言模型作为评判者来评估更主观的标准(例如文章质量)。</p>
<p>后续你将学习两种主要的评估类型:</p>
<ul>
<li><strong>端到端评估</strong>:衡量整个代理的最终输出质量。</li>
<li><strong>组件级评估</strong>:衡量代理工作流中单个步骤的输出质量。</li>
</ul>
<p>事实证明,这两种评估对于推动不同的积极开发过程都很有用。</p>
<p>此外,我经常做的一件事是检查中间输出,有时你称之为模型的“痕迹”,以理解它在哪些地方未达到我的期望。我们称之为<strong>错误分析</strong>,即通读每个步骤的中间输出,试图发现改进的机会。事实证明,能够进行评估和错误分析是一项非常关键的技能。</p>
<p>关于这一点,在课程的第四个模块中还有更多内容要讲。</p>
<h2 id="总结-">总结 📝</h2>
<p>在本节课中,我们一起学习了为代理式AI工作流构建评估体系的基础知识。我们了解到,评估应从观察实际输出、识别问题开始。对于客观错误(如提及竞争对手),可以通过编写代码进行量化追踪;对于主观质量(如文章水平),则可以引入另一个大语言模型作为评判者。我们还预览了端到端评估和组件级评估这两种主要类型,并认识了通过分析中间输出进行错误分析的重要性。掌握这些评估方法是高效开发和持续改进AI代理的关键。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/fa620e0664184a84e889840639d6c185_5.png"></p>
<p>我们即将结束这第一个模块。在继续之前,我想在下一个视频中与你分享我认为构建代理工作流最重要的设计模式。</p>
<p>代理式AI:模块1-5:代理工作流设计模式 🧩</p>
<p>在本节课中,我们将学习如何将基础构建模块组合起来,构建复杂的代理工作流。我们将介绍四种关键的设计模式,它们能帮助你思考如何将这些模块整合成更强大的工作流。</p>
<hr>
<h3 id="概述-3">概述</h3>
<p>我们通过组合基础构建模块,来编排复杂的代理工作流。本节将分享几种关键的设计模式,它们为如何组合这些模块提供了清晰的思路。</p>
<hr>
<h3 id="四种关键设计模式">四种关键设计模式</h3>
<p>构建代理工作流的四种关键设计模式是:<strong>反思</strong>、<strong>工具使用</strong>、<strong>规划</strong>和<strong>多代理协作</strong>。下面我们将简要介绍它们的含义,后续课程会深入探讨其中大部分模式,并辅以代码示例。</p>
<hr>
<h4 id="反思模式">反思模式</h4>
<p>第一种主要设计模式是<strong>反思</strong>。例如,我可以要求一个语言模型代理编写代码,它可能会生成如下代码:</p>
<pre><code class="language-python">def some_task():
# 执行某项任务的Python函数
...
</code></pre>
<p>然后,我可以构建一个提示词,内容如下:</p>
<blockquote>
<p>“这段代码旨在完成某项任务。[此处粘贴模型刚输出的代码]。请仔细检查代码的正确性、风格和效率,并提出建设性批评。”</p>
</blockquote>
<p>事实证明,同一个语言模型在被这样提示后,可能能够指出代码中的一些问题。如果我将这些批评反馈给模型,并说:“这里有一个错误,你能修改代码来修复它吗?”,那么它可能会生成一个更好的代码版本。</p>
<p>为了预览工具的使用,如果你能运行代码并查看其失败之处,然后将这些信息反馈给语言模型,也能促使它迭代并生成更好的版本(例如V3版本)。</p>
<p>因此,反思是一种常见的设计模式,你可以要求语言模型检查自己的输出,或者引入一些外部信息源(例如运行代码并查看是否产生错误信息),并以此作为反馈进行迭代,从而产生更好的输出版本。这个设计模式很巧妙,虽然不能保证每次都100%成功,但有时能显著提升系统的性能。</p>
<p>在上面的描述中,我假设是向同一个模型进行提示。为了预示多代理工作流,你也可以想象不是让同一个模型自我批评,而是有一个<strong>批评者代理</strong>。这本质上是一个被赋予了特定指令(例如“你的角色是代码审查员。这是一段旨在完成某项任务的代码,请仔细检查...”)的语言模型。第二个批评者代理可能会指出错误或对单元测试进行排序。这就像拥有两个独立的代理,每个代理只是一个被赋予特定角色的语言模型,让它们来回交互迭代以获得更好的输出。</p>
<hr>
<h4 id="工具使用模式">工具使用模式</h4>
<p>除了反思模式,第二个重要的设计模式是<strong>工具使用</strong>。如今,语言模型可以被赋予工具(即可调用的函数)来完成任务。</p>
<p>例如,如果你问一个语言模型:“根据评论,最好的咖啡机是什么?”,并赋予它网络搜索工具,那么它实际上可以搜索互联网以找到更好的答案。或者,如果你问一个数学问题,比如“如果投资100美元,复利计算...”,并赋予它代码执行工具,那么它可以编写并执行代码来计算答案。</p>
<p>如今,不同的开发者已经为语言模型提供了许多不同的工具,涵盖数学、数据分析、通过网络或各种数据库获取信息、与电子邮件和日历等生产力应用交互,以及处理图像等等。语言模型决定使用何种工具(即调用哪些函数)的能力,使得模型能够完成更多工作。</p>
<hr>
<h4 id="规划模式">规划模式</h4>
<p>四种设计模式中的第三种是<strong>规划</strong>。这是一个来自名为“HuggingGPT”论文的例子。如果你要求一个系统:“请生成一张女孩读书的图片,姿势要与这张男孩的图片相同。然后用新的声音描述这张图片。”那么,模型可以自动决定,为了执行此任务,它首先需要找到一个姿势确定模型来识别男孩的姿势,然后根据姿势生成女孩的图片,接着为图片生成文本描述,最后将文本转换为语音。</p>
<p>在规划中,语言模型决定它需要采取的一系列行动步骤(在本例中是一系列API调用),以便以正确的顺序执行正确的步骤来完成任。因此,这不同于开发者预先硬编码步骤序列,而是让语言模型自行决定要采取的步骤。目前,能够规划的代理更难控制,且更具实验性,但有时能产生非常令人满意的结果。</p>
<hr>
<h4 id="多代理协作模式">多代理协作模式</h4>
<p>最后是<strong>多代理工作流</strong>。正如人类经理可能会雇佣多人共同完成一个复杂项目一样,在某些情况下,雇佣一组多个代理(每个代理专精于不同的角色)并让它们协作完成复杂任务可能是有意义的。</p>
<p>你在这里看到的左侧图片取自一个名为“ChatDev”的项目。在ChatDev中,多个具有不同角色(如首席执行官、程序员、测试员、设计师等)的代理,像一个虚拟软件公司一样协作,可以共同完成一系列软件开发任务。</p>
<p>让我们考虑另一个例子。如果你想撰写一份营销手册,你可能会考虑雇佣一个三人团队:一名研究员进行在线研究,一名营销人员撰写营销文案,最后一名编辑进行润色和修改。</p>
<p>类似地,你可以考虑构建一个多代理工作流,其中包含一个模拟的研究员代理、一个模拟的营销人员代理和一个模拟的编辑代理,它们共同为你完成这项任务。多代理工作流更难控制,因为你无法总是提前预知代理会做什么,但研究表明,对于许多复杂任务(如撰写传记或决定国际象棋走法),它们能带来更好的结果。在本课程后续部分,你也会学到更多关于多代理工作流的内容。</p>
<hr>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/1af2eb2a5252d83c5e1fac0f39eae9c3_1.png"></p>
<h3 id="总结-1">总结</h3>
<p>本节课中,我们一起学习了代理工作流能做什么,以及寻找构建模块并将其组合起来(可能通过这些设计模式)以实现代理工作流的关键挑战。当然,还包括开发评估方法,以便了解系统表现如何并持续改进。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/1af2eb2a5252d83c5e1fac0f39eae9c3_3.png"></p>
<p>在下一个模块中,我将深入介绍这些设计模式中的第一个——<strong>反思模式</strong>。你会发现,这是一种实现起来可能出奇简单的技术,有时能显著提升系统的性能。让我们进入下一个模块,学习反思设计模式。</p>
<h1 id="008反思设计模式">008:反思设计模式</h1>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/892aedfaed6da84e505eff13b7863b86_1.png"></p>
<p>在本节课中,我们将要学习一种名为“反思设计模式”的技术。这种模式借鉴了人类自我检查、改进输出的行为,并将其应用于大型语言模型,以帮助模型生成更高质量的结果。我们将通过编写邮件和代码的具体例子,来理解其工作原理和实现方法。</p>
<h2 id="反思模式的基本原理">反思模式的基本原理</h2>
<p>正如人类有时会反思自己的产出并找到改进方法一样,AI代理也可以做到这一点。</p>
<p>例如,我可能会快速起草一封邮件,初稿可能并不完美。当我重读时,可能会发现一些问题:比如“下个月”这个时间表述不清,Tommy哪天有空吃饭不明确;邮件中可能存在拼写错误;我可能还忘了署名。这些反思能让我修改草稿,使其更具体、更准确,例如改为:“Tommy,你5号到7号有空一起吃晚饭吗?”</p>
<h2 id="实现反思模式的工作流程">实现反思模式的工作流程</h2>
<p>以下是实现反思模式的一个典型工作流程。</p>
<ol>
<li><strong>生成初稿</strong>:首先,提示一个大型语言模型生成任务的初稿。例如,生成邮件的第一版 <code>email_v1</code>。</li>
<li><strong>进行反思</strong>:然后,将初稿(可以传递给同一个模型,也可以是另一个模型)连同新的提示一起输入,要求模型对初稿进行反思和改进。</li>
<li><strong>输出改进版</strong>:模型基于反思,生成一个改进后的第二版输出,例如 <code>email_v2</code>。</li>
</ol>
<p>在这个例子中,我硬编码了工作流:先提示模型生成,再提示同一个模型进行反思和改进,最终得到 <code>email_v2</code>。</p>
<h2 id="反思模式的应用扩展">反思模式的应用扩展</h2>
<p>事实证明,类似的过程可以用来改进其他类型的输出。</p>
<p>例如,如果你让语言模型编写代码,你可以提示它编写完成某项任务的代码,它会给出代码的初版 <code>v1</code>。然后,你可以将这段代码传递给同一个模型或另一个不同的模型,要求它检查错误并写出改进后的第二版代码。</p>
<p>不同的模型有不同的优势,因此有时我会选择不同的模型来分别负责“生成初稿”和“反思改进”。例如,推理模型(有时也称为思维模型)通常更擅长发现错误。因此,我有时会用直接生成模型来编写代码初稿,然后用一个推理模型来检查错误。</p>
<h2 id="结合外部反馈的增强反思">结合外部反馈的增强反思</h2>
<p>然而,不仅仅是让语言模型自行反思代码,如果能引入外部反馈——即来自语言模型之外的新信息——反思过程会变得强大得多。</p>
<p>对于代码而言,一个有效的方法是直接执行它,观察代码的运行结果。通过检查输出(包括任何错误信息),你能为语言模型的反思提供极其有用的信息。</p>
<p>在这个例子中,模型生成了代码初稿,但当我运行它时,产生了语法错误。当你将这段代码、其输出和错误日志反馈给语言模型,并要求它基于这些反馈进行反思并写出新草案时,模型就获得了大量非常有用的信息,从而能够生成质量高得多的代码第二版 <code>version2</code>。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/892aedfaed6da84e505eff13b7863b86_3.png"></p>
<h2 id="设计考量与总结">设计考量与总结</h2>
<p>反思设计模式非常有效。它并不能保证语言模型每次都能100%正确,但通常能显著提升其表现。</p>
<p>但需要记住的一个设计考虑是:<strong>当反思过程能够获取新的、额外的外部信息时,它会变得强大得多</strong>。</p>
<p>在本例中,如果你能运行代码,并将代码输出或错误信息作为反思步骤的额外输入,这就能让模型进行更深入的反思,找出问题所在(如果有的话),从而产生比没有这些外部信息时好得多的代码第二版。</p>
<p>因此,请记住:<strong>每当反思有机会获得额外信息时,其效果都会大大增强</strong>。</p>
<p>本节课中,我们一起学习了反思设计模式。我们了解了其模仿人类反思行为的基本原理,探讨了从生成初稿到反思改进的标准工作流程,并看到了它在邮件撰写和代码编写中的具体应用。最重要的是,我们认识到结合外部反馈(如代码执行结果)能极大增强反思的效果,帮助AI代理产出更可靠、更准确的成果。</p>
<h1 id="009为什么不是直接生成">009:为什么不是直接生成?</h1>
<p>在本节课中,我们将要学习为什么在构建AI代理时,我们更倾向于使用“反思”工作流,而不是简单地让模型一次性直接生成答案。</p>
<h2 id="概述直接生成与反思">概述:直接生成与反思</h2>
<p>上一节我们介绍了AI代理的基本概念,本节中我们来看看两种不同的生成方式:直接生成与反思。直接生成是一种简单的方法,而反思则通过多步骤的自我检查来提升输出质量。</p>
<p>直接生成是指你向大语言模型(LLM)提供一个指令,让它一次性生成最终答案。</p>
<p>例如:</p>
<ul>
<li>你要求LLM写一篇关于黑洞的文章,它直接生成文本。</li>
<li>你要求LLM编写一个计算复利的Python函数,它直接生成代码。</li>
</ul>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/c24452bbb1da2f2dcb5f19a538e96554_1.png"></p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/c24452bbb1da2f2dcb5f19a538e96554_2.png"></p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/c24452bbb1da2f2dcb5f19a538e96554_3.png"></p>
<p>你在这里看到的提示词示例也被称为<strong>零样本提示</strong>。</p>
<p>让我解释一下零样本的含义。与零样本提示相对的一种相关方法是在你的提示词中包含一个或多个你期望的输出示例,这被称为<strong>单样本提示</strong>(如果你在提示词中包含一个期望的输入-输出对示例)或<strong>少样本提示</strong>(取决于你在提示词中包含多少个这样的示例)。</p>
<p>因此,<strong>零样本提示</strong>指的是如果你包含零个示例,即不包含任何期望输出的示例。</p>
<p>但如果你还不熟悉这些术语,请不要担心。重要的是,在你这里看到的例子中,你只是提示LLM一次性直接生成答案,我也称之为零样本提示,因为我们包含了零个示例。</p>
<h2 id="反思的优势">反思的优势</h2>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/c24452bbb1da2f2dcb5f19a538e96554_5.png"></p>
<p>事实证明,多项研究表明,反思在各种任务上都能提升直接生成的性能。</p>
<p>下图改编自Madan等人的研究论文,它展示了在不同模型上、使用或不使用反思来实现的一系列不同任务。</p>
<p>阅读此图的方法是查看这些相邻的浅色和深色条形图对,其中浅色条形图表示零样本提示,深色条形图表示同一模型但使用了反思,而蓝色、绿色和红色表示使用不同模型(如GPT-3.5和GPT-4)进行的实验。</p>
<p>你可以看到,对于许多应用,代表使用反思的深色条形图明显高于浅色条形图。当然,具体效果可能因你的特定应用而异。</p>
<p>以下是反思可能有所帮助的更多例子:</p>
<p>以下是反思可能派上用场的一些场景:</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/c24452bbb1da2f2dcb5f19a538e96554_7.png"></p>
<ul>
<li><strong>生成结构化数据</strong>:例如生成HTML表格时,输出格式有时可能不正确。因此,一个用于验证HTML代码的反思提示可能会有所帮助。如果是基本的HTML,这可能帮助不大,因为模型本身就很擅长生成基本HTML。但特别是当你需要更复杂的结构化输出时,比如可能具有大量嵌套的JSON数据结构,反思更有可能发现错误。</li>
<li><strong>生成步骤序列</strong>:如果你要求LLM生成一系列步骤来完成某项指令,例如如何冲泡一杯完美的茶,LLM可能会遗漏步骤。一个要求检查指令连贯性和完整性的反思提示可能有助于发现错误。</li>
<li><strong>生成域名</strong>:这是我实际参与过的工作,使用LLM生成域名。有时它生成的名称可能带有 unintended 的含义,或者可能非常难发音。因此,我使用反思提示来双重检查域名是否有任何有问题的含义,或者名称是否难发音。我们团队的一个AI产品实际上就曾帮助为我们合作的初创公司构思域名。</li>
</ul>
<h2 id="如何编写反思提示">如何编写反思提示</h2>
<p>我想向你展示几个用于构思域名的反思提示示例。</p>
<p>你可能会要求它:</p>
<ul>
<li>审查你建议的域名。</li>
<li>检查每个名称是否易于发音。</li>
<li>检查每个名称在英语或其他语言中是否可能意味着负面含义。</li>
<li>然后输出满足这些标准的候选名称简短列表。</li>
</ul>
<p>或者,为了改进一封电子邮件,你可以编写一个反思提示,告诉它:</p>
<ul>
<li>审查邮件的初稿。</li>
<li>检查语气。</li>
<li>核实事实、日期和承诺是否准确(这在LLM已被输入大量事实和数据以撰写邮件草稿的上下文中是合理的,这些信息将作为LLM上下文的一部分提供)。</li>
<li>然后,根据它发现的任何问题,撰写邮件的下一稿。</li>
</ul>
<p>以下是一些编写反思提示的技巧:</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/c24452bbb1da2f2dcb5f19a538e96554_9.png"></p>
<ul>
<li>明确表示你希望它审查或反思输出的初稿。</li>
<li>如果可能,明确指定标准,例如域名是否易于发音、是否可能有负面含义,或者对于邮件,检查语气和核实事实。这可以更好地指导LLM按照你最关心的标准进行反思和评判。</li>
</ul>
<p>我发现学习编写更好提示的方法之一是阅读大量其他人编写的提示。有时我甚至会下载开源软件,去找那些我认为做得特别好的软件中的提示词,只是为了阅读作者编写的提示。</p>
<h2 id="总结与预告">总结与预告</h2>
<p>本节课中我们一起学习了直接生成与反思工作流的区别。我们了解到,虽然直接生成(零样本提示)简单快捷,但引入反思步骤可以通过自我审查和批判性思考,在生成结构化数据、复杂指令或需要创意筛选(如域名)等任务上,显著提高输出的准确性和质量。编写有效的反思提示需要清晰指明反思对象和具体的评估标准。</p>
<p>希望你现在对如何编写基本的反思提示有了概念,甚至可以在自己的工作中尝试,看看它是否能帮助你获得更好的性能。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/c24452bbb1da2f2dcb5f19a538e96554_11.png"></p>
<p>在下一个视频中,我将分享一个有趣的例子,我们将开始研究多模态输入在AI代理中的应用,看看算法如何对生成的图像或图表进行反思。</p>
<p>😊,让我们一起来看看吧。</p>
<h1 id="010图表生成工作流-">010:图表生成工作流 📊</h1>
<p>在本节课中,我们将学习一个图表生成工作流。我们将看到如何使用智能体(Agent)来生成美观的图表,并了解“反思”(Reflection)技术如何显著提升输出结果的质量。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/dd57e293085effa164b572911df870a1_1.png"></p>
<h2 id="概述-4">概述</h2>
<p>在本模块的实践项目中,你将体验一个图表生成工作流。该工作流利用智能体来生成美观的图表。事实证明,引入反思环节可以显著改善其输出质量。让我们开始探索。</p>
<h2 id="工作流示例">工作流示例</h2>
<p>假设我们有一份咖啡机的销售数据,记录了拿铁、热巧克力、卡布奇诺等不同饮品的销售时间和价格。</p>
<p>我们的目标是让一个智能体创建一个图表,用于比较2024年和2025年第一季度的咖啡销售额。</p>
<p>一种直接的方法是编写一个提示词(Prompt),要求大语言模型(LLM)利用存储在CSV文件(即逗号分隔值表格文件)中的数据,生成一个比较2024年和2025年第一季度咖啡销售额的图表。</p>
<p>大语言模型可能会编写类似下面的代码来生成图表:</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/dd57e293085effa164b572911df870a1_3.png"></p>
<pre><code class="language-python"># 示例代码:生成堆叠柱状图
import pandas as pd
import matplotlib.pyplot as plt
# 读取数据
data = pd.read_csv('coffee_sales.csv')
# ... 数据处理与图表生成代码 ...
</code></pre>
<p>如果执行这段V1版本的代码,可能会生成一个类似下图的图表:</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/dd57e293085effa164b572911df870a1_1.png"></p>
<p>当我第一次运行模型输出的代码时,它生成了这个图表。这是一个堆叠柱状图,但这种方式并不易于直观比较数据,图表本身看起来也不够理想。</p>
<h2 id="引入反思环节">引入反思环节</h2>
<p>接下来,我们可以将V1版本的代码以及这段代码生成的图表,输入给一个多模态模型(即一个也能接受图像输入的大语言模型)。</p>
<p>然后,我们要求该模型检查这张由代码生成的图像,对其进行批判性分析,找出生成更佳可视化效果的方法,并更新代码以生成更清晰、更好的图表。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/dd57e293085effa164b572911df870a1_5.png"></p>
<p>多模态大语言模型具备视觉推理能力,因此可以直观地审视这张图,找出改进的方法。</p>
<p>当我这样做时,模型实际上生成了一个条形图。这个条形图将2024年和2025年的咖啡销售额分开显示,相比之前的堆叠柱状图,我认为这种方式更令人愉悦且更清晰。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/dd57e293085effa164b572911df870a1_3.png"></p>
<h2 id="模型选择策略">模型选择策略</h2>
<p>在编码实践中,你可以自由尝试不同的问题,看看是否能得到视觉效果更好的图表。因为不同的大语言模型各有优缺点。</p>
<p>有时,我会为初始生成和反思环节使用不同的大语言模型。</p>
<p>例如,你可以用一个模型(如GPT-4或GPT-5等)来生成初始代码。只需给出类似“编写Python代码以生成可视化图表”这样的提示词。</p>
<p>然后,反思提示词可能是这样的:要求模型扮演专家数据分析师的角色,提供建设性反馈。接着,给它V1版本的代码、生成的图表,或许还包括生成代码时的对话历史。要求它根据<strong>可读性、清晰度和完整性</strong>等特定标准进行批判。提供具体标准有助于模型更好地理解需要做什么。最后,要求它编写新的代码来实现改进。</p>
<p>你可能会发现,有时使用具备推理能力的模型进行反思,效果可能优于非推理模型。因此,当你为初始生成和反思环节尝试不同模型时,可以尝试切换或组合不同的配置。希望你在编码实践中获得乐趣。</p>
<h2 id="反思的实际效果">反思的实际效果</h2>
<p>现在,当你构建应用程序时,可能会思考一个问题:反思是否真的能提升你在特定应用上的性能?</p>
<p>根据多项研究,反思在某些应用上能略微提升性能,在某些应用上能大幅提升,而在另一些应用上可能几乎没有效果。因此,了解反思对你具体应用的影响非常有用,它也能指导你如何调整初始生成或反思的提示词,以尝试获得更好的性能。</p>
<h2 id="总结-2">总结</h2>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/dd57e293085effa164b572911df870a1_7.png"></p>
<p>本节课中,我们一起学习了图表生成工作流。我们看到了如何利用智能体生成图表,并重点介绍了通过引入<strong>反思</strong>环节,让多模态模型分析初始输出并提出改进方案,从而显著提升图表质量的方法。我们还讨论了为初始生成和反思步骤选择不同模型的策略。理解反思在你特定任务上的效果,是优化智能体工作流的关键一步。</p>
<h1 id="011评估反思机制的影响-">011:评估反思机制的影响 📊</h1>
<p>在本节课中,我们将学习如何评估反思机制对AI代理工作流程性能的实际影响。我们将探讨两种主要的评估方法:基于客观标准的评估和基于主观标准的评估,并了解如何通过系统化的评估来优化提示词和整体工作流程。</p>
<hr>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/86e1899dc5a332bf491db8d7b63639a5_1.png"></p>
<h2 id="概述-5">概述</h2>
<p>反思机制通常能提升系统的性能,但在决定保留它之前,我们通常需要双重检查它实际带来了多少提升,因为它需要额外的步骤,可能会稍微降低系统速度。让我们来看看如何为反思工作流程构建评估体系。</p>
<h2 id="客观评估数据库查询示例">客观评估:数据库查询示例</h2>
<p>上一节我们介绍了反思的基本概念,本节中我们来看看一个具体的评估案例。假设你经营一家零售店,可能会收到诸如“哪种颜色的产品总销售额最高?”之类的问题。为了回答这个问题,你可能会让一个大语言模型生成一个数据库查询语句(例如SQL查询)。</p>
<p>但生成查询后,我们不是直接用它从数据库获取信息,而是让同一个或另一个大语言模型对第一版的查询进行反思和改进,生成一个可能更优的版本。</p>
<p><strong>工作流程公式</strong>:</p>
<pre><code>1. 用户提问 -> 2. LM生成初始查询 -> 3. LM反思并改进查询 -> 4. 执行改进后的查询 -> 5. LM根据查询结果生成最终答案
</code></pre>
<p>为了评估“使用第二个LM来反思和改进SQL查询”是否真的能改善最终输出,我们可以采取以下步骤:</p>
<p>以下是构建客观评估的步骤:</p>
<ol>
<li><strong>收集测试集</strong>:收集一组问题(提示词)及其对应的标准答案。例如:“2025年5月售出了多少件商品?”、“库存中最贵的商品是什么?”、“我的商店有多少种款式?”。</li>
<li><strong>运行无反思流程</strong>:仅使用第一个LM生成的SQL查询来获取答案。</li>
<li><strong>运行有反思流程</strong>:使用经过第二个LM反思改进后的SQL查询来获取答案。</li>
<li><strong>计算正确率</strong>:分别计算两种流程下答案的正确百分比。</li>
</ol>
<p>在这个例子中,假设无反思的正确率为87%,而有反思的正确率提升至95%。这表明反思机制显著提高了数据库查询的质量,从而更准确地获取答案。</p>
<p>开发者经常做的另一件事是重写反思提示词。例如,你可能想在反思提示中加入“让数据库查询运行更快”或“让查询更清晰”的指令。一旦建立了上述评估体系,你就可以快速尝试不同的提示词创意,并通过测量系统正确率的变化,来判断哪种提示词对你的应用最有效。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/86e1899dc5a332bf491db8d7b63639a5_3.png"></p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/86e1899dc5a332bf491db8d7b63639a5_4.png"></p>
<h2 id="主观评估图表生成示例">主观评估:图表生成示例</h2>
<p>然而,并非所有应用都像数据库查询那样有明确的对错。在之前关于反思的视频中,我们看到了一个图表生成的例子:无反思时生成了堆叠条形图,有反思后生成了另一种图表。但我们如何知道哪个图表更好呢?这更像是一个主观标准,而非纯粹的黑白分明的客观标准。</p>
<p>对于这类主观标准,一种方法是使用大语言模型作为“裁判”。一个基础的做法可能是将两张图表输入一个能接收多张图像的多模态大语言模型,然后直接问“哪张图更好?”。但事实证明,这种方法效果不佳。</p>
<p>以下是使用LM作为裁判时可能遇到的问题:</p>
<ul>
<li><strong>答案质量不稳定</strong>:裁判LM的答案可能不够好。</li>
<li><strong>对提示词措辞敏感</strong>:裁判LM的判断可能高度依赖于提示词的具体措辞。</li>
<li><strong>与人类判断不一致</strong>:裁判LM的排名顺序可能与人类专家的判断不太相符。</li>
<li><strong>存在位置偏见</strong>:许多LM往往会更频繁地选择第一个选项,无论其内容如何。</li>
</ul>
<p>与其让LM直接比较两个输入,<strong>提供一个评分标准(Rubric)来评估单个输入通常能得到更一致的结果</strong>。</p>
<p>你可以这样提示LM:“根据以下质量评分标准评估所附图像”。评分标准可以包含几个清晰的判断维度,例如:</p>
<ul>
<li>图表是否有清晰的标题?</li>
<li>坐标轴标签是否清晰?</li>
<li>选择的图表类型是否合适?</li>
</ul>
<p>事实证明,与其让LM在1到5的尺度上打分(其校准通常不佳),不如给它5个二元判断标准(是/否),然后汇总这些分数得到一个1到5(或1到10)的分数,这样往往能得到更一致的结果。</p>
<p>因此,我们可以收集一批用户查询(例如10-15个),让系统分别生成无反思和有反思的图表,然后使用上述评分标准为每张图像打分,从而检查有反思生成的图像是否真的比无反思的更好。</p>
<p>一旦建立了这样一套评估体系,如果你想更改初始生成提示词或反思提示词,也可以重新运行评估,看看更新后的提示词是否能让系统生成根据该评分标准得分更高的图像。这为你持续优化提示词以获得更好性能提供了一种方法。</p>
<h2 id="总结与对比">总结与对比</h2>
<p>本节课中我们一起学习了如何为反思机制构建评估体系。在构建反思或其他智能体工作流程的评估时,你可能会发现:</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/86e1899dc5a332bf491db8d7b63639a5_6.png"></p>
<ul>
<li><strong>对于有客观标准的任务</strong>,基于代码的评估通常更容易管理。就像数据库查询的例子,我们建立了一个包含标准输入输出的测试集,并编写代码来统计系统生成正确答案的频率。</li>
<li><strong>对于主观性较强的任务</strong>,你可能会使用LM作为裁判,但这通常需要更多的调试,例如需要仔细思考使用什么样的评分标准,才能使作为裁判的LM判断更准确、更可靠。</li>
</ul>
<p>掌握如何进行良好的评估,对于有效构建智能体工作流程至关重要。在后续视频中我们还会深入探讨这一点。</p>
<p>现在你已经了解了如何使用反思机制,下一节视频我们将深入探讨其中一个方面:<strong>如何从外部获取额外信息来显著提升反思的效果</strong>。让我们在下一个视频中继续学习。</p>
<h1 id="012使用外部反馈进行反思-">012:使用外部反馈进行反思 🚀</h1>
<p>在本节课中,我们将要学习如何利用外部反馈来增强AI代理的反思能力,从而显著提升其输出质量。我们将探讨外部反馈相较于仅使用语言模型内部反思的优势,并通过具体示例理解其应用方法。</p>
<h2 id="外部反馈的优势">外部反馈的优势</h2>
<p>上一节我们介绍了反思的概念。本节中我们来看看,如果能够获取外部反馈,其效果将远胜于仅依赖语言模型自身进行的反思。</p>
<p>当我们构建应用程序时,如果仅通过提示工程进行直接生成(零样本提示),性能随提示调整的变化可能呈现如下趋势:初期,随着提示的优化,性能会有所提升;但一段时间后,性能会趋于平缓或达到瓶颈。即使继续调整提示,也很难获得显著的性能提升。</p>
<p>与其将所有时间浪费在调整提示上,有时更好的做法是在流程的早期阶段就引入反思机制。这有时能带来性能上的提升,幅度或大或小,取决于任务的复杂性。</p>
<p>然而,如果能够在反思的基础上引入外部反馈,情况将大为不同。外部反馈意味着语言模型获得的不再是基于原有信息的重复思考,而是全新的外部信息。随着我们继续优化提示和调整外部反馈机制,最终可能达到一个更高的性能水平。</p>
<p>因此,如果你正在进行提示工程,并感觉努力带来的回报正在递减,即调整大量问题后性能提升有限,那么可以考虑引入反思机制。如果能有外部反馈介入,则效果更佳,这有望将性能曲线从平缓的红色轨迹,推向一个更高的改进轨道。</p>
<h2 id="外部反馈的示例">外部反馈的示例</h2>
<p>以下是几个具体的例子,说明软件代码或工具如何创造新信息来辅助反思过程。</p>
<p><strong>1. 代码执行反馈</strong><br>
我们之前看到,对于编写代码的任务,一个反馈来源是直接执行代码,观察其生成的输出或错误信息,并将这些输出反馈给语言模型。模型利用这些新信息进行反思,然后据此编写新版本的代码。</p>
<p><strong>2. 内容审查与模式匹配</strong><br>
如果你使用AI撰写邮件,而邮件中有时会提及竞争对手的名字,你可以编写代码或构建一个软件工具(例如通过正则表达式进行模式匹配)来搜索输出中的竞争对手名称。一旦发现,就将此信息作为批评性输入反馈给AI。这是非常有用的信息,可以指示AI重写文本,避免提及这些竞争对手。</p>
<p><strong>3. 事实核查与网络搜索</strong><br>
另一个例子是使用网络搜索或查阅其他可信来源来对文章进行事实核查。假设你的研究代理写道:“泰姬陵建于1648年。”严格来说,泰姬陵实际上于1631年动工,1648年竣工。这个说法虽非完全错误,但未能准确反映历史。为了更准确地描述这座美丽建筑的建造时间,你可以进行网络搜索,获取解释泰姬陵具体建造时期的文本片段,并将其作为额外输入提供给反思代理。这样,它就能利用这些信息写出关于泰姬陵历史的更好版本。</p>
<p><strong>4. 字数统计与格式限制</strong><br>
最后一个例子,如果你使用语言模型撰写文案(如博客文章或研究论文摘要),但其输出有时会超出字数限制。语言模型目前仍不擅长精确控制字数。此时,你可以实现一个字数统计功能,编写代码来精确计算单词数量。如果超出限制,就将该字数统计结果反馈给语言模型,并要求其重试。这有助于它更准确地达到你期望的输出长度。</p>
<p>在上述三个例子中,你都可以编写一段代码来帮助发现关于初始输出的额外信息(无论是发现的竞争对手名称、网络搜索到的信息还是精确的字数),然后将这些事实反馈给反思用的语言模型,以期它能更好地思考如何改进输出。</p>
<h2 id="总结与展望">总结与展望</h2>
<p>本节课中,我们一起学习了外部反馈在增强AI代理反思能力中的强大作用。反思本身已是一个强大的工具,而结合外部反馈则能将其效能提升到新的高度。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/dcd5a5f7e513a96a4efbefd16e076c1e_1.png"></p>
<p>在下一个模块中,我们将在此基础上进一步探讨,除了你刚才看到的几个工具示例外,如何系统地让你的AI代理调用不同的函数。这将使你的代理应用程序变得更加强大。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/dcd5a5f7e513a96a4efbefd16e076c1e_3.png"></p>
<p>希望你对反思的学习有所收获。期待在下一个视频中与你再见。</p>
<h1 id="013什么是工具-️">013:什么是工具 🛠️</h1>
<p>在本节课中,我们将要学习代理式AI中的一个核心概念:<strong>工具</strong>。我们将了解什么是工具,为什么它们对大型语言模型(LLM)至关重要,以及如何通过赋予LLM调用工具的能力来构建更强大的应用程序。</p>
<h2 id="概述-6">概述</h2>
<p>正如人类使用工具可以完成远超徒手能力范围的事情一样,大型语言模型在获得工具访问权限后,其能力也能得到极大扩展。本节课程将解释“工具使用”的概念,展示其工作原理,并通过具体例子说明工具如何帮助LLM生成更准确、更有用的回答。</p>
<h2 id="什么是工具使用">什么是工具使用?</h2>
<p>上一节我们介绍了代理式AI的基本概念,本节中我们来看看一个关键机制:<strong>工具使用</strong>。</p>
<p>工具使用指的是让您的大型语言模型(LLM)自行决定何时需要请求调用一个函数来执行某项操作、获取某些信息或完成其他任务。这就像人类使用锤子、扳手等工具来增强自身能力。对于LLM而言,我们提供的“工具”就是一些函数,当LLM认为有必要时,可以请求调用这些函数。</p>
<p><strong>核心概念</strong>:<code>工具 = 提供给LLM并可让其请求调用的函数</code></p>
<h2 id="工具使用的工作原理">工具使用的工作原理</h2>
<p>以下是工具使用的基本工作流程:</p>
<ol>
<li><strong>输入提示</strong>:用户向LLM提出问题。</li>
<li><strong>工具决策</strong>:LLM查看可用的工具集,并决定是否需要调用某个工具。</li>
<li><strong>工具调用</strong>:如果决定调用,LLM会请求执行相应的函数(工具)。</li>
<li><strong>结果返回</strong>:被调用的函数执行并返回结果,该结果会被添加回对话历史中。</li>
<li><strong>生成输出</strong>:LLM结合原始问题、自身知识以及工具返回的结果,生成最终的回答。</li>
</ol>
<p>为了直观表示LLM被赋予了使用工具的选项,我们将在图表中使用一个<strong>带有虚线框的LLM图标</strong>。这个虚线框表示我们为LLM提供了一组工具,供其在认为适当时选择使用。</p>
<h2 id="一个简单的例子获取当前时间">一个简单的例子:获取当前时间</h2>
<p>让我们通过一个具体例子来理解。如果您询问一个可能在数月前训练完成的LLM“现在几点了?”,由于训练模型本身并不知道精确的当前时间,它可能会回答:“抱歉,我无法获取当前时间。”</p>
<p>但是,如果您编写一个 <code>get_current_time()</code> 函数,并赋予LLM调用此函数的权限,那么它就能给出更有用的答案。</p>
<p><strong>工作流程示例</strong>:</p>
<ol>
<li>用户提问:“现在几点了?”</li>
<li>LLM(拥有 <code>get_current_time</code> 工具)决定调用该工具。</li>
<li><code>get_current_time()</code> 函数执行,返回结果,例如 “3:20 PM”。</li>
<li>该结果被反馈给LLM。</li>
<li>LLM 生成最终输出:“现在是下午3点20分。”</li>
</ol>
<p><strong>重要特性</strong>:工具的使用是由LLM自主决定的。对于同一个设置了时间工具的LLM,如果您问“绿茶含有多少咖啡因?”,LLM知道回答这个问题不需要当前时间,因此会直接生成答案,而不会调用 <code>get_current_time</code> 函数。</p>
<h2 id="工具如何提升应用能力">工具如何提升应用能力</h2>
<p>赋予LLM工具访问权限能显著提升其回答质量。以下是一些例子:</p>
<ul>
<li><strong>网络搜索</strong>:如果用户问“你能找到加州山景城附近的一些意大利餐厅吗?”,一个拥有网络搜索工具的LLM可以调用搜索引擎获取实时信息,并据此生成回答。</li>
<li><strong>数据库查询</strong>:如果您经营一家零售店,LLM被赋予查询数据库的工具,那么对于“给我看看买了白色太阳镜的顾客”这类问题,LLM可以查找销售记录并生成报告。</li>
<li><strong>专业计算</strong>:对于“如果以5%的年利率存入1000美元,10年后我会得到多少钱?”这样的财务问题,LLM可以调用利息计算工具来获得精确答案。另一种方法是让LLM编写并执行一段计算代码,例如 <code>1000 * (1 + 0.05)**10</code>,这本身也是一种工具使用。</li>
</ul>
<p>作为开发者,您需要根据应用程序的目标任务来设计和创建相应的工具。无论是餐厅查询、零售问答还是财务助理,都需要提供合适的工具集。</p>
<h2 id="多工具协作示例">多工具协作示例</h2>
<p>到目前为止,我们看到的例子大多只涉及一个工具。但在许多实际用例中,您需要为LLM提供多个工具,让它根据情况选择调用。</p>
<p>假设我们正在构建一个<strong>日历助手代理</strong>。用户提出请求:“请在我的日历中查找周四的空闲时段,并安排一个与Alice的约会。”</p>
<p>为了实现这个请求,我们可能需要为LLM提供以下工具(函数):</p>
<ul>
<li><code>check_calendar()</code>:查看日历中的空闲时间。</li>
<li><code>make_appointment()</code>:发送日历邀请,创建新日程。</li>
<li><code>delete_appointment()</code>:取消已有的日历条目。</li>
</ul>
<p>以下是LLM可能执行的步骤序列:</p>
<ol>
<li>LLM首先决定,在可用工具中,它应该先使用 <code>check_calendar</code> 函数来查看我周四何时有空。</li>
<li>该函数返回空闲时段(例如“下午2点至4点”),结果反馈给LLM。</li>
<li>LLM接着决定下一步:选择一个具体时间(比如下午3点),然后调用 <code>make_appointment</code> 函数向Alice发送日历邀请。</li>
<li>该函数返回操作成功的确认信息,并反馈给LLM。</li>
<li>最后,LLM生成最终输出告诉用户:“您与Alice的约会已安排在周四下午3点。”</li>
</ol>
<p>这个例子展示了LLM如何通过自主决策,按顺序调用多个工具来完成一个复杂的多步骤任务。</p>
<h2 id="总结-3">总结</h2>
<p>本节课中我们一起学习了<strong>工具使用</strong>这一核心概念。我们了解到:</p>
<ul>
<li>工具是提供给LLM并可让其请求调用的函数。</li>
<li>工具使用让LLM能够获取实时信息、执行特定操作,从而极大地扩展了其能力边界。</li>
<li>LLM会自主决定是否需要调用工具,以及调用哪个工具。</li>
<li>开发者需要根据应用场景设计和实现相应的工具集。</li>
<li>通过组合多个工具,可以构建出能够处理复杂、多步骤任务的智能代理。</li>
</ul>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/36c5795e13eabbebd0bc7b8d9672623a_1.png"></p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/36c5795e13eabbebd0bc7b8d9672623a_2.png"></p>
<p>能够为您的LLM提供工具访问权限是一件非常重要的事情,它将使您的应用程序变得更加强大。在下一个视频中,我们将具体看看如何编写函数、创建工具,并将它们提供给您的LLM使用。</p>
<h1 id="014创建工具-️">014:创建工具 🛠️</h1>
<p>在本节课中,我们将学习如何让大型语言模型(LLM)调用外部工具或函数。我们将通过一个简单的例子,逐步拆解其背后的工作原理,即使这个过程最初看起来有些神秘。</p>
<h2 id="概述-7">概述</h2>
<p>大型语言模型(LLM)通常被训练来生成文本。那么,它是如何决定并执行“调用一个函数”这样的非文本操作的呢?本节将通过一个“获取当前时间”的例子,详细解释从LLM请求到函数执行并返回结果的完整流程。理解这个基础过程,将帮助我们更好地掌握现代LLM使用工具的语法。</p>
<h2 id="llm调用工具的基本原理">LLM调用工具的基本原理</h2>
<p>上一节我们介绍了代理式AI的概念,本节中我们来看看LLM调用工具的具体机制。关键在于,LLM本身并不直接执行代码,而是通过生成特定格式的文本来“请求”开发者编写的代码去执行函数。</p>
<p><strong>核心流程</strong>可以用以下伪代码描述:</p>
<pre><code>1. 用户提问 -> LLM
2. LLM生成“函数调用请求”文本 -> 开发者代码
3. 开发者代码解析请求,执行真实函数 -> 获得结果
4. 开发者代码将结果反馈给LLM -> LLM
5. LLM结合结果生成最终回答 -> 用户
</code></pre>
<h2 id="逐步解析无参数的函数调用">逐步解析:无参数的函数调用</h2>
<p>让我们从一个最简单的例子开始:用户询问“现在几点了?”,我们需要LLM调用一个无参数的 <code>get_current_time</code> 函数。</p>
<p>首先,作为开发者,你需要完成以下步骤:</p>
<ol>
<li><strong>实现工具函数</strong>:编写实际能获取时间的代码,例如 <code>get_current_time()</code>。</li>
<li><strong>修改系统提示词</strong>:告诉LLM这个函数的存在和使用方法。</li>
</ol>
<p>以下是提供给LLM的提示词可能的样子:</p>
<pre><code>你有一个可用的工具叫 `get_current_time`。
当你想使用它时,请输出以下文本:
FUNCTION: get_current_time
如果我看到“FUNCTION: get_current_time”,我就会为你调用该函数。
</code></pre>
<p>当用户提问“现在几点了?”时,流程如下:</p>
<ol>
<li><strong>LLM生成请求</strong>:LLM理解需要获取时间,于是输出:<code>FUNCTION: get_current_time</code>。</li>
<li><strong>开发者代码解析</strong>:你写的程序会监控LLM的输出,一旦发现以 <code>FUNCTION:</code> 开头的文本,就提取出函数名 <code>get_current_time</code>。</li>
<li><strong>执行函数</strong>:你的程序调用真正的 <code>get_current_time()</code> 函数,假设返回结果是“8 AM”。</li>
<li><strong>反馈结果给LLM</strong>:你的程序将这个结果“8 AM”作为新消息输入给LLM。此时LLM的对话历史包括:用户的问题、它自己发出的函数请求、以及函数执行的结果“8 AM”。</li>
<li><strong>LLM生成最终回复</strong>:LLM综合所有信息,生成最终回答:“现在是早上8点”。</li>
</ol>
<p>需要明确的是,<strong>LLM从不直接调用函数</strong>。它只是输出一个事先约定好的信号(如<code>FUNCTION: get_current_time</code>),由你的代码来接收这个信号并执行相应操作,然后将结果回传给LLM。</p>
<h2 id="进阶带参数的函数调用">进阶:带参数的函数调用</h2>
<p>理解了基础流程后,我们来看一个更复杂的场景。假设函数可以接受参数,例如 <code>get_current_time(timezone)</code>,用于获取指定时区的当前时间。</p>
<p>以下是修改后的提示词可能包含的指令:</p>
<pre><code>你可以使用 `get_current_time` 工具来获取特定时区的当前时间。
使用时,请输出:FUNCTION: get_current_time(<时区参数>)
例如,对于新西兰时间,输出:FUNCTION: get_current_time(Pacific/Auckland)
</code></pre>
<p>当用户提问“新西兰现在几点了?”时,流程如下:</p>
<ol>
<li><strong>LLM生成请求</strong>:LLM判断需要获取新西兰时间,并知道其对应的时区参数。它输出:<code>FUNCTION: get_current_time(Pacific/Auckland)</code>。</li>
<li><strong>开发者代码解析与执行</strong>:你的代码解析出函数名 <code>get_current_time</code> 和参数 <code>Pacific/Auckland</code>,然后调用真实函数 <code>get_current_time("Pacific/Auckland")</code>,假设返回“4 AM”。</li>
<li><strong>反馈与最终回复</strong>:将结果“4 AM”反馈给LLM。LLM据此生成最终回答:“新西兰现在是凌晨4点”。</li>
</ol>
<h2 id="总结与展望-1">总结与展望</h2>
<p>本节课中我们一起学习了LLM调用工具的传统流程。我们来总结一下关键步骤:</p>
<ol>
<li><strong>提供工具</strong>:实现功能函数,并通过提示词告知LLM该工具的存在及调用格式。</li>
<li><strong>LLM发出请求</strong>:LLM在需要时,按照约定格式输出一个字符串信号。</li>
<li><strong>执行与反馈</strong>:你的代码解析该信号,执行对应函数,并将结果返回给LLM。</li>
<li><strong>LLM继续处理</strong>:LLM利用返回的结果生成最终回答或决定下一步行动。</li>
</ol>
<p>需要注意的是,上述使用全大写<code>FUNCTION:</code>作为信号的方法是一种早期、略显笨拙的实现方式。在现代,LLM已经被直接训练成使用一种更清晰、更结构化的语法来请求工具调用。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/a6cbc46217b8f751744146f20698c3f5_1.png"></p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/a6cbc46217b8f751744146f20698c3f5_2.png"></p>
<p>在下一节中,我们将看看现代LLM用于调用工具的标准语法是什么样子,这会让整个过程更加简洁和强大。让我们继续观看下一个视频。</p>
<h1 id="015工具调用语法-️">015:工具调用语法 🛠️</h1>
<p>在本节课中,我们将学习如何编写代码,使你的大语言模型(LLM)能够调用外部工具。我们将重点介绍如何使用AI Suite开源库来简化这一过程,并理解其背后的工作原理。</p>
<h2 id="概述-8">概述</h2>
<p>上一节我们介绍了工具调用的基本概念。本节中,我们来看看如何通过具体的代码语法,让LLM请求并执行工具函数。我们将使用一个名为AI Suite的开源库,它可以帮助我们更便捷地管理工具调用。</p>
<h2 id="工具调用代码示例">工具调用代码示例</h2>
<p>首先,我们来看一个没有时区参数的旧版获取当前时间函数。</p>
<pre><code class="language-python">def get_current_time():
"""
获取当前时间。
"""
# 函数实现...
</code></pre>
<p>以下是如何使用AI Suite库来让LLM调用工具的代码。这段语法与OpenAI的语法非常相似,但AI Suite使其能够更容易地调用多个LLM提供商。</p>
<pre><code class="language-python">response = client.chat.completions.create(
model="gpt-4",# 假设使用OpenAI的GPT-4模型
messages=messages,# 传递给LLM的消息序列
tools=,# LLM可以访问的工具列表
max_turns=5# 最大调用轮次,防止无限循环
)
</code></pre>
<p>如果这段代码看起来有些复杂,请不要担心,我们将在后续的实验中看到更多示例。简单来说,它与OpenAI的语法类似:你指定模型、消息和工具列表。<code>max_turns</code>参数是一个安全上限,用于限制LLM连续请求调用工具的次数,实践中很少会触及这个限制。</p>
<h2 id="ai-suite如何自动描述工具">AI Suite如何自动描述工具</h2>
<p>AI Suite的一个便利之处在于,它会自动将函数<code>get_current_time</code>以适当的方式描述给LLM,从而使LLM知道何时调用它。你无需手动编写冗长的提示词。</p>
<p>其实现原理并不神秘:AI Suite会查看与<code>get_current_time</code>函数关联的<strong>文档字符串</strong>(即函数定义中的注释),并利用这些信息来向LLM描述该函数。</p>
<p>为了说明这一点,我们再次查看这个函数,以及使用AI Suite调用LLM的代码片段。</p>
<pre><code class="language-python">def get_current_time():
"""
获取当前时间。
"""
# 函数实现...
# AI Suite在后台会创建一个JSON Schema来描述此函数
</code></pre>
<p>在后台,AI Suite会创建一个详细的JSON Schema来描述函数。具体来说,它会提取函数的名称(<code>get_current_time</code>)以及从文档字符串中提取的函数描述,然后将这些信息传递给LLM。这使LLM能够判断何时需要调用此函数。</p>
<p>有些API要求你手动构建这个JSON Schema,但AI Suite包为你自动完成了这项工作。</p>
<h2 id="处理带参数的复杂工具">处理带参数的复杂工具</h2>
<p>让我们看一个更复杂的例子。如果你有一个带有时区参数的<code>get_current_time2</code>函数。</p>
<pre><code class="language-python">def get_current_time2(time_zone: str):
"""
根据指定的时区获取当前时间。
参数:
time_zone (str): 时区名称,例如 'America/New_York' 或 'Pacific/Auckland'。
"""
# 函数实现...
</code></pre>
<p>对于这个函数,AI Suite会创建一个更复杂的JSON Schema。和之前一样,它会提取函数名和描述,同时还会识别参数并根据左侧所示的文档向LLM描述它们。这样,当LLM生成调用该工具所需的参数时,它就知道应该传入类似<code>"America/New_York"</code>或<code>"Pacific/Auckland"</code>这样的值。</p>
<p>如果你执行左下角的代码片段,它将使用OpenAI的GPT-4模型。如果LLM决定调用一个函数,它就会调用该函数,获取函数输出,将其反馈给LLM,并最多重复此过程5轮,然后返回最终响应。</p>
<p>需要注意的是,如果LLM请求调用<code>get_current_time</code>函数,AI Suite(或这个客户端)会为你调用它。你不需要自己显式地执行这一步。所有这些都封装在你需要编写的这个单一函数调用中。</p>
<p>请注意,有些其他接口的实现可能需要你手动执行这些步骤。但使用这个特定的AI Suite包,所有功能都封装在了<code>client.chat.completions.create</code>函数调用中。</p>
<h2 id="代码执行工具的特殊性">代码执行工具的特殊性</h2>
<p>在所有可以提供给LLM的工具中,有一个工具非常特殊且强大,那就是<strong>代码执行工具</strong>。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/74d6795dc82d513423a05735608fbbdd_1.png"></p>
<p>如果你能告诉LLM:“你可以编写代码,而我有一个工具可以为你执行这些代码”,那么这将赋予LLM极大的灵活性,因为代码几乎可以做任何事情。事实证明,赋予LLM编写和执行代码的能力是一个非常强大的工具。</p>
<p>因此,代码执行工具是特殊的。我们将在下一个视频中详细讨论LLM的代码执行工具。</p>
<h2 id="总结-4">总结</h2>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/74d6795dc82d513423a05735608fbbdd_3.png"></p>
<p>本节课中,我们一起学习了如何通过AI Suite库编写代码来实现LLM的工具调用。我们了解了其自动利用文档字符串生成工具描述的原理,并看到了处理带参数工具的示例。最后,我们提到了代码执行工具的特殊性和强大之处。现在你已经知道如何进行函数调用了,希望你能在实验课中愉快地探索。当你提供几个函数,并看到LLM为了完成你的请求而在“世界”中采取行动、获取更多信息时,这确实非常神奇。如果你之前没有尝试过,我相信你会发现这真的很酷。</p>
<h1 id="016模块1-5代码执行-">016:模块1-5|代码执行 🧑💻</h1>
<p>在本节课中,我们将要学习如何通过让大型语言模型(LLM)编写并执行代码,来极大地扩展AI代理的能力,使其能够处理复杂的计算任务。我们将探讨其工作原理、实现方法以及需要注意的安全问题。</p>
<hr>
<h2 id="概述-9">概述</h2>
<p>在之前的内容中,我们介绍了如何为AI代理创建特定的工具(如加法、乘法函数)来处理任务。然而,为每一种可能的数学或计算操作都预先编写工具是不现实的。本节将介绍一种更强大的方法:让LLM动态生成代码来解决问题。</p>
<h2 id="代码执行的工作原理">代码执行的工作原理</h2>
<p>上一节我们介绍了为特定任务创建工具的方法。本节中我们来看看如何通过代码执行来应对更广泛、更复杂的任务。</p>
<p>其核心思想是:我们不再为每一个计算功能都编写一个工具,而是指示LLM根据用户的问题,动态生成解决问题的代码。</p>
<p>以下是实现此流程的关键步骤:</p>
<ol>
<li><strong>用户提出查询</strong>:例如,“2的平方根是多少?”</li>
<li><strong>LLM生成代码</strong>:我们通过特定的提示词(Prompt)指示LLM编写Python代码来解决问题。</li>
<li><strong>提取并执行代码</strong>:从LLM的回复中提取出代码,并在一个安全的环境中执行它。</li>
<li><strong>返回结果</strong>:将代码执行的结果返回给LLM,由LLM生成格式友好的最终答案给用户。</li>
</ol>
<h2 id="实现步骤详解">实现步骤详解</h2>
<p>让我们通过一个具体的例子来理解这个过程。</p>
<h3 id="1-设计提示词prompt">1. 设计提示词(Prompt)</h3>
<p>首先,你需要设计一个提示词,明确告诉LLM你的要求。一个典型的提示词如下:</p>
<pre><code>write code to solve the user's query。
return your answer as Python code delim it with <execute_python> and closing </execute_python> tags。
</code></pre>
<p>这个提示词要求LLM将解决方案写成Python代码,并用特定的标签<code><execute_python></code>和<code></execute_python></code>包裹起来,方便我们后续提取。</p>
<h3 id="2-llm生成代码">2. LLM生成代码</h3>
<p>当用户查询“What is the square root of two?”时,LLM可能会生成如下回复:</p>
<pre><code><execute_python>
import math
print(math.sqrt(2))
</execute_python>
</code></pre>
<h3 id="3-提取与执行代码">3. 提取与执行代码</h3>
<p>接下来,我们需要从回复中提取代码并执行。以下是两种常见的方法:</p>
<ul>
<li><strong>使用<code>exec()</code>函数</strong>:这是Python的内置函数,可以直接执行字符串形式的代码。虽然功能强大,但存在安全风险。<pre><code class="language-python">code_string = “import math\nprint(math.sqrt(2))”
exec(code_string)# 输出:1.4142135623730951
</code></pre>
</li>
<li><strong>使用沙箱环境</strong>:为了安全起见,最佳实践是在一个隔离的沙箱环境(如Docker容器)中运行生成的代码。这可以防止恶意或错误的代码损害你的主系统或泄露敏感数据。</li>
</ul>
<h3 id="4-处理结果并回复">4. 处理结果并回复</h3>
<p>代码执行后,你会得到一个结果(例如<code>1.4142135623730951</code>)。将这个结果传回给LLM,LLM可以将其组织成自然语言的答案回复给用户,例如:“2的平方根大约是1.414。”</p>
<h2 id="安全考量与最佳实践">安全考量与最佳实践</h2>
<p>让AI代理执行任意生成的代码存在潜在风险。一个真实的例子是,一个AI编码代理曾错误地尝试删除项目目录中的所有<code>.py</code>文件。</p>
<p>因此,遵循最佳实践至关重要:</p>
<ul>
<li><strong>始终使用沙箱环境</strong>:这是最重要的安全措施。像Docker或E2B这样的工具可以创建一个隔离的环境来运行代码,即使代码出错或有害,也不会影响到主机系统。</li>
<li><strong>实施反射机制</strong>:如果代码执行失败或报错,可以将错误信息反馈给LLM,让它“反思”并尝试生成修正后的代码。这可以提高最终答案的准确性。</li>
<li><strong>做好数据备份</strong>:在处理重要数据时,确保有备份,以防万一。</li>
</ul>
<h2 id="代码执行的优势">代码执行的优势</h2>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/cb5447b44e08202dd03586073ea59602_1.png"></p>
<p>代码执行作为一种工具,为AI应用带来了显著优势:</p>
<ul>
<li><strong>处理复杂任务</strong>:LLM可以生成代码来进行利息计算、解方程或处理比简单算术复杂得多的数学问题。</li>
<li><strong>减少工具开发</strong>:你无需为无数种可能的功能预先编写工具,LLM可以根据需要即时生成解决方案。</li>
<li><strong>灵活性高</strong>:这种方法使AI代理能够适应各种未预见的、需要计算或逻辑处理的新任务。</li>
</ul>
<h2 id="总结与展望-2">总结与展望</h2>
<p>本节课中我们一起学习了代码执行这一强大技术。我们了解了如何通过提示词让LLM生成代码,如何安全地提取和执行这些代码,以及必须注意的安全措施。这种方法极大地扩展了AI代理解决问题的能力。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/cb5447b44e08202dd03586073ea59602_3.png"></p>
<p>目前,我们讨论的方法都需要开发者自己创建并管理这些工具。然而,许多团队都在构建类似的工具。幸运的是,一个名为<strong>模型上下文协议(Model Context Protocol, MCP)</strong>的新标准正在兴起,它能让开发者更轻松地为LLM接入海量的现有工具。在接下来的视频中,我们将进一步了解MCP。</p>
<h1 id="017模型上下文协议mcp-">017:模型上下文协议(MCP) 🧩</h1>
<p>在本节课中,我们将要学习模型上下文协议(MCP)。MCP是一个由Anthropic提出,并被众多公司和开发者采纳的标准,旨在为大型语言模型提供更丰富的上下文和工具访问能力。了解MCP将帮助你为应用程序获取更多资源。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/54c5fffbebd8ec747ee437fda00c6c20_1.png"></p>
<h2 id="解决的问题与核心思想">解决的问题与核心思想</h2>
<p>上一节我们介绍了为AI代理提供工具的重要性,本节中我们来看看MCP如何解决工具集成中的效率问题。</p>
<p>MCP试图解决的核心痛点是开发工作的重复性。如果一个开发者想要构建一个集成了Slack、Google Drive、Github数据或Postgres数据库的应用程序,他需要编写代码来封装这些服务的API,以便为应用程序提供功能。当另一个团队构建另一个应用程序时,他们又需要重复集成Slack、Google Drive和Github等工具。这意味着,如果有 <strong>M</strong> 个应用程序和 <strong>N</strong> 种工具,整个社区需要完成的工作总量是 <strong>M × N</strong>。</p>
<p>MCP通过提出一个应用程序访问工具和数据源的标准,改变了这一局面。其核心思想是:</p>
<p><strong>总工作量 = M + N</strong></p>
<p>而非 <strong>M × N</strong></p>
<h2 id="mcp的构成">MCP的构成</h2>
<p>MCP最初的设计侧重于如何为大型语言模型提供更多上下文或获取数据,其初始工具主要是用于获取数据的,在文档中被称为“资源”。但MCP实际上提供了对数据以及应用程序可能想要调用的更通用函数的访问。</p>
<p>以下是MCP生态系统中的主要组成部分:</p>
<ul>
<li><strong>MCP客户端</strong>:指那些需要访问工具或数据的应用程序。</li>
<li><strong>MCP服务器</strong>:通常是封装了数据访问逻辑的软件包装器,它们提供对Slack、Github、Google Drive等资源的访问,或允许你在这些资源上执行操作。</li>
</ul>
<p>如今,消费工具或资源的MCP客户端列表正在快速增长,同时提供工具和资源的MCP服务器也在不断增加。</p>
<h2 id="一个mcp使用示例">一个MCP使用示例</h2>
<p>为了让你更直观地理解,我们来看一个使用MCP客户端的快速示例。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/54c5fffbebd8ec747ee437fda00c6c20_3.png"></p>
<p>这是一个云桌面应用程序,它已连接到一个Github MCP服务器。</p>
<p>当我输入查询:“总结来自Github仓库(此URL,实际上是AI Suite仓库)的README markdown文件”时,这个作为MCP客户端的应用程序会使用Github MCP服务器,发出一个请求:<code>getReadmeFromRepo(AI_Suite, 此仓库)</code>。随后,它收到了一个相当长的响应。所有这些内容随后被反馈给语言模型的上下文,模型最终生成了该markdown文件的摘要。</p>
<p>现在,让我输入另一个请求:“让我看看最新的拉取请求是什么”。这促使语言模型使用MCP服务器发出另一个不同的请求:<code>listPullRequests</code>。这是Github MCP服务器提供的另一个工具。它请求列出AI Suite仓库的拉取请求,并获取了相关信息。这些响应被反馈给语言模型,然后模型写出了关于该仓库最新拉取请求的简洁技术摘要。</p>
<h2 id="总结与展望-3">总结与展望</h2>
<p>本节课中我们一起学习了模型上下文协议(MCP)。MCP是一个重要的标准,它通过标准化工具和数据源的访问方式,极大地减少了开发者的重复工作,提高了生态系统的效率。如果你想深入了解,DeepLearning.AI也提供了一个专门深入讲解MCP协议的短期课程,你可以在完成本课程后去查看。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/54c5fffbebd8ec747ee437fda00c6c20_5.png"></p>
<p>希望本视频能让你简要了解MCP为何有用,以及为何许多开发者现在都基于此标准进行构建。</p>
<p>这引出了我们关于工具使用的最后一个视频。通过为你的语言模型提供工具访问,你将能够构建更强大的代理应用程序。</p>
<p>在下一个模块中,我们将讨论评估和错误分析。根据我的观察,能够高效执行代理工作流的团队与效率较低的团队之间的一个关键区别,就在于推动严格评估流程的能力。在接下来的系列视频中,我将与你分享一些关于如何使用评估来驱动代理工作流开发的最佳实践,这可能是整个课程中最重要的模块。</p>
<p>期待在下一个模块中与你相见。</p>
<h1 id="018构建与评估ai工作流">018:构建与评估AI工作流</h1>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/2b7f2c8a5541c3eb50a94501a2e40d76_1.png"></p>
<p>在本节课中,我们将学习构建代理式AI工作流的实用技巧,并重点探讨如何通过评估来发现和改进系统的问题。我们将通过几个具体例子,理解如何创建和使用评估来驱动系统性能的提升。</p>
<h2 id="概述从原型到评估">概述:从原型到评估</h2>
<p>上一节我们介绍了代理式AI的基本概念。本节中,我们来看看如何通过构建快速原型并建立评估来迭代改进系统。</p>
<p>开发代理式AI系统时,很难提前预知系统在哪些方面表现良好,在哪些方面表现不佳。因此,一个常见的建议是,先构建一个哪怕是“快速而粗糙”的系统原型。这样你就可以运行它,观察输出,从而更精准地发现需要重点改进的地方。相比之下,花费数周时间进行理论推测和假设,效果往往不如直接动手构建一个安全、合理且不泄露数据的快速原型。</p>
<h2 id="构建评估以驱动改进">构建评估以驱动改进</h2>
<p>在构建了初始原型后,下一步是识别问题并建立评估来量化改进。以下是创建评估的几个步骤。</p>
<h3 id="第一步检查输出并识别问题模式">第一步:检查输出并识别问题模式</h3>
<p>首先,你需要运行系统并检查其输出。例如,假设你构建了一个发票处理工作流,其任务是提取四个必填字段并保存到数据库记录中。</p>
<p>构建系统后,你可以找一批发票(例如10或20张),逐一检查输出结果,看看哪些处理正确,哪些出现了错误。</p>
<p>以下是检查时可能发现的情况:</p>
<ul>
<li>发票1:输出正确。</li>
<li>发票2:混淆了发票开具日期和到期日。在本任务中,我们需要提取到期日以便按时付款。</li>
<li>发票3:输出正确。</li>
<li>发票4:输出正确。</li>
</ul>
<p>通过检查多个例子,你可能会发现一个常见的问题模式:系统在处理日期时频繁出错。基于此观察,你可以得出结论,需要优先改进系统提取到期日的准确性。</p>
<h3 id="第二步创建针对性评估">第二步:创建针对性评估</h3>
<p>一旦确定了需要改进的核心问题(例如日期提取),就应该创建一个评估来量化该问题的严重程度并跟踪改进进度。</p>
<p>对于发票日期提取问题,你可以创建一个测试集或评估集。</p>
<p>以下是创建评估集的步骤:</p>
<ol>
<li>找到10到20张发票。</li>
<li>手动记录下每张发票的正确到期日,并以标准年月日格式(如<code>2025-08-20</code>)写下。</li>
<li>为了便于后续用代码评估,你可以在给大语言模型的提示中要求其始终以<code>年月日</code>格式输出日期。</li>
<li>编写代码从模型输出中提取日期(使用正则表达式匹配模式,例如四位年份、两位月份、两位日期)。</li>
<li>编写测试代码,判断提取出的日期是否等于你手动标注的真实日期。</li>
</ol>
<p><strong>代码示例:检查日期匹配</strong></p>
<pre><code class="language-python"># 假设 extracted_date 是从模型输出中提取的字符串,ground_truth_date 是标注的正确日期
if extracted_date == ground_truth_date:
correct_count += 1
</code></pre>
<p>通过这个包含约20个例子的评估集,你可以修改提示词或调整系统组件,并观察提取日期的正确率是否提升。</p>
<h3 id="第三步迭代改进与评估">第三步:迭代改进与评估</h3>
<p>这个过程概括了改进代理式AI工作流的常见路径:观察输出,发现问题,如果知道如何修复就直接修复。如果需要更长时间的迭代改进,则建立评估并用它来驱动后续开发。</p>
<p>此外,随着开发的深入,你可能会发现初始的20个例子不够全面,或者数量太少。这时,你可以随时向评估集中添加更多例子,确保它能更好地反映你对系统性能是否满意的判断。</p>
<h2 id="评估的不同类型与应用场景">评估的不同类型与应用场景</h2>
<p>上一节我们以发票处理为例介绍了有明确标注的评估。本节中我们来看看其他几种常见的评估场景。</p>
<h3 id="场景一评估客观规则无逐例标注">场景一:评估客观规则(无逐例标注)</h3>
<p>假设我们正在构建一个为Instagram撰写产品说明的营销文案助手。营销团队要求文案长度不超过10个单词。</p>
<p>系统接收产品图片(如太阳镜)和用户查询(如“请写一段推销这些太阳镜的文案”),然后由多模态大模型生成描述。</p>
<p>检查输出后,你发现文案内容大多不错,但有时长度会超标。例如,太阳镜文案17个词,咖啡机文案14个词,搅拌机文案11词。这表明模型在遵守长度规则方面存在困难。</p>
<p>对于这种情况,你可以创建一个评估来跟踪文本长度。</p>
<p><strong>创建评估的步骤:</strong></p>
<ol>
<li>创建一个测试集,包含太阳镜、咖啡机等约10-20个例子。</li>
<li>运行系统处理每个例子。</li>
<li>编写代码计算输出文本的单词数。</li>
<li>将生成文本的长度与10个单词的目标限制进行比较。</li>
</ol>
<p><strong>代码示例:检查文案长度</strong></p>
<pre><code class="language-python"># 假设 generated_text 是模型生成的文案
word_count = len(generated_text.split())
if word_count <= 10:
correct_count += 1
</code></pre>
<p>这个评估与发票例子不同之处在于,它没有“逐例标注的真实值”。每个例子的目标都是相同的(≤10个词),而不是像发票日期那样每张发票都有一个独特的正确日期。</p>
<h3 id="场景二评估主观质量有逐例标注">场景二:评估主观质量(有逐例标注)</h3>
<p>让我们回顾之前的研究代理例子。检查它在不同输入提示下的输出时,你可能会发现一些问题。</p>
<p>例如:</p>
<ul>
<li>要求撰写关于“黑洞研究近期突破”的文章时,它遗漏了一些被广泛报道的重要成果。</li>
<li>要求研究“在西雅图租房与买房”时,它做得不错。</li>
<li>要求研究“水果采摘机器人”时,它未提及一家领先的设备公司。</li>
</ul>
<p>基于此,你发现系统有时会遗漏人类专家作者肯定会涵盖的重要论点。为此,你可以创建一个评估来衡量它捕捉要点的频率。</p>
<p><strong>创建评估的步骤:</strong></p>
<ol>
<li>准备一系列示例提示(如关于黑洞、机器人采摘等)。</li>
<li>为每个提示手动制定3到5个“黄金标准”讨论要点。<strong>这里存在逐例标注</strong>,因为每个主题的重要要点都不同。</li>
<li>使用一个大语言模型作为“裁判”,来统计生成的文章中包含了多少个黄金标准要点。</li>
</ol>
<p><strong>提示词示例(给裁判LLM):</strong></p>
<pre><code>请判断提供的文章中包含了多少条(共5条)黄金标准讨论要点。
原始提示:[用户提问]
文章文本:[模型生成的文本]
黄金标准要点:[要点列表1, 要点2, ...]
请返回一个JSON对象,包含“分数”(0到5)和“解释”。
</code></pre>
<p>在这个例子中,我们使用LLM作为裁判来计数,因为讨论要点的表述方式多种多样,简单的正则表达式或模式匹配代码可能效果不佳。这是一种针对更主观评价的评估。</p>
<h2 id="评估方法的分类框架">评估方法的分类框架</h2>
<p>通过以上例子,我们可以看到评估方法可以根据两个维度进行分类,形成一个有用的2x2网格:</p>
<table>
<thead>
<tr>
<th style="text-align: left">评估方式</th>
<th style="text-align: left"><strong>有逐例标注的真实值</strong></th>
<th style="text-align: left"><strong>无逐例标注的真实值</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left"><strong>用代码进行客观评估</strong></td>
<td style="text-align: left"><strong>发票日期提取</strong>:编写代码检查输出日期是否与每张发票的唯一正确日期匹配。</td>
<td style="text-align: left"><strong>营销文案长度</strong>:编写代码检查每个输出的单词数是否都满足≤10词的统一规则。</td>
</tr>
<tr>
<td style="text-align: left"><strong>用LLM作为裁判进行主观评估</strong></td>
<td style="text-align: left"><strong>研究文章要点</strong>:使用LLM裁判判断文章是否涵盖了为每个主题独特制定的要点列表。</td>
<td style="text-align: left"><strong>图表评分</strong>:使用LLM裁判根据统一的评分标准(如是否有坐标轴标签)评估每个生成的图表。</td>
</tr>
</tbody>
</table>
<p>这个框架可以帮助你思考为自己的应用构建哪种类型的评估。这些评估通常被称为<strong>端到端评估</strong>,因为一端是输入(如用户查询),另一端是最终输出,评估的是整个端到端系统的性能。</p>
<h2 id="设计端到端评估的最终建议">设计端到端评估的最终建议</h2>
<p>在本节最后,我想分享一些设计端到端评估的实用建议。</p>
<p><strong>1. 从“快速而粗糙”的评估开始</strong><br>
许多团队因为认为构建评估是一项耗时数周的大工程而迟迟无法开始。实际上,就像迭代改进代理工作流一样,你也应该计划迭代改进你的评估。开始时,用10-20个例子建立一个初步评估,写点代码或用LLM裁判,先获得一些度量指标。这可以与人工检查输出相结合,共同驱动决策。</p>
<p><strong>2. 迭代并改进你的评估集</strong><br>
随着开发进程,你可能会发现初始的评估集无法完全捕捉你对系统好坏的判断。例如,你改进了系统,感觉效果更好,但评估分数却没有提高。这通常是一个信号,提示你需要扩大评估集,或者改变评估输出方式,使其更符合你的实际判断。因此,你的评估集和评估方法也会随着时间的推移而变得更完善。</p>
<p><strong>3. 从评估中获取改进灵感</strong><br>
代理工作流通常用于自动化人类可以完成的任务。对于这类应用,我常寻找那些系统表现<strong>逊于人类专家</strong>的环节。这能为我提供明确的方向,告诉我应该集中精力改进哪些方面,或者需要收集哪些类型的例子来让工作流表现得更好。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/2b7f2c8a5541c3eb50a94501a2e40d76_3.png"></p>
<h2 id="总结与预告-1">总结与预告</h2>
<p>本节课中我们一起学习了如何通过构建快速原型来启动代理式AI项目,并通过创建端到端评估来识别问题、量化性能并驱动系统迭代改进。我们探讨了基于代码的客观评估和使用LLM裁判的主观评估,以及它们在有/无逐例标注情况下的应用,并通过一个分类框架梳理了这些方法。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/2b7f2c8a5541c3eb50a94501a2e40d76_5.png"></p>
<p>除了帮助你驱动改进,评估还有一个重要作用:帮助你理解复杂代理系统中,哪个组件最值得投入精力优化。因为代理系统通常由多个部分组成,高效判断优化重点是一项关键技能。在下一个视频中,我们将深入探讨这个话题。</p>
<h1 id="019错误分析与优先级排序-">019:错误分析与优先级排序 🎯</h1>
<p>在本节课中,我们将学习如何对代理工作流进行错误分析,并确定改进的优先级。当您构建的代理系统未能达到预期效果时,系统性地分析错误来源,而非凭直觉猜测,能极大地提升您改进系统的效率。</p>
<p>上一节我们介绍了研究代理的示例,本节中我们来看看如何通过分析其工作流中的中间输出来定位问题。</p>
<h2 id="错误分析的重要性">错误分析的重要性</h2>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/a96b64854059efd64a7937ba8c6d04fd_1.png"></p>
<p>假设您已经构建了一个代理工作流,但其表现未达预期。这种情况经常发生。问题在于,您应该将改进精力集中在何处?</p>
<p>代理工作流包含许多不同的组件,改进某些组件可能比其他组件带来更大的收益。您选择聚焦点的能力,将极大地影响您改进系统的速度。我发现,一个团队效率高低的关键预测指标之一,就是他们能否通过一个严谨的错误分析流程来确定工作重点。因此,这是一项重要的技能。</p>
<h2 id="如何进行错误分析">如何进行错误分析</h2>
<p>在研究代理的示例中,我们在之前的视频里已经看到了错误分析。我们发现它经常遗漏关键点。专家本应在某些主题上写出引人入胜的文章。</p>
<p>现在您发现了“有时遗漏关键点”这个问题。您如何知道该改进哪里?事实证明,在这个工作流的众多步骤中,几乎任何一步都可能导致“遗漏关键点”这个问题。</p>
<p>例如:</p>
<ul>
<li>第一步的LLM可能生成了不佳的搜索词,导致搜索了错误的内容,未能发现正确的文章。</li>
<li>或者使用的网络搜索引擎本身效果不佳。实际上存在多个网络搜索引擎,其中一些比另一些更好。</li>
<li>或者网络搜索本身没问题,但当我们将搜索结果列表交给LLM时,它可能没有很好地选出最佳的几篇来下载。</li>
<li>网页抓取在此案例中问题较少(假设您能准确抓取网页),但在将网页内容交给LLM后,LLM可能忽略了已抓取文档中的某些要点。</li>
</ul>
<p>有些团队有时会凭直觉选择其中一个组件进行改进,有时这能奏效,但有时会导致团队花费数月时间,系统整体性能却进展甚微。</p>
<p>因此,与其凭直觉决定改进哪个组件,我认为进行错误分析以更好地理解工作流中的每一步要有效得多。特别是,我经常检查<strong>追踪信息</strong>,即每个步骤后的中间输出,以了解哪些组件的性能不达标(即远低于人类专家的水平),因为这指明了哪里可能存在显著的改进空间。</p>
<h2 id="检查追踪信息示例">检查追踪信息示例</h2>
<p>让我们看一个例子。如果我们要求研究代理撰写一篇关于黑洞科学最新发现的文章,其输出可能是这样的搜索词:“黑洞理论 爱因斯坦 事件视界望远镜 射电……”等等。</p>
<p>然后,我会让人类专家查看这些搜索词,判断它们对于撰写黑洞科学最新发现的文章是否合理。也许专家会说这些网络搜索词看起来没问题,与人类会做的搜索很相似。</p>
<p>接着,我查看网络搜索的输出,即返回的URL列表。网络搜索会返回许多不同的网页,可能其中一篇是“小学生声称破解了3年之久的黑洞谜题——来自AstroKid新闻”。这看起来不像是最严谨的同行评议文章。检查所有返回的文章后,您可能会得出结论:它返回了太多博客或大众媒体类型的文章,而不足以支撑撰写一篇高质量的研究报告。</p>
<p>同样,最好也查看其他步骤的输出。例如,选出的“最佳五个来源”可能以AstroKid新闻、SpaceB 2000、SpaceF新闻等结尾。</p>
<p>正是通过查看这些中间输出,您才能尝试评估每个步骤输出结果的质量。</p>
<h2 id="相关术语">相关术语</h2>
<p>所有中间步骤的完整输出集合通常被称为该代理一次运行的<strong>追踪信息</strong>。此外,在其他资料中您可能还会看到,单个步骤的输出有时被称为<strong>跨度</strong>。这些术语来自计算机可观测性文献,用于帮助理解计算机的运行情况。在本课程中,我会较多地使用“追踪信息”一词,较少使用“跨度”,但您可能会在互联网上看到这两个术语。</p>
<p>通过阅读追踪信息,您可以开始非正式地了解哪些组件可能问题最大。</p>
<h2 id="系统化错误分析方法">系统化错误分析方法</h2>
<p>为了以最系统化的方式进行错误分析,将注意力集中在系统出错的案例上是有用的。也许有些文章写得很好,输出完全令人满意。我会将这些案例放在一边,并尝试找出一组例子,在这些例子中,无论出于何种原因,您的研究代理的最终输出并不完全令人满意,然后只专注于这些例子。这就是我们称之为“错误分析”的原因之一,因为我们希望专注于系统出错的案例,并通过分析找出哪些组件对错误负主要责任。</p>
<p>为了使分析更严谨,而不仅仅是阅读和获得非正式的印象,您可以建立一个电子表格来更明确地统计错误所在。这里的“错误”指的是,某个步骤的输出性能显著低于人类专家在给定相同输入时可能产生的输出。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/a96b64854059efd64a7937ba8c6d04fd_3.png"></p>
<p>我经常自己用电子表格来做这件事。我可能会建立这样一个电子表格:</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/a96b64854059efd64a7937ba8c6d04fd_3.png"></p>
<p>对于第一个查询“黑洞科学的最新发展”,我看到搜索词没问题,但搜索结果不佳,因为“博客文章、大众媒体文章太多,科学论文不足”。基于此,确实选出的五个最佳来源也不理想,但在这里我不会说“挑选五个最佳来源”这一步做得不好,因为如果筛选的输入文章本身都不够严谨,那么我不能责怪这一步没有选出更好的文章,因为它已经在给定的选择范围内尽力了。人类专家面对同样的选择列表可能也会如此。</p>
<p>然后,您可以为不同的提示重复此过程。例如,对于“在西雅图租房还是买房”这个提示,它可能遗漏了一个知名的关于水果采摘机器人的博客。在这种情况下,我们可能会查看并说:“哦,搜索词太宽泛了,搜索结果也不好”,等等。</p>
<p>基于此,我将在电子表格中统计在不同组件中观察到错误的频率。在这个例子中,我对搜索词不满意的情况占5%,但对搜索结果不满意的情况占45%。</p>
<p>如果我实际看到这个数据,我可能会仔细检查搜索词,以确保搜索词确实没问题,并且搜索词的选择不是导致搜索结果不佳的原因。但如果我确实认为搜索词没问题,而搜索结果不理想,那么我会仔细检查正在使用的网络搜索引擎,以及是否有任何参数可以调整,使其返回更相关或更高质量的结果。</p>
<p>正是这种类型的分析告诉我,在这个例子中,也许我应该将注意力集中在修复搜索结果上,而不是这个代理工作流的其他组件上。</p>
<h2 id="总结与优先级排序">总结与优先级排序</h2>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/a96b64854059efd64a7937ba8c6d04fd_5.png"></p>
<p>本节课中我们一起学习了错误分析。总结一下,我发现养成在构建代理工作流后查看追踪信息的习惯非常有用。主动查看中间输出,以感受每个步骤的实际执行情况,从而更好地理解不同步骤的性能优劣。</p>
<p>更系统化的错误分析可以通过电子表格来完成,让您收集统计数据或计算哪个组件最频繁地表现不佳。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/a96b64854059efd64a7937ba8c6d04fd_5.png"></p>
<p>查看哪些组件表现不佳,以及我对于有效改进不同组件是否有思路,这将帮助您确定改进的优先级。也许某个组件有问题,但我没有任何改进它的想法,这可能意味着不应将其优先级设得太高。但如果有一个组件产生了大量错误,并且我有改进它的思路,那么这就是优先处理该组件的一个充分理由。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/a96b64854059efd64a7937ba8c6d04fd_7.png"></p>
<p>我想强调的是,错误分析是帮助您决定工作重点的一个非常有用的产出。因为在任何复杂系统中,有太多可以改进的地方,很容易随便选一个点,然后投入数周甚至数月时间,最后才发现这并未带来系统整体性能的提升。因此,利用错误分析来决定工作重点,对于提高您的效率来说极其有用。</p>
<p>在本视频中,我们通过研究代理的示例探讨了错误分析。但我认为错误分析是一个如此重要的话题,我想再介绍一些额外的示例。所以,让我们进入下一个视频,在那里我们将查看更多错误分析的例子。</p>
<h1 id="020更多错误分析示例-">020:更多错误分析示例 🧐</h1>
<p>在本节课中,我们将学习如何通过具体的错误分析示例,来诊断和优化代理式AI工作流中的问题。我们将通过发票处理和客户邮件回复两个案例,演示如何定位导致系统性能不佳的根本原因。</p>
<p>上一节我们介绍了错误分析的基本概念,本节中我们来看看两个更具体的应用实例。</p>
<h2 id="发票处理工作流的错误分析">发票处理工作流的错误分析</h2>
<p>我们首先回顾一下发票处理的工作流。该流程遵循一个清晰的代理工作流:识别四个必需字段,然后将它们记录到数据库中。在本模块的第一个视频示例中,我们提到系统经常在发票的<strong>到期日期</strong>上出错。因此,我们可以进行错误分析,以找出问题可能出在哪个组件上。</p>
<p>例如,问题可能源于:</p>
<ul>
<li><strong>PDF转文本</strong>组件提取日期错误。</li>
<li>或者,<strong>大语言模型</strong>从PDF转文本组件输出的所有文本中提取了错误的日期。</li>
</ul>
<p>为了进行错误分析,我会尝试找出多个数据提取器出错的例子。和上一个视频一样,专注于那些性能不佳的示例以找出问题所在是很有用的。我会忽略那些日期正确的例子,但会找出大约10到20张日期错误的发票,然后逐一检查。</p>
<p>以下是分析步骤:</p>
<ol>
<li>判断问题是PDF转文本组件提取日期错误。</li>
<li>还是大语言模型在给定PDF转文本输出后,提取了错误的日期(例如,可能识别成了发票日期而非到期日期)。</li>
</ol>
<p>你可能会建立一个如下所示的简单电子表格,检查20张发票,并统计每种错误发生的频率。</p>
<table>
<thead>
<tr>
<th style="text-align: left">发票编号</th>
<th style="text-align: left">PDF转文本错误?</th>
<th style="text-align: left">LLM日期提取错误?</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left">1</td>
<td style="text-align: left">否</td>
<td style="text-align: left">是</td>
</tr>
<tr>
<td style="text-align: left">2</td>
<td style="text-align: left">是</td>
<td style="text-align: left">否</td>
</tr>
<tr>
<td style="text-align: left">...</td>
<td style="text-align: left">...</td>
<td style="text-align: left">...</td>
</tr>
<tr>
<td style="text-align: left">总计</td>
<td style="text-align: left">20%</td>
<td style="text-align: left">80%</td>
</tr>
</tbody>
</table>
<p>在这个假设的例子中,看起来<strong>大语言模型的日期提取</strong>导致了更多的错误。这告诉我,也许我应该把精力集中在改进日期提取组件上,而不是PDF转文本组件。</p>
<p>这一点很重要。因为如果没有这个错误分析,我设想有些团队可能会花费数周或数月的时间来调整PDF转文本组件,最终才发现这对整个系统的性能提升影响不大。另外,底部的百分比总和可能不是100%,因为这些错误并非互斥的。</p>
<h2 id="客户邮件回复工作流的错误分析">客户邮件回复工作流的错误分析</h2>
<p>让我们再看最后一个例子,回到回复客户邮件的HIV工作流。在这个流程中,大语言模型在收到客户关于订单的邮件后,会提取订单详情、从数据库获取信息,然后起草回复供人工审核。</p>
<p>同样,我会找出一些最终输出不满意的例子,然后尝试找出问题所在。</p>
<p>可能出现问题的地方包括:</p>
<ul>
<li>大语言模型生成了错误的数据库查询。当查询发送到数据库时,它未能成功获取客户信息。</li>
<li>数据库本身存在损坏的数据。因此,即使大语言模型生成了完全合适的数据库查询(例如用SQL),数据库也没有正确的信息。</li>
<li>或者,在获得了正确的客户订单信息后,大语言模型撰写的邮件在某些方面不太合适。</li>
</ul>
<p>再次,我会检查一批最终输出不满意的邮件,并尝试找出问题根源。</p>
<p>例如:</p>
<ul>
<li>在邮件1中,我们可能发现大语言模型在查询中请求了错误的表,即以错误的方式查询了数据库。</li>
<li>在邮件2中,我可能发现数据库实际上存在错误,并且大语言模型基于那个输入也写出了不太好的邮件。</li>
</ul>
<p>在这个例子中,在检查了许多邮件后,我可能发现最常见的错误在于大语言模型编写数据库查询(比如SQL查询)以获取相关信息的方式。而数据库本身大部分是正确的,只有少量数据错误。撰写邮件的方式也存在一些错误,可能在大约30%的情况下写得不太合适。</p>
<p>这告诉我,最值得投入精力的是改进大语言模型编写查询的方式。其次重要的是改进撰写最终邮件的提示。像这样的分析可以告诉你,系统可能75%的错误都源于数据库查询问题。这对于指导你在开发GenAI工作流时应将注意力集中在哪里,是极其宝贵的信息。</p>
<p>当我开发生成式AI工作流时,我经常使用这种类型的错误分析来告诉我应该优先改进哪个部分。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/1635fe8c194c9b31d64d46896ea7bca1_1.png"></p>
<p>在你做出这个决定后,事实证明,为了补充我们在本模块早期讨论的端到端评估,通常不仅评估整个端到端系统,也评估单个组件是很有用的。因为这可以使你更高效地改进错误分析后决定要重点关注的某个特定组件。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/1635fe8c194c9b31d64d46896ea7bca1_3.png"></p>
<p>本节课中我们一起学习了如何通过具体的错误分析案例,定位代理工作流中的瓶颈。我们看到了系统性地检查错误样本、归因问题组件,并据此确定优化优先级的过程。这能帮助我们避免在次要问题上浪费精力,从而更高效地提升系统整体性能。</p>
<h1 id="021组件级评估-">021:组件级评估 🧩</h1>
<p>在本节课中,我们将学习如何构建和使用组件级评估。我们将通过一个研究代理的例子,探讨为何仅依赖端到端评估可能效率低下,以及如何通过针对特定组件的评估来更高效地优化系统性能。</p>
<h2 id="概述-10">概述</h2>
<p>在之前的课程中,我们提到研究代理有时会遗漏关键信息。如果问题出在网络搜索组件上,那么每次我们更换搜索引擎或调整参数时,都需要重新运行整个工作流程来进行端到端评估。这种方法虽然能提供全面的性能指标,但成本高昂且效率低下。此外,由于整个工作流程较为复杂,其他组件引入的随机噪声可能会掩盖网络搜索组件本身的微小改进。因此,本节将介绍一种替代方案:构建专门的组件级评估。</p>
<h2 id="构建组件级评估">构建组件级评估</h2>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/a420c0efa67b2064c9fcbd12fbf977b1_1.png"></p>
<p>上一节我们介绍了端到端评估的局限性,本节中我们来看看如何为特定组件(如网络搜索)建立独立的评估体系。</p>
<p>核心思想是:为单个组件设计一个清晰、独立的度量标准,以便快速、准确地判断其性能变化,而无需运行整个复杂系统。</p>
<p>以下是构建网络搜索组件评估的具体步骤:</p>
<ol>
<li><strong>建立黄金标准资源列表</strong>:针对少量特定查询,邀请领域专家确定一组最权威的网页资源。这些资源被视为“黄金标准”,即一个理想的搜索应该找到这些页面。
<ul>
<li><strong>专家判断</strong>:<code>专家资源列表 = </code></li>
</ul>
</li>
<li><strong>编写评估代码</strong>:运行你的网络搜索组件,获取其返回的网页结果列表。
<ul>
<li><strong>组件输出</strong>:<code>搜索结果列表 = </code></li>
</ul>
</li>
<li><strong>计算标准指标</strong>:通过代码计算你的搜索结果与黄金标准资源列表之间的重叠程度。信息检索领域有标准的评估指标,例如<strong>F1分数</strong>,它综合了<strong>精确率</strong>和<strong>召回率</strong>。
<ul>
<li><strong>精确率</strong>:<code>(检索出的相关网页数量) / (检索出的全部网页数量)</code></li>
<li><strong>召回率</strong>:<code>(检索出的相关网页数量) / (全部相关网页数量)</code></li>
<li><strong>F1分数</strong>:<code>2 * (精确率 * 召回率) / (精确率 + 召回率)</code></li>
</ul>
</li>
</ol>
<p>通过这种方式,你便获得了一个专门用于评估网络搜索组件质量的工具。</p>
<h2 id="组件级评估的优势">组件级评估的优势</h2>
<p>拥有了组件级评估工具后,你可以在调整组件时获得更清晰的反馈信号。</p>
<ul>
<li><strong>快速迭代</strong>:当你调整网络搜索的参数或超参数时——例如更换搜索引擎(尝试Google、Bing、DuckDuckGo等)、改变返回结果数量或调整搜索日期范围——你可以快速运行组件级评估来判断质量是否提升。</li>
<li><strong>信号清晰</strong>:组件级评估能提供更清晰的改进信号,让你确切知道正在优化的组件(如网络搜索)是否有所改善,避免了端到端系统中其他复杂组件带来的噪声干扰。</li>
<li><strong>团队协作高效</strong>:在由不同团队负责不同组件的大型项目中,每个团队可以拥有自己明确优化的指标,而无需担心其他组件的影响。这使得团队能够更专注、更快速地解决各自范围内更具针对性的问题。</li>
</ul>
<p>当然,在最终完成工作前,运行一次端到端评估以确保整体系统性能得到提升仍然是必要的。但在逐个调整超参数的过程中,通过评估单个组件可以极大地提高效率,无需每次都重新运行昂贵的端到端评估。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/a420c0efa67b2064c9fcbd12fbf977b1_3.png"></p>
<h2 id="总结与过渡-1">总结与过渡</h2>
<p>本节课中我们一起学习了组件级评估的概念与构建方法。我们了解到,当决定改进某个组件时,考虑为其建立专门的组件级评估是值得的,这能让你更快地提升该组件的性能。</p>
<p>现在,你可能会想:如果决定改进一个组件,具体该如何让它变得更好呢?在下一个视频中,让我们来看一些具体的例子。🚀</p>
<h1 id="022如何解决已识别的问题-️">022:如何解决已识别的问题 🛠️</h1>
<p>在本节课中,我们将学习如何分析和改进代理工作流中的各个组件。我们将探讨针对不同类型组件的优化策略,并分享一些提升模型性能、降低成本和延迟的通用模式。</p>
<h2 id="概述-11">概述</h2>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/68a80ffba86acf660e9272bc3bce0bab_1.png"></p>
<p>一个代理工作流通常包含多种不同类型的组件。因此,改进不同组件的工具和方法也会有很大差异。接下来,我将分享一些在实践中观察到的通用模式。</p>
<h2 id="优化非llm组件">优化非LLM组件</h2>
<p>上一节我们介绍了代理工作流的构成,本节中我们来看看如何优化其中的非LLM组件。</p>
<p>你的代理工作流中可能包含一些非基于大语言模型的组件。例如,它可能是一个网络搜索引擎、一个文本检索组件(如果你的系统包含检索增强生成功能)、一个代码执行器、一个单独训练的机器学习模型,或者是一个语音识别或图片人物检测系统。</p>
<p>这些非LLM组件通常有可以调整的参数或超参数。以下是几个例子:</p>
<ul>
<li>对于网络搜索引擎,你可以调整返回结果的数量或要求其考虑的日期范围。</li>
<li>对于文本检索组件,你可以更改决定文本相似度的相似度阈值,或者调整分块大小(检索系统通常会将文本切分成更小的块进行匹配)。</li>
<li>对于人物检测,你可以更改检测阈值,这会影响其敏感度以及判定“发现人物”的可能性,从而在误报和漏报之间进行权衡。</li>
</ul>
<p>如果你没有完全理解上述所有超参数的细节,不必担心,具体细节并不那么重要。关键在于,这些组件通常都有可以调整的参数。当然,你也可以尝试直接替换组件。我在自己的代理工作流中经常这样做,例如更换不同的检索搜索引擎或RAG提供商,以测试其他提供商是否会因为其多样性而表现更好。</p>
<p>鉴于非LLM组件的多样性,改进它们的技术也将更加多样化,并高度依赖于该组件的具体功能。</p>
<h2 id="优化llm组件">优化LLM组件</h2>
<p>在讨论了非LLM组件的优化后,现在我们将焦点转向基于大语言模型的组件。以下是你可以考虑的一些选项:</p>
<ul>
<li><strong>改进提示词</strong>:尝试添加更明确的指令。如果你了解<strong>小样本提示</strong>,它指的是在提示中添加一个或多个输入和期望输出的具体示例。这是一种可以为你的LLM提供示例,从而帮助其生成更好性能输出的技术。</li>
<li><strong>尝试不同的LLM</strong>:使用AI套件或其他工具,尝试多个LLM模型并利用评估来选择最适合你应用的模型,这通常相当容易。</li>
<li><strong>任务分解</strong>:如果一个步骤对单个LLM来说过于复杂,你可以考虑将任务分解为更小的步骤,或者将其分解为一个生成步骤和一个反思步骤。更一般地说,如果一个步骤内的指令非常复杂,单个LLM可能难以遵循所有指令。将任务分解为更小的步骤,可能更容易让两到三次LLM调用准确执行。</li>
<li><strong>微调模型</strong>:当其他方法效果不够好时,可以考虑微调模型。这往往比其他选项复杂得多,在开发时间上的成本也更高。但如果你有可用于微调LLM的数据,这可能比仅使用提示词带来更好的性能。我倾向于在真正用尽其他选项后才进行微调,因为它通常很复杂。但对于那些尝试了所有其他方法后,性能仍停留在90%或95%,而我确实需要提升最后几个百分点的情况,微调我自己的定制模型有时是一个很好的技术。由于其成本高昂,我倾向于只在更成熟的应用中这样做。</li>
</ul>
<h2 id="培养模型选择直觉">培养模型选择直觉</h2>
<p>事实证明,当你尝试选择使用哪个LLM时,如果你对不同大语言模型的智能程度或能力有良好的直觉,这对开发者非常有帮助。你可以做的就是尝试很多模型,看看哪个效果最好。我发现,随着使用不同模型工作,我开始磨练出关于哪些模型最适合哪些类型任务的直觉。随着这些直觉的磨练,你也能更高效地为模型编写好的提示词,并为你的任务选择合适的模型。</p>
<p>因此,我想与你分享一些关于如何磨练直觉,以判断哪些模型适合你应用的想法。让我们用一个例子来说明:使用LLM遵循指令来移除或编辑PII(个人可识别信息),以保护私人敏感信息。</p>
<p>例如,如果你使用LLM来总结客户通话记录,那么一个摘要可能是:“在2023年7月14日,Jessica Alvarez(社会安全号码XXX-XX-XXXX)就支持工单#12345联系了我们,她的地址是...”</p>
<p>这段文本包含大量敏感的个人可识别信息。现在,假设我们想从这些摘要中移除所有PII,因为我们希望将这些数据用于下游统计分析,以了解客户来电原因,并且为了保护客户信息,我们希望在进行分析前剥离这些PII。</p>
<p>你可能会这样提示LLM:“识别以下文本中的所有PII案例,然后返回编辑后的文本,用<code>[已编辑]</code>替换...”</p>
<p>事实证明,较大的前沿模型往往更擅长遵循指令,而较小的模型虽然擅长回答简单的事实性问题,但在遵循指令方面就不那么出色。如果你在一个较小的模型(例如具有80亿参数的OpenAI o1模型)上运行这个提示,它可能会生成如下输出:</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/68a80ffba86acf660e9272bc3bce0bab_3.png"></p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/68a80ffba86acf660e9272bc3bce0bab_4.png"></p>
<blockquote>
<p>识别出的PII是:社会安全号码和地址。编辑如下:[已编辑]...</p>
</blockquote>
<p>这里它犯了几个错误:没有正确遵循指令(先显示了列表,然后编辑文本,然后又返回了一个本不该出现的列表);在这个PII列表中漏掉了姓名;并且我认为它也没有编辑部分地址。细节可能有所不同,但它没有完美遵循这些指令,并且可能遗漏了一些PII。</p>
<p>相比之下,如果你使用一个更智能、更擅长遵循指令的模型,你可能会得到更好的结果,例如它正确地列出了所有PII,并正确地编辑了所有PII。</p>
<p>我发现,不同的LLM提供商在不同任务上各有专长,不同的模型确实更适合不同的任务:有些更擅长编码,有些更擅长遵循指令,有些在某些特定类型的事实上表现更好。你可以磨练自己的直觉,了解哪些模型智能程度更高或更低,以及它们更擅长或更不擅长遵循哪些指令,从而能够更好地决定使用哪些模型。</p>
<p>以下是一些关于如何做到这一点的建议:</p>
<ul>
<li><strong>经常尝试不同模型</strong>:每当有新模型发布,我经常去尝试,并在上面测试不同的查询,包括专有模型和开源模型。</li>
<li><strong>建立个人评估集</strong>:有时,拥有一套个人评估集也很有用,即你经常询问不同模型的一些特定问题,这可以帮助你校准它们在不同类型任务上的表现。</li>
<li><strong>阅读他人的提示词</strong>:我经常做的一件事是花大量时间阅读他人的提示词。有时人们会在互联网上发布他们的提示词,我经常去阅读,以了解提示词的最佳实践是什么。我也经常与各个公司的朋友(包括一些前沿模型公司)交流,分享我的提示词,看看他们是如何编写提示词的。有时,我还会去找我尊敬的人编写的开源软件包,下载并深入研究,以找到作者编写的提示词,通过阅读它们来磨练我关于如何编写好提示词的直觉。我鼓励你考虑这种技术:通过阅读大量他人的提示词,这将帮助你更好地自己编写提示词。我经常这样做,也鼓励你这样做。这将磨练你的直觉,了解模型擅长遵循哪些类型的指令,以及何时对不同的模型说某些话。</li>
<li><strong>在工作流中尝试多种模型</strong>:除了尝试模型和阅读他人的提示词,如果你在代理工作流中尝试许多不同的模型,这也能让你磨练直觉。你会看到哪些模型在哪些类型的任务上表现最好,无论是通过查看追踪记录获得非正式的感知,还是通过查看组件级或端到端的评估,都能帮助你评估不同模型在工作流中的表现。然后,你开始磨练关于性能、价格和速度之间权衡的直觉,以便为不同模型的使用做出决策。我倾向于在AI套件上开发代理工作流的原因之一,就是因为它可以让我轻松快速地更换和尝试不同的模型,这使我在尝试和评估哪些模型最适合我的工作流方面更有效率。</li>
</ul>
<h2 id="优化成本与延迟">优化成本与延迟</h2>
<p>我们已经讨论了很多关于如何改进不同组件的性能,以期提升端到端系统整体表现的方法。除了提高输出质量,在你的工作流中,你可能还想优化延迟和成本。</p>
<p>我发现,对于很多团队来说,开始开发时通常最关心的是输出质量是否足够高。但当系统运行良好并投入生产后,使其运行得更快、成本更低也往往很有价值。</p>
<p>因此,在下一个视频中,让我们看看一些关于改进代理应用成本和延迟的想法。</p>
<h2 id="总结-5">总结</h2>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/68a80ffba86acf660e9272bc3bce0bab_6.png"></p>
<p>本节课中我们一起学习了如何分析和优化代理工作流中的各个组件。我们探讨了针对非LLM组件(如调整参数或更换提供商)和LLM组件(如改进提示词、更换模型、任务分解和微调)的不同策略。我们还讨论了如何通过频繁尝试不同模型、阅读他人提示词以及在具体工作流中测试来培养模型选择的直觉。最后,我们提到了在确保质量后,优化系统延迟和成本的重要性。掌握这些方法将帮助你构建更高效、更经济的智能代理系统。</p>
<h1 id="023延迟与成本优化-">023:延迟与成本优化 🚀</h1>
<p>在本节课中,我们将学习如何优化代理工作流的延迟与成本。我们将探讨如何通过基准测试和分析,识别并改进工作流中耗时或成本高昂的环节。</p>
<hr>
<p>当构建代理工作流时,通常建议团队首先专注于提升输出质量,之后再优化成本和延迟。成本和延迟并非不重要,但提升性能或输出质量通常是最困难的部分。只有当工作流真正有效运行时,才应开始关注其他方面。</p>
<p>我曾多次遇到这样的情况:团队构建了一个代理工作流并交付给用户,幸运的是用户数量庞大,导致成本实际上成为了问题,于是我们不得不紧急采取措施降低成本。但这本身是一个“好问题”。因此,我倾向于不过早担心成本问题,但也不会完全忽视它。在我的待办事项列表中,它的优先级较低,直到用户数量多到确实需要降低人均成本时才会重点关注。对于延迟,我也会有所顾虑,但同样不如确保输出质量高那么重要。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/ca20e2f35d13fc909e45f8aa0e57d0e8_1.png"></p>
<p>然而,当工作流达到一定规模时,拥有优化延迟和成本的工具将非常有用。让我们看看一些实现方法。</p>
<h2 id="优化延迟-️">优化延迟 ⏱️</h2>
<p>如果你想优化代理工作流的延迟,我通常会做的一件事是对工作流进行基准测试或计时。</p>
<p>以这个研究代理为例,它包含多个步骤。如果我对每个步骤计时,可能会发现:生成搜索查询耗时7秒,网络搜索耗时5秒,读取网页耗时63秒,总结内容耗时11秒,撰写最终文章平均耗时18秒。</p>
<p>通过查看这个整体时间线,我可以了解哪些组件最有提速空间。在这个例子中,或许可以尝试多种方法。如果你尚未利用某些步骤的并行性,例如获取网页,或许值得考虑并行执行其中一些操作。或者,如果你发现某些语言模型调用耗时过长——比如第一步耗时7秒,最后一步耗时18秒——我可能会考虑尝试使用更小、或许智能度稍低的模型,看看它是否仍能满足需求,或者寻找能提供更快响应的语言模型供应商。</p>
<p>许多API提供商提供不同的模型接口,一些公司拥有专用硬件,能够以更快的速度提供某些模型服务。因此,有时尝试不同的提供商,看看哪个能最快地返回结果,是值得的。至少,进行这种时间分析可以让你明确应该集中精力优化哪些组件以减少延迟。</p>
<h2 id="优化成本-">优化成本 💰</h2>
<p>在优化成本方面,可以进行类似的计算,即计算每个步骤的成本,这也能让你进行基准测试并决定应关注哪些步骤。</p>
<p>许多语言模型提供商根据输入和输出的令牌数量收费。许多API提供商按API调用次数收费。计算步骤的成本可能因服务器容量付费方式和服务成本而异。</p>
<p>对于这样一个流程,你可能会在这个例子中决定:此步骤的令牌平均每个成本0.004美分,网络搜索API可能花费1.6美分,读取网页API成本这么多,文本处理成本这么多,最终文章生成的令牌成本这么多。这同样可以让你了解,是否有更便宜的组件或模型可以使用,从而找到优化成本的最大机会。</p>
<p>我发现这些基准测试练习通常能带来很大启发,有时能清晰地告诉我某些组件根本不值得担心,因为它们对成本或延迟的贡献并不显著。因此,我发现当成本或延迟成为问题时,简单地测量每个步骤的成本和/或延迟,通常能为你提供一个决策基础,以确定应优先优化哪些组件。</p>
<hr>
<h2 id="总结--1">总结 📝</h2>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/ca20e2f35d13fc909e45f8aa0e57d0e8_3.png"></p>
<p>本节课中,我们一起学习了代理工作流中延迟与成本的优化策略。我们了解到,在开发初期应优先保证输出质量,待工作流稳定运行后,再通过基准测试和分析来识别并优化高延迟或高成本的环节。通过计时和成本计算,我们可以明确工作流中的瓶颈,并采取相应措施,如利用并行处理、尝试不同模型或供应商,以实现更高效、更经济的系统运行。</p>
<p>我们即将结束本模块的学习。感谢你坚持学习,让我们进入本模块的最后一个视频进行总结。</p>
<h1 id="024规划工作流-">024:规划工作流 🧠</h1>
<h2 id="概述-12">概述</h2>
<p>在本节课中,我们将要学习一种名为“规划”的设计模式。这种模式能让您构建高度自主的智能体,无需预先硬编码执行步骤的固定顺序。智能体可以更灵活地自行决定需要采取哪些步骤来完成一项任务。我们将通过两个具体示例来理解规划模式的工作原理。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/958c51a720d74f4abf9952f5dcb2eb6f_1.png"></p>
<h2 id="规划模式简介">规划模式简介</h2>
<p>上一节我们介绍了构建自主智能体的目标。本节中我们来看看实现这一目标的关键模式之一:规划。规划模式的核心思想是,让大型语言模型(LM)先制定一个多步骤的计划,然后逐步执行该计划,而不是直接执行最终任务。</p>
<h2 id="示例一客户服务智能体">示例一:客户服务智能体</h2>
<p>假设您经营一家太阳镜零售店,库存信息存储在数据库中。您希望有一个客户服务智能体来回答诸如“你们有100美元以下的圆形太阳镜库存吗?”这样的复杂查询。</p>
<p>为了处理这类查询,我们需要为LM提供一组工具,例如:</p>
<ul>
<li><code>get_item_descriptions</code>:获取商品描述。</li>
<li><code>check_inventory</code>:检查库存。</li>
<li><code>get_item_price</code>:获取商品价格。</li>
</ul>
<p>以下是构建此类智能体的关键步骤:</p>
<ol>
<li>
<p><strong>生成计划</strong>:首先,我们提示LM根据用户请求生成一个分步计划。提示词可能如下:</p>
<pre><code>你可以使用以下工具:[工具列表]。请返回一个分步计划来执行用户的请求。
</code></pre>
<p>对于上述查询,LM可能输出的合理计划是:</p>
<ul>
<li>步骤1:使用 <code>get_item_descriptions</code> 查找圆形太阳镜。</li>
<li>步骤2:使用 <code>check_inventory</code> 检查找到的太阳镜是否有库存。</li>
<li>步骤3:使用 <code>get_item_price</code> 检查库存中的太阳镜价格是否低于100美元。</li>
</ul>
</li>
<li>
<p><strong>执行计划</strong>:生成计划后,我们引导LM逐步执行。</p>
<ul>
<li>我们将<strong>步骤1</strong>的文本(例如“使用 <code>get_item_descriptions</code> 查找圆形太阳镜”)连同用户查询和工具背景信息一起输入给LM,让它执行第一步操作。</li>
<li>LM调用相应工具(<code>get_item_descriptions</code>)并获得结果(例如,找到两款圆形太阳镜)。</li>
<li>接着,我们将<strong>步骤2</strong>的文本和<strong>步骤1的输出结果</strong>一起输入给LM,让它执行第二步(检查这两款太阳镜的库存)。</li>
<li>同理,用<strong>步骤3</strong>的文本和<strong>步骤2的输出结果</strong>驱动LM执行第三步(检查价格)。</li>
<li>最后,将所有步骤的结果汇总,让LM生成最终答案回复给用户。</li>
</ul>
</li>
</ol>
<p>这种方法的优势在于,开发者无需预先决定调用工具的确切顺序。对于不同的用户请求(例如“我想退回之前购买的金框眼镜,但不是金属框的那副”),LM可以动态生成不同的执行计划。</p>
<h2 id="示例二邮件助手智能体">示例二:邮件助手智能体</h2>
<p>让我们再看一个规划模式的例子:邮件助手。如果您想让它“回复Bob关于纽约晚宴邀请的邮件,然后将其归档”,我们可以为它提供以下工具:</p>
<ul>
<li><code>search_email</code>:搜索邮件。</li>
<li><code>send_email</code>:发送邮件。</li>
<li><code>move_email</code>:移动邮件。</li>
</ul>
<p>以下是处理流程:</p>
<ol>
<li>
<p><strong>生成计划</strong>:LM针对该请求可能生成如下计划:</p>
<ul>
<li>步骤1:使用 <code>search_email</code> 查找来自Bob关于纽约晚宴的邮件。</li>
<li>步骤2:生成并发送确认出席的回复邮件。</li>
<li>步骤3:将该邮件移动到归档文件夹。</li>
</ul>
</li>
<li>
<p><strong>执行计划</strong>:与上一个示例类似,系统会引导LM依次执行这三个步骤,每一步都使用上一步的输出作为上下文。</p>
</li>
</ol>
<h2 id="规划模式的应用与挑战">规划模式的应用与挑战</h2>
<p>规划模式已在许多高度自主的编码系统中成功应用。例如,当要求AI编写一个复杂应用程序时,它可能会先规划出需要构建的各个组件,形成一个检查清单,然后逐一完成。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/958c51a720d74f4abf9952f5dcb2eb6f_3.png"></p>
<p>然而,规划模式的应用目前在某些领域仍处于实验阶段,尚未广泛普及。它面临的一个挑战是可能使系统更难控制,因为开发者在运行时无法确切知道智能体会制定出什么样的计划。</p>
<p>尽管如此,规划是一项令人兴奋的技术,它使智能体无需为复杂任务硬编码精确的步骤序列。随着技术发展,我们将在越来越多的应用中看到它的身影。</p>
<h2 id="总结-6">总结</h2>
<p>本节课中我们一起学习了<strong>规划设计模式</strong>。我们了解到,通过让大型语言模型先<strong>制定分步计划</strong>,再<strong>逐步执行该计划</strong>,可以构建出能够灵活处理复杂、多步骤任务的自主智能体。我们通过客户服务和邮件助手两个示例,具体分析了该模式的工作流程:<code>生成计划 -> 执行步骤1 -> 执行步骤2 -> ... -> 生成最终输出</code>。虽然规划模式赋予了系统更大的灵活性,但它也带来了可控性方面的挑战。在接下来的视频中,我们将更深入地探讨这些计划的具体形式以及如何将它们串联执行。</p>
<h1 id="025创建与执行llm计划">025:创建与执行LLM计划</h1>
<p>在本节课中,我们将详细探讨如何提示大型语言模型(LLM)生成计划,以及如何读取、解释并执行该计划。让我们开始吧。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/b113e96d0e9efc28097e6dbb9dea7505_1.png"></p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/b113e96d0e9efc28097e6dbb9dea7505_1.png"></p>
<h2 id="生成清晰的计划格式">生成清晰的计划格式</h2>
<p>上一节我们介绍了客户服务代理的示例计划,该计划使用了简单的文本描述进行高层级展示。本节中我们来看看如何让LLM编写更清晰、更详细的计划,而不仅仅是简单的高层文本描述。</p>
<p>许多开发者会要求LLM将计划格式化为JSON格式,以便执行。因为JSON格式允许下游代码以相对清晰、无歧义的方式解析计划的各个步骤。尽管目前领先的LLM在生成JSON输出方面表现良好,但系统提示词可以这样设计:</p>
<pre><code class="language-json">{
"system_prompt": "你拥有访问以下工具的权限:[工具列表]。请创建一个JSON格式的逐步计划。"
}
</code></pre>
<p>开发者需要足够详细地描述JSON格式,以引导模型输出类似右侧所示的计划结构。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/b113e96d0e9efc28097e6dbb9dea7505_3.png"></p>
<h2 id="json计划结构解析">JSON计划结构解析</h2>
<p>以下是JSON输出结构的一个示例。它创建了一个列表,其中第一个列表项包含清晰的键值对。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/b113e96d0e9efc28097e6dbb9dea7505_3.png"></p>
<pre><code class="language-json">{
"plan": [
{
"step": 1,
"description": "计划第一步的描述",
"tool": "要使用的工具名称",
"arguments": "传递给该工具的参数"
},
{
"step": 2,
"description": "计划第二步的描述",
"tool": "要使用的工具名称",
"arguments": "传递给该工具的参数"
}
]
}
</code></pre>
<p>与用英语书写计划相比,这种JSON格式允许下游代码更清晰地解析计划的每一步,从而能够可靠地逐步执行。</p>
<h2 id="其他计划格式选择">其他计划格式选择</h2>
<p>除了JSON,一些开发者也会使用XML。你可以使用XML分隔符或标签来明确指定计划的步骤及其编号。</p>
<pre><code class="language-xml"><plan>
<step number="1">
<description>第一步描述</description>
<tool>工具名</tool>
<arguments>参数</arguments>
</step>
</plan>
</code></pre>
<p>我感觉使用Markdown的开发者较少,因为它在如何解析方面有时略显模糊。而纯文本可能是这些选项中最不可靠的。但我认为,无论是这里展示的JSON还是XML,都是让LLM格式化计划的良好选择,可以确保计划明确无误。</p>
<h2 id="执行json计划">执行JSON计划</h2>
<p>通过以JSON格式生成计划,你可以解析它,并让下游工作流更系统化地执行计划的不同步骤。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/b113e96d0e9efc28097e6dbb9dea7505_5.png"></p>
<h2 id="进阶思路用代码表达计划">进阶思路:用代码表达计划</h2>
<p>在向LLM提供计划方面,还有一个非常巧妙的想法,可以让LLM输出非常复杂的计划并确保其可靠执行,那就是让LLM编写代码,并用代码来表达计划。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/b113e96d0e9efc28097e6dbb9dea7505_5.png"></p>
<p>我们将在下一个视频中详细探讨这个思路。</p>
<h2 id="总结-7">总结</h2>
<p>本节课中我们一起学习了如何引导LLM生成清晰的计划,重点介绍了使用JSON格式来结构化计划,以便于下游代码解析和执行。我们还简要了解了XML作为替代格式,并预告了让LLM通过编写代码来表达复杂计划的进阶方法。掌握这些格式和技巧,将帮助你构建更可靠、更易执行的AI代理工作流。</p>
<h1 id="026使用代码执行进行规划-">026:使用代码执行进行规划 🧠</h1>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/5b4488851ca69ac5078fcca76801e61e_1.png"></p>
<p>在本节课中,我们将要学习一种强大的代理式AI规划技术:<strong>使用代码执行进行规划</strong>。我们将探讨其核心思想、适用场景、优势以及实现方式。</p>
<hr>
<h2 id="概述-13">概述</h2>
<p>传统的AI规划方式可能要求模型以JSON等格式逐步生成计划。然而,一种更高效的方法是让大型语言模型直接编写代码来制定并执行计划。这种方法允许模型通过代码捕获多步骤计划,并通过执行生成的代码来完成复杂任务。</p>
<p>上一节我们介绍了基础的规划概念,本节中我们来看看如何利用代码执行来实现更强大的规划能力。</p>
<hr>
<h2 id="为何使用代码执行进行规划">为何使用代码执行进行规划?</h2>
<p>假设你需要构建一个系统,用于回答关于咖啡机销售数据的问题。数据存储在一个类似下图的电子表格中。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/5b4488851ca69ac5078fcca76801e61e_3.png"></p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/5b4488851ca69ac5078fcca76801e61e_1.png"></p>
<p>你可能会为模型提供一系列工具函数来处理数据,例如:</p>
<ul>
<li><code>get_column_max</code>:获取某列的最大值。</li>
<li><code>get_column_mean</code>:获取某列的平均值。</li>
<li><code>filter_rows</code>:根据条件筛选行。</li>
</ul>
<p>以下是这些工具函数的示例代码:</p>
<pre><code class="language-python"># 示例工具函数
def get_column_max(dataframe, column_name):
return dataframe.max()
def filter_rows(dataframe, condition):
return dataframe.query(condition)
</code></pre>
<p>如果用户提问:“哪个月份的热巧克力销售额最高?”,使用上述工具回答会非常复杂。你需要:</p>
<ol>
<li>用 <code>filter_rows</code> 筛选出一月份所有热巧克力的交易。</li>
<li>对这些交易进行统计。</li>
<li>对二月份重复步骤1和2。</li>
<li>对三月份重复...</li>
<li>...一直重复到十二月。</li>
<li>最后,从所有月份的结果中找出最大值。</li>
</ol>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/5b4488851ca69ac5078fcca76801e61e_5.png"></p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/5b4488851ca69ac5078fcca76801e61e_6.png"></p>
<p>这个过程不仅繁琐,而且当用户提出新问题时,例如“上周有多少笔独特的交易?”,现有的工具可能无法直接回答。这通常导致开发者需要不断创建新的、更具体的工具函数来覆盖各种边缘情况,效率低下。</p>
<hr>
<h2 id="更好的方法让模型编写代码">更好的方法:让模型编写代码</h2>
<p>与其提供大量特定工具,不如直接提示模型:“请编写代码来解决用户的问题,并将答案以Python代码形式返回。”</p>
<p>例如,你可以使用这样的提示词:</p>
<pre><code class="language-python">prompt = f"""
请编写Python代码来解决用户查询。
将你的代码包裹在 <execute> 和 </execute> 标签中。
用户查询:{user_query}
可用数据:coffee_sales.csv
"""
</code></pre>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/5b4488851ca69ac5078fcca76801e61e_8.png"></p>
<p>模型可能会生成如下代码:</p>
<pre><code class="language-python">import pandas as pd
# 加载数据
df = pd.read_csv('coffee_sales.csv')
# 确保日期列格式正确
df['date'] = pd.to_datetime(df['date'])
# 按日期排序
df_sorted = df.sort_values('date')
# 选择最后五笔交易
last_five = df_sorted.tail(5)
# 仅显示价格列
result = last_five[['price']]
print(result)
</code></pre>
<p>在这段代码中,模型实际上制定了一个清晰的计划:</p>
<ol>
<li>加载CSV文件。</li>
<li>解析日期列。</li>
<li>按日期排序数据。</li>
<li>选择最后5行。</li>
<li>提取价格列并输出。</li>
</ol>
<p>通过使用像Python(及Pandas库)这样的编程语言,模型可以利用其训练数据中见过的成百上千个内置函数来组合成计划,从而灵活应对各种复杂查询。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/5b4488851ca69ac5078fcca76801e61e_10.png"></p>
<p>对于“上周有多少笔独特交易?”这样的问题,模型同样可以生成一个包含多个步骤(如读取数据、定义时间窗口、筛选行、去重、计数)的代码计划来直接解决。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/5b4488851ca69ac5078fcca76801e61e_11.png"></p>
<hr>
<h2 id="优势与注意事项">优势与注意事项</h2>
<p><strong>核心优势</strong>:</p>
<ul>
<li><strong>表达能力强</strong>:代码可以简洁地表达包含多步骤和复杂逻辑的计划。</li>
<li><strong>利用现有知识</strong>:模型可以利用其对编程语言和常用库(如Pandas、NumPy)的丰富知识。</li>
<li><strong>减少工具开发</strong>:无需为每个特定任务预先构建大量专用工具。</li>
</ul>
<p><strong>重要注意事项</strong>:</p>
<ul>
<li><strong>安全执行环境</strong>:必须在一个安全的沙箱环境中执行模型生成的代码,以防止恶意或错误代码对主系统造成损害。这是一个关键的安全考量。</li>
<li><strong>适用场景</strong>:此方法最适合那些本质上可以通过编写代码来解决的任务,例如数据分析、文件处理、计算等。</li>
</ul>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/5b4488851ca69ac5078fcca76801e61e_13.png"></p>
<hr>
<h2 id="效果对比">效果对比</h2>
<p>根据相关研究(如Xyao Wang等人的工作),在许多任务上,让模型“编写代码作为行动”的方法,其性能优于让模型“编写JSON计划”或“编写纯文本计划”。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/5b4488851ca69ac5078fcca76801e61e_15.png"></p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/5b4488851ca69ac5078fcca76801e61e_13.png"></p>
<p>图表显示,<strong>代码作为行动 > JSON计划 > 文本计划</strong>。当然,对于需要集成特定自定义工具的应用,编写代码可能不是唯一选择,但在适用的情况下,它是一种非常强大的规划表达方式。</p>
<hr>
<h2 id="总结与展望-4">总结与展望</h2>
<p>本节课中我们一起学习了<strong>使用代码执行进行规划</strong>这一设计模式。我们了解到:</p>
<ol>
<li><strong>核心思想</strong>:让大型语言模型通过编写可执行代码来表达和实现复杂计划,而非逐步输出结构化指令。</li>
<li><strong>适用场景</strong>:尤其适合数据处理、自动化脚本等可通过编程解决的任务。</li>
<li><strong>关键优势</strong>:极大地扩展了模型的计划能力,减少了为每个功能开发专用工具的需要。</li>
<li><strong>重要前提</strong>:必须在安全的沙箱环境中执行生成的代码,并评估其任务适用性。</li>
</ol>
<p>目前,这一技术在最先进的<strong>智能编程助手</strong>中得到了卓越应用。这些助手能够为编写复杂软件制定详细计划(如先构建A模块,再构建B模块,然后进行集成测试),并逐步执行该计划。</p>
<p>尽管在编程领域之外,规划技术的应用仍在发展和探索中,并且放弃部分控制权以换取模型更强的自主性也需要权衡,但这无疑是一项重要且前沿的技术,有望在未来解决更广泛的问题。</p>
<p>这节关于规划的内容就到此结束。在本模块中,最后一个我希望与你分享的设计模式是:<strong>如何构建多智能体系统</strong>。在这种系统中,并非只有一个智能体,而是多个智能体协同工作以完成任务。让我们在下一个视频中一探究竟。</p>
<h1 id="027多智能体工作流-">027:多智能体工作流 🚀</h1>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/8ac156b7624048993837508c3d5b8670_1.png"></p>
<p>在本节课中,我们将要学习如何构建多智能体系统,让多个AI智能体协同工作,以完成复杂的任务。我们将探讨多智能体系统的设计理念、构建方法以及不同的协作模式。</p>
<h2 id="概述-14">概述</h2>
<p>之前我们讨论了如何构建单个智能体来完成任务。在多智能体工作流中,我们将拥有一组智能体,它们通过协作来为你完成工作。这类似于在软件开发中将任务分解为多个进程或线程,或者在现实世界中组建一个各司其职的团队来完成复杂项目。</p>
<h2 id="为什么需要多智能体系统">为什么需要多智能体系统?</h2>
<p>有些人初次听说多智能体系统时会疑惑:为什么需要多个智能体?我反复提示同一个大语言模型,使用同一台计算机,不就可以了吗?</p>
<p>一个有用的类比是:尽管我们在一台计算机上工作,但我们通常会将工作分解为多个进程或线程。作为开发者,思考如何将工作分解为多个进程或程序来运行,会使编写代码变得更加容易。同样地,面对复杂任务时,与其思考如何雇佣一个人来完成,不如考虑雇佣一个由不同角色组成的团队来分别处理任务的各个部分。</p>
<p>在实践中,对于许多代理式系统的开发者来说,一个有效的思维框架是:不要问“我应该雇佣哪一个人来做这件事?”,而是问“雇佣哪三四个不同角色的人来共同完成这个整体任务更有意义?”这提供了一种将复杂事物分解为子任务,并逐一为这些子任务构建解决方案的方法。</p>
<h2 id="多智能体工作流实例创建营销材料">多智能体工作流实例:创建营销材料</h2>
<p>让我们通过一个具体例子来看看这是如何运作的。假设任务是创建营销材料,例如为一款太阳镜制作营销宣传册。</p>
<p>一个自然的团队分工可能包括:</p>
<ul>
<li><strong>研究员</strong>:负责研究太阳镜市场趋势和竞争对手的产品。</li>
<li><strong>平面设计师</strong>:负责制作图表或精美的太阳镜图片。</li>
<li><strong>文案撰写人</strong>:负责整合研究报告和设计素材,撰写一份美观的宣传册。</li>
</ul>
<p>以下是这些角色可能承担的具体任务:</p>
<ul>
<li><strong>研究员</strong>:分析市场趋势,研究竞争对手。在设计研究员智能体时,需要考虑它需要哪些工具来完成研究报告。一个自然的工具是<strong>网络搜索</strong>,就像人类研究员需要上网搜索一样。</li>
<li><strong>平面设计师</strong>:创建视觉艺术品。这个智能体可能需要<strong>图像生成和处理的API</strong>,或者像之前咖啡机例子中那样,需要<strong>代码执行</strong>能力来生成图表。</li>
<li><strong>文案撰写人</strong>:将研究和报告文本转化为营销文案。在这种情况下,除了大语言模型本身生成文本的能力外,它可能不需要其他特殊工具。</li>
</ul>
<p>在接下来的讲解中,我们将用紫色方框代表一个智能体。构建单个智能体的方法是通过提示大语言模型来扮演特定角色(如研究员、设计师或撰写人)。例如,对于研究员智能体,你可以这样提示:<br>
<code>你是一个研究员智能体,负责分析太阳镜产品的市场趋势和竞争对手。请进行在线研究,分析太阳镜产品的市场趋势,并总结竞争对手的动态。</code></p>
<p>类似地,通过提示大语言模型扮演平面设计师(配备相应工具)和文案撰写人,你就可以构建出这些智能体。</p>
<h2 id="智能体协作模式">智能体协作模式</h2>
<p>构建好这三个智能体后,让它们协同工作以生成最终报告的一种方式是采用<strong>线性顺序工作流</strong>。</p>
<p>例如,要创建太阳镜的夏季营销活动:</p>
<ol>
<li>你将任务提示给<strong>研究员智能体</strong>。</li>
<li>研究员生成一份报告,内容为“当前太阳镜趋势与竞品分析”。</li>
<li>将这份研究报告传递给<strong>平面设计师智能体</strong>。设计师根据研究发现的数据,创建一些数据可视化和艺术设计方案。</li>
<li>将所有素材传递给<strong>文案撰写人智能体</strong>。撰写人整合研究和图形输出,撰写最终的营销宣传册。</li>
</ol>
<p>以这种方式构建多智能体工作流的优势在于,设计研究员、设计师或撰写人时,你可以一次专注于一件事。你可以花时间构建最好的平面设计师智能体,而你的合作者可以同时构建研究员和撰写人智能体,最后再将它们串联起来,形成这个多智能体系统。在某些情况下,开发者开始复用一些智能体。例如,构建了一个用于营销宣传册的平面设计师后,可以考虑将其构建得更通用,使其也能帮助撰写社交媒体帖子和网页插图。</p>
<h2 id="更复杂的协作管理者智能体">更复杂的协作:管理者智能体</h2>
<p>上面展示的是一个线性计划,即研究员、设计师、撰写人依次工作。除了线性计划,智能体之间还可以以更复杂的方式互动。</p>
<p>让我用一个例子来说明涉及多个智能体的规划。之前我们看到了如何给一个大语言模型一套工具来执行不同任务。而在这里,我们将给一个大语言模型调用不同智能体的选项,让它请求不同智能体帮助完成不同任务。</p>
<p>具体来说,你可以写一个这样的提示:<br>
<code>你是营销经理,拥有以下团队智能体可供调用:[此处描述研究员、设计师、撰写人智能体]。</code><br>
这与我们进行规划和工具调用的过程非常相似,只是绿色的“工具”框被紫色的“智能体”框所取代。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/8ac156b7624048993837508c3d5b8670_3.png"></p>
<p>然后,我们要求它返回一个分步计划来执行用户的请求。在这种情况下,它可能会:</p>
<ol>
<li>要求研究员研究当前太阳镜趋势并报告。</li>
<li>要求平面设计师创建图像并报告。</li>
<li>要求文案撰写人创建报告。</li>
<li>最后,可能选择审查或反思并改进报告一次。</li>
</ol>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/8ac156b7624048993837508c3d5b8670_3.png"></p>
<p>执行这个计划时,你会按步骤进行:研究员执行研究,将结果传给设计师,再传给撰写人,最后可能进行一步反思,然后任务完成。</p>
<p>这个工作流的一个有趣视角是:除了上面这三个智能体,左边这个大语言模型本身就像是<strong>第四个智能体</strong>——一个营销经理智能体。它负责设定方向,并将任务委派给研究员、设计师和撰写人智能体。因此,这实际上是一个由四个智能体组成的集合:一个营销经理智能体协调着研究员、平面设计师和文案撰写人智能体的工作。</p>
<h2 id="总结与展望-5">总结与展望</h2>
<p>在本视频中,你看到了两种通信模式:</p>
<ol>
<li><strong>线性模式</strong>:智能体依次采取行动,直到任务结束。</li>
<li><strong>管理者协调模式</strong>:一个管理者智能体协调其他几个智能体的活动。</li>
</ol>
<p>事实证明,在构建多智能体系统时,一个关键的设计决策就是确定不同智能体之间的<strong>通信模式</strong>。这是一个热门的研究领域,目前正在涌现多种模式。</p>
<p>在下一节课中,我将向你展示一些最常见的通信模式,用于让你的智能体彼此协作。让我们在下一个视频中继续探讨。😊</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/8ac156b7624048993837508c3d5b8670_5.png"></p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/8ac156b7624048993837508c3d5b8670_5.png"></p>
<h1 id="028多智能体系统的通信模式-️">028:多智能体系统的通信模式 🗣️</h1>
<p>在本节课中,我们将要学习多智能体系统中几种常见的通信模式。理解这些模式对于设计高效协作的智能体团队至关重要。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/36dc760ad3bf34e7d04edb5a7e39665c_1.png"></p>
<p>当一个人工智能团队共同工作时,它们之间的通信模式可能相当复杂。事实上,设计一个组织结构图以找到人员之间最佳的沟通与协作方式,本身就是一项复杂的任务。</p>
<p>事实证明,为多智能体系统设计通信模式也同样复杂。接下来,我将展示几种目前不同团队最常用的设计模式。</p>
<h2 id="线性通信模式-">线性通信模式 📈</h2>
<p>首先,我们来看一个最常见的通信计划。在一个采用线性计划的营销团队中,研究员首先工作,然后是平面设计师,最后是文案。其通信模式是线性的。</p>
<p>以下是线性通信模式的工作流程:</p>
<ul>
<li>研究员与平面设计师沟通。</li>
<li>研究员和平面设计师都可能将输出结果传递给文案。</li>
</ul>
<p>这是一种非常线性的通信模式,也是我目前所见最常用的两种通信计划之一。</p>
<h2 id="分层通信模式-">分层通信模式 🏢</h2>
<p>上一节我们介绍了线性模式,本节中我们来看看第二种最常见的通信计划。它类似于我们在使用多智能体进行规划的示例中所见,即存在一个管理者,负责与多个团队成员沟通并协调他们的工作。</p>
<p>在这个例子中,营销经理决定调用研究员来完成一些工作。你可以想象,营销经理收到报告后,将其发送给平面设计师;收到平面设计师的报告后,再指示文案。这就是一种分层通信模式。</p>
<p>如果你要实际实现分层通信模式,让研究员将报告传回给营销经理,而不是由研究员直接将结果传递给平面设计师和文案,可能会更简单。因此,这种由一个管理者协调多个其他智能体工作的分层结构,也是一种相当常见的规划通信模式的方式。</p>
<h2 id="其他通信模式-">其他通信模式 🔄</h2>
<p>除了上述两种主流模式,还有一些更高级、使用频率较低但在实践中有时会用到的通信模式。</p>
<h3 id="深层分层结构">深层分层结构</h3>
<p>这种模式与之前类似,设有营销经理、研究员、平面设计师和文案。但研究员自己可能还会调用另外两个智能体,例如网络研究员和事实核查员。平面设计师可能独立工作,而文案则可能拥有一名初级风格写手和一名引文检查员。</p>
<p>这构成了一种分层组织的智能体结构,其中某些智能体自身可以调用其他子智能体。我在一些应用中也见过这种模式,但它比单层分层结构复杂得多,因此目前使用较少。</p>
<h3 id="全互联通信模式">全互联通信模式</h3>
<p>最后一种模式执行起来颇具挑战性,但我看到一些实验性项目在使用它,即全互联通信模式。</p>
<p>在这种模式中,任何智能体都可以在任何时间与其他任何智能体交谈。实现方式是,提示所有四个智能体(在本例中),告知它们可以决定调用其他三个智能体。每当一个智能体决定向另一个智能体发送消息时,该消息就会被添加到接收方智能体的上下文中。然后,接收方智能体可以思考一段时间,再决定何时回复第一个智能体。</p>
<p>于是,所有智能体在一个群体中协作,相互交谈一段时间,直到每个智能体都声明自己完成了任务,停止交谈。也许当所有人都认为完成时,或者当文案认为足够好时,就生成最终输出。</p>
<p>在实践中,我发现全互联通信模式的结果有点难以预测。因此,一些不需要高度控制的应用可以运行它,看看能得到什么。如果营销手册不够好,也许没关系,只需再次运行,看看是否能得到不同的结果。我认为,对于那些愿意容忍一点混乱和不可预测性的应用,我确实看到一些开发者在使用这种通信模式。</p>
<h2 id="工具与框架-️">工具与框架 🛠️</h2>
<p>我希望以上内容能传达出多智能体系统的丰富性。目前也有相当多的软件框架,支持轻松构建多智能体系统,并且它们也能相对容易地实现上述一些通信模式。因此,如果你要构建自己的多智能体系统,可能会发现这些框架对于探索这些不同的通信模式也很有帮助。</p>
<p>本节课中我们一起学习了多智能体系统的几种核心通信模式:线性的、分层的、深层分层的以及全互联的。理解这些模式是设计高效、可控的智能体协作系统的关键基础。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/36dc760ad3bf34e7d04edb5a7e39665c_3.png"></p>
<p>现在,这把我们带到了本模块也是本课程的最后一个视频。让我们进入最后的视频进行总结。</p>
<h1 id="029课程总结-">029:课程总结 🎓</h1>
<p>在本节课中,我们将回顾整个课程的核心内容,总结从基础概念到高级应用的关键知识点,并展望如何将这些技能应用于实际项目中。</p>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/813a9697fc47543cab0afdc2287f72b1_1.png"></p>
<hr>
<h2 id="课程回顾-">课程回顾 📚</h2>
<p>上一节我们介绍了多智能体系统等高级主题,本节中,我们来对整个课程进行总结。</p>
<p>首先,我们回顾了本课程涵盖的五个主要模块。</p>
<p>以下是各模块的核心内容:</p>
<ol>
<li>
<p><strong>模块一:应用前景</strong><br>
我们探讨了利用代理式AI可以构建哪些前所未有的应用程序。</p>
</li>
<li>
<p><strong>模块二:关键设计模式</strong><br>
我们开始研究关键的设计模式,包括反思设计模式。这是一种有时能为你的应用带来显著性能提升的简单方法。</p>
</li>
<li>
<p><strong>模块三:工具使用与评估</strong><br>
我们深入讨论了工具使用和函数调用,这扩展了你的LLM应用的能力,代码执行是其中一个重要案例。我们还花了大量时间讨论评估、错误分析,以及如何通过严谨的构建和分析流程,持续高效地提升代理式AI系统的性能。</p>
</li>
<li>
<p><strong>模块四:实用构建技巧</strong><br>
第四模块包含了一些我认为在你长期构建代理式AI系统时会发现最有用的材料。</p>
</li>
<li>
<p><strong>模块五:规划与多智能体系统</strong><br>
在这个模块中,我们讨论了规划与多智能体系统,它们能让你构建更强大(尽管有时更难控制、更难预测)的高级系统。</p>
</li>
</ol>
<hr>
<p><img src="https://github.com/OpenDocCN/dsai-notes-pt1-zh/raw/master/docs/dlai-aiagt/img/813a9697fc47543cab0afdc2287f72b1_3.png"></p>
<h2 id="技能应用与职业机会-">技能应用与职业机会 💼</h2>
<p>凭借从本课程中学到的技能,我认为你现在已经知道如何构建许多酷炫、令人兴奋的代理式AI应用。</p>
<p>当我的团队或我面试求职者时,我发现面试官常常试图评估候选人是否具备与本课程所教授内容相似的技能。</p>
<p>因此,我希望本课程也能为你开启新的职业机会。</p>
<p>无论你是为了兴趣还是为了专业的实际应用场景,我相信你都会享受现在可以构建的这一系列新事物。</p>
<hr>
<h2 id="总结与致谢-">总结与致谢 🙏</h2>
<p>最后,我想再次感谢你花时间与我一起学习。</p>
<p>我希望你能掌握这些技能,负责任地使用它们,并着手构建出色的应用。</p>
<p>在本节课中,我们一起回顾了代理式AI的核心概念、设计模式、评估方法以及高级系统构建。从反思模式到多智能体协作,你已掌握了构建智能、高效AI代理所需的关键知识与实践技能。现在,是时候将这些知识付诸实践,创造属于你的智能应用了。</p>
</div>
<div id="MySignature" role="contentinfo">
<img src="https://img-blog.csdnimg.cn/20190720101942967.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly93aXphcmQuYmxvZy5jc2RuLm5ldA==,size_16,color_FFFFFF,t_70" width="500"><br><br>
来源:https://www.cnblogs.com/wizardforcel/p/19773756
頁:
[1]