30 秒看懂
DSPy 和 LangGraph 可以用不同方式解决同一智能体工作流:DSPy 强调输入输出签名、Python 模块与优化,而 LangGraph 使用共享状态、节点和路由建模。Stanford 的 Michael Ryan 用日历助手演示了两者,然后展示评估如何改变设计决策:在一次小规模测试中,优化指令让一个模型从 20 个样例中正确 11 个提高到正确 20 个。他提醒这是针对特定任务的测试,并主张采用有代表性的评估、让故障可见及可恢复,而非默认增加智能体的复杂性。
- 1经过工程化设计的 AI 系统除了模型,还需要数据和评估Ryan 区分了一个能运行的智能体和一个行为可被衡量、改进的工程化系统。
- 2DSPy 将输入输出约定与模型如何完成任务分开签名描述字段,模块组合行为,优化器利用数据和指标改进程序。
- 3在 20 封邮件的测试中,提示词优化让小模型从正确 11 封提高到 20 封示例使用 30 封训练邮件和 20 封留出测试邮件。Ryan 提醒,数据划分、评估质量和优化成本仍然重要。
- 4LangGraph 明确表示共享状态和路由节点读取并更新状态,边定义控制流程。Ryan 说,图节点内部也可以调用 DSPy。
- 5智能体支撑框架影响模型如何使用工具和上下文Ryan 对比了基于 shell 的极简支撑框架与其他框架,后者以不同方式管理事件、持久终端或分支历史。
- 6持久化工作流可以重试失败的活动在 Temporal 日历示例中,表情选择活动经过重试后工作流继续执行,历史记录展示了发生的情况。
- 7评估真正需要的任务,包括失败情况Ryan 建议使用有代表性且有难度的案例,除了准确率还衡量成本和延迟,而不是把不相关的基准测试当作目标。
要点建议
- 步骤已知时先使用工作流;当任务需要模型决定下一步时,再增加智能体自主性。
- 在判断框架或提示词变更是否更好之前,先定义特定任务的数据和评估。
- DSPy 提示词优化在一个小型留出测试中,将日历提取示例的成绩从 11/20 提高到 20/20;这一结果不能证明普遍性能。
- 使用追踪、超时、重试次数限制和执行预算,让智能体故障可见且可恢复。
- 即便底层模型相同,支撑框架在工具、上下文、执行和记忆方面的选择也会改变结果。
按章节阅读整理后的全文
框架隐藏细节,工程仍需评估
Ryan 将 AI 框架与 PyTorch 的抽象相比,并根据控制流程所在的位置区分模型、编排工作流和智能体。
框架通过隐藏重复的实现细节,让智能体系统更容易构建。Michael Ryan 将它们比作 PyTorch:开发者指定前向传播并调用反向传播,而不必手动编写每个导数,尽管底层数学仍然重要。
Ryan 描述了 AI 工程的三个支柱:系统本身、示范与反馈等数据,以及评估或指标。没有后两者也可以构建能运行的智能体,但他认为,要可靠地改进它,就需要三者兼备。
他将系统放在一个连续谱上。在工作流中,应用代码控制模型调用和分支的顺序;在智能体中,模型对选择工具等行动有更多控制权。实际系统可以混合使用这两种方式。

DSPy 和 LangGraph 都可用于工作流和智能体,Temporal 解决可靠性问题,Langfuse 和 MLflow 等工具则帮助检查执行过程。Ryan 区分了可观测性与可靠性机制:前者让问题可见,后者还能自动恢复。
DSPy 签名定义输入与输出
一个现场日历示例介绍签名、字段类型、描述,以及格式化并验证输出的适配器。
Ryan 说明自己此前曾参与 DSPy 工作。本次讲座介绍其中三个概念:定义输入输出的签名、指定并组合行为的模块,以及利用数据和指标改进提示词或权重的优化器。
现场示例使用一个日历应用,其中包含添加、删除和移动事件的工具。Ryan 从一个将消息映射为回复的简单签名开始,使用 DSPy 的 Predict 模块调用模型。
进行情感提取时,宽松的签名可能返回不一致的标签或大小写。增加类型可以将预期输出限制为正面、负面或中性,并添加数值置信度字段。
被问到如何强制满足格式时,Ryan 解释,适配器会将签名转换为模型指令,并验证返回的结构。他说,内置适配器可以尝试备用格式,但如果最终仍无法产生有效结果,就会抛出错误。

基于类的签名可以描述更复杂的任务:从邮件中提取事件名称、日期、时间和时长。可选字段可以表示信息缺失,字段描述则可指定 24 小时制等约定。
一位学生问,仅凭字段名是否足以告诉模型要提取什么。Ryan 说,名称和类型提供了信息,但描述可以澄清模糊情况。签名还会限制程序请求哪些输出。
在 DSPy 的提示词构建过程中,类的 docstring 提供任务指令。Ryan 建议在其中写明基本要求,同时让优化器帮助处理细节。他说,签名转换为提示词的过程是确定性的,模型响应则是独立的下一步。
用普通 Python 组合模型调用
模块将提取、表情选择和日历 API 组合起来,代码决定执行哪些步骤。
模块可以改变完成签名任务的方式。Ryan 演示了 ChainOfThought,它在其他输出之前增加推理字段;他还展示了第二个签名,为事件选择表情符号。
课堂讨论了为什么把 docstring 用作系统指令。Ryan 说,它在代码中容易找到和阅读;一位参与者指出,这种结构也限制了某些错误。他们承认,让文档变成可执行行为有些奇特。
Ryan 在更大的 Python 模块中组合提取和表情选择。forward 方法先从邮件中提取事件,检查名称、日期和时间是否存在,再选择表情并调用日历 API。如果缺少必填字段,示例就不返回事件。
当消息未指定时长时,日历演示默认使用一小时。一封会议邮件会添加事件;没有可用事件的消息则返回无事件结果。Ryan 强调,这个分支来自他的应用代码,并非库的特殊要求。
根据带标签的样例与指标进行优化
Ryan 用 30 封训练邮件和 20 封测试邮件演示提示词优化,并讨论成本、留出评估和过拟合。
为了讨论优化,Ryan 问一个较小的开放权重模型能否完成提取任务。他准备了 50 封带标签的合成邮件,分成 30 个训练样例和 20 个测试样例。
示例指标要求日期、开始时间和时长完全匹配,事件名称不计分。指标会返回分数,也可以提供文本反馈,帮助优化器理解错误。
在这个小型留出集合上,演示中的较大模型答对了全部 20 个样例。小型 Gemma 模型最初答对 20 个中的 11 个;GEPA 提示词优化器使用训练数据重写指令后,显示的测试结果变为 20 个全对。

优化后的指令更长,明确写出了提取任务和输出字段。Ryan 说,人也可能手工写出类似指令。他还指出,优化需要多次模型调用,可能消耗大量 token,具体取决于预算。
一位学生问到过拟合。Ryan 说,其他机器学习工作中的训练、开发和测试集划分同样适用。他的示例在训练集上优化,在测试集上报告结果,但指标和样例必须反映真实目标。
DSPy 会缓存输入和参数相同的模型调用,因此命中缓存时可以复现存储的输出。没有缓存时,再生成一次优化提示词不一定是确定性的。
优化后的指令有时看起来很奇怪。Ryan 回忆了一个旧例子:它为数学任务使用了《星际迷航》场景。他建议根据有意义的留出评估判断提示词,并警惕可能被钻空子的指标。
让模型选择日历工具
ReAct 模块选择工具调用来更新日历。Ryan 还讨论了在递归语言模型中使用代码检查长收件箱。
日历工作流也可以变得更像智能体。Ryan 使用 DSPy 的 ReAct 模块,将日历函数作为工具,向它提出请求并要求给出摘要。演示中,它添加了一场咖啡会面,并更改了讲座的表情符号。
他简要展示了递归语言模型处理收件箱的方法。示例没有将每封邮件直接放入模型调用,而是给系统一个变量和一个代码执行环境,让它检查或搜索文本。
学生问能否提供自己的提示词。Ryan 说,可以在签名的 docstring 中编写指令;使用优化器是可选的,优化也可以从已有指令开始。
总结时他说,签名指定约定,模块决定如何完成约定,优化器利用数据和指标改进程序。智能体模块则提供工具使用循环等模式。
LangGraph 表示状态、节点和边
Ryan 将日历工作流重建为具有条件路由的图,并将其抽象与 DSPy 相比。
LangGraph 使用不同的抽象:共享状态、读取和更新状态的节点,以及控制节点之间路径的边。边可以带条件,模型与工具循环是图的一种可能形式。
Ryan 使用结构化输出重建事件提取器。图以状态中的邮件开始,运行一个写入提取结果的节点,然后结束。将图可视化,使这条简单的固定路径清晰可见。
一位学生问为什么要使用图。Ryan 说,明确编排有助于思考重试、检查和分布式工作。开发者负责定义图,最终应用的用户不必编辑它。
随后他增加了一条条件路由:如果提取后的状态包含名称、日期和开始时间,工作流就选择表情并添加日历事件;否则结束。因此,没有事件的邮件不会创建日历条目。
被要求比较两个框架时,Ryan 说,DSPy 用户常用 Python 编写控制流程并优化提示词,而 LangGraph 强调图编排。两者的选择有重叠,也可以结合使用:LangGraph 节点可以调用 DSPy。
LangChain 的智能体辅助工具可以创建模型与工具的循环。在示例中,智能体收到移动咖啡会面的请求并更新日历。Ryan 说明,一些实现细节只是他的理解,并非完整说明。
对于大型数据处理任务,他说,结构化输出本身不是决定性区别,因为两个框架都支持。大型图编排可能更适合 LangGraph,而图内部仍可使用 DSPy 调用和优化过的提示词。

更广泛的启示是,不同框架为相似任务提供不同抽象。无论使用什么库,开发者都要决定控制权放在哪里,并需要数据和评估来改进最终系统。
智能体支撑框架在工具和记忆方面作出不同选择
极简和更丰富的支撑框架以不同方式处理命令执行、上下文和历史。基准测试结果同时取决于模型和支撑框架。
智能体支撑框架是模型周围的机制,包括工具、规划和记忆机制、上下文构建及执行。不同选择会在成功率、成本、延迟和用户控制之间作出权衡。
Ryan 将 mini-SWE-agent 描述为极简例子:它以 Bash 为工具,使用不断增长的线性历史。每条命令使用新进程,而不是有状态的终端,从而简化一些执行问题。
OpenHands 使用面向事件的历史和持久终端,并有停止重复失败的机制。Ryan 将它与 Pi 的少量工具和树状历史对比,说明智能体可以用不同方式组织相似工作。
他还将 OpenClaw 描述为较长时间运行的智能体例子,具有定时活动以及基于文件的身份和记忆。这些是设计选择,并非每种支撑框架都必须具备的要求。
一张基准图比较了不同支撑框架中的模型,显示周边实现可以影响结果。Ryan 还介绍了生成特定任务支撑框架的研究,同时提醒,针对基准优化不等于构建通用编程助手。
Temporal 记录执行过程并重试失败
一个日历工作流展示持久化活动、工作进程和服务端历史;失败的活动可以重试和检查。
运行时间较长的任务需要能够经受故障的基础设施。Ryan 区分了模型基准图中以人类时间计算的任务时长与模型实际运行时间;他关注的操作问题是,工作流运行时机器或工作进程可能发生故障。
在 Temporal 中,工作流连接各个活动;工作进程执行代码,服务端维护执行历史与状态并分发工作。Ryan 再次运行日历任务,并打开服务端界面,而不是逐行讲解全部代码。
示例包含一个故意设计得不稳定的表情选择活动。历史记录显示,日历操作继续之前,该活动重试了三次,使恢复过程和时间都可供检查。
追踪调用、成本和延迟
可观测性工具显示输入、输出、错误和性能,帮助团队调试较长时间运行的系统。
Ryan 展示了 MLflow、LangSmith 和 Langfuse 等可观测性工具。根据工具不同,团队可以检查输入、输出、追踪记录、token 用量、延迟、成本和评估分数,以了解系统实际做了什么。
从简单方案开始,评估实际任务
Ryan 建议使用适合任务的最简单架构、具有代表性的评估和故障保护措施。最后他讨论了抽象和外部依赖的代价。
他的第一条实践建议是保持架构简单。从邮件中提取日历事件时,固定工作流可能很合适;而被要求管理日历的开放式助手可能需要模型自行选择行动。
对于定义明确且有足够训练数据的提取问题,单个特定任务模型甚至可能就够用。使用智能体时,Ryan 建议有意识地选择可用工具,而不是无缘由地增加自主性。
让故障可见且可恢复:追踪模型和工具调用,记录状态变化和错误,设置超时,限制重试次数和执行预算,并监控实际发生的情况。将工具错误反馈给智能体,可以让它尝试其他方法。
Ryan 提到一个名为 Shepherd 的研究系统,它使用监督智能体观察另一智能体的行动,并在失败后干预。他将其作为可观测性方法的一个例子,与普通工程工具并列。
评估应指导设计和优化。构建代表目标任务的案例,包括多样输入、边缘情况和失败情况;除了准确率,也要考虑成本和延迟。
他提醒不要针对不相关的热门基准进行优化。日历助手应在日历任务上测试;如果目标是通用编程智能体,编程基准才更合适。
抽象让开发更快,却可能隐藏故障时很重要的行为。Ryan 建议理解框架下面的提示词、系统机制和依赖,包括外部库是否可能继续得到维护。
他最后提出的循环是构建、运行、评估和改进。从简单设计开始,为额外复杂性提供理由,规划故障和恢复,并使用相关评估的证据权衡质量、成本和延迟。
同频道的其他文章
1:40:43EN → 简体中文
1:19:15EN → 简体中文
1:11:21EN → 简体中文
1:16:31EN → 简体中文
1:03:19EN → 简体中文
1:17:53EN → 简体中文