Hello everyone. Welcome to the workshop on continuously improving agents with Langfuse. Um you can already go to lenuse.com/workshop. There are steps there that we will go over today and that way you can also later at home when you want to revisit it go over it yourself and there are also some extra steps that we won't cover today that you can find then as well we'll show this QR code later in the presentation uh again so continuously improving agents what does it mean we will be talking a lot about um different processes that teams use to then uh to improve their agents or to detect changes and improve their agents in different ways and you can change these together into a continuous loop and as we know in San Francisco we really like loops and so this process and this set of these set of processes together you can it's also often called AI engineering so what is AI engineering and why do we need it and how is it different from traditional engineering the main difference is that AI agents are not deter deterministic. So your system your status of your system can look healthy while the responses or the actions your agent is taking are wrong. Sometimes it's actually wrong. Sometimes it's also not qualitative enough. And so um this is what AI engineering solves. For the people who are not familiar, um, Langfuse offers a platform to actually execute on these processes and, uh, we are open source, model agnostic, framework agnostic, so you can actually use us with whatever setup you already have. There are some large companies that already use day-to-day, but we also have a large community of smaller individual users who really help us because they're working on many different setups and agent projects. And this is definitely one of the um ways we keep up to date with where this very fastm moving field is going. By the way, uh this workshop is given by Annabelle and me today and Mark, our founder, is also somewhere in the room and there he is. And we will also be walking around to help you um during the workshop if you need anything.

虽然用户反馈和人工标注可能在扩展性上稍弱,但正是在这些环节中能发现你自己未曾考虑到的问题。因此,这也是我们今天的重点所在。我的同事 Annabelle 将演示一个实际案例,而 Mark 和我会在现场走动协助。如果你需要帮助,请举手示意。正如 Lotte 已经提到的,今天的核心内容是如何有效地处理应用程序的追踪数据(traces),以及如何决定你真正需要监控的内容。这不仅关乎你的应用中哪些部分对你有意义,而非泛泛而谈;还涉及如何利用编码代理(coding agents)让自己效率提升十倍,同时也需明确哪些环节应保留人工介入,而不是让编码代理独自完成所有工作。

让我们深入探讨一下。首先,我们要介绍今天的示例应用程序:一款名为 Specs 的 IT 支持代理。这个迷你仓库源自一个小型项目,是我为我父亲开发的,因为他经常在 WhatsApp 上问我如何设置手机、打印机或电脑等各种问题。我构建了这个小代理,在生产环境中通过 WhatsApp 向他回复信息。而在本案例中,我们提供了一个简洁的用户界面(UI)。想象一下其工作原理:用户是我的父亲或其他人,他向 Specs 提问。Specs 拥有几个可用工具,例如获取支持上下文(包括父亲使用的手机型号、操作系统及安装的应用程序信息),以及搜索帮助库,其中包含解决特定问题的常见问题解答和上下文背景。

此外,我们使用 OpenAI 的 API 端点来生成回复并将结果反馈给我们的父亲。对于这个应用程序,我们将首先共同查看追踪数据(traces),然后思考哪些信息是我们真正需要关注的,以确保父亲获得他想要的技术支持。你可以扫描这里的二维码找到研讨会仓库,我会与你一起完成设置步骤,无需担心。过程中还有文档可供参考以防迷路,后续若想进一步探索,还将提供更多模块。请访问 lenfuse.com/workshop 查看 Markdown 页面,点击链接即可进入 GitHub 仓库并将代码克隆到你的 IDE。

我已经完成了克隆操作并做好了准备。接下来我们需要配置环境变量。为此,让我们前往 langfuse.com 创建账户或登录现有组织。你可以选择任意区域,然后注册账号并进入控制台。系统会自动为你创建一个项目,你可以通过点击“创建新的 API 密钥”来获取所需的 API Keys。请花一点时间访问我们的网站并完成此设置,这是我们要共同完成的第一步。稍后我会展示这些步骤,它们也记录在我们的研讨会网站上。

快速注册并创建新账户后,对于已经完成此步骤的人,我们今天提供了一组临时的 OpenAI API 密钥。你可以扫描该二维码获取密钥(之后我们会轮换它,但今天请使用此密钥)。将其添加到你的 .env 文件中即可开始。只需复制示例的 .env 文件并填入密钥,然后安装依赖项。这是一个使用 OpenAI Agent SDK 的 TypeScript 应用程序,运行 npm run dev 即可启动应用。

应用已直接打开,我们可以看到示例应用程序界面——“父亲支持代理”。它已经用一些预设问题向我们打招呼。例如,我们可以输入:“如何在 iPhone 上开启蓝牙?” Specs 会稍作停顿,在后台调用所需的工具获取上下文,然后以分步指令的形式回复父亲如何开启蓝牙。这就引出了后台发生的情况——这也是我们想要深入分析的重点部分。

现在,让我们回到追踪(Tracing)页面运行应用并提问后,你会看到第一个追踪记录弹出。这里的每一行代表一个观察点(observation),图标不同意味着它们属于不同类型的操作。点击其中一项,我们可以看到整个流程根植于我们的代理观察(agent observation),下方则包含几次生成调用以及拉取特定上下文的工具调用。这是一个完全具备可观测性的应用程序,虽然也有分步设置指南和自动化脚本,但今天我们将专注于如何使用这些追踪数据。

回到 lenfuse.com/workshop 页面,进入“监控研讨会”模块(正如 Lotte 提到的)。在我们的父亲支持应用背景下,“监控”究竟意味着什么?当父亲与应用程序互动时,我们当然看不到他的具体操作,因为代理的意义就在于此——我们无法坐在他身边。但我们确实需要追踪后台发生的事情。我们不仅想……

为了追踪代理正在执行的操作,但我们实际上需要理解其含义。因此我们思考了在支持应用中可能出错的情况。首先是父亲可能对应用表示不满,例如当我询问如何设置蓝牙时,我会疑惑它实际是如何工作的、按钮在哪里。如果父亲提出这个问题,我们可能希望捕捉到这一信号,因为之前的回答可能不够清晰或详细。现在让我们共同设置一下:首先复制这里的 Git 命令,检出用于监控的检查点(checkpoint),然后回到 IDE 运行该命令。我们可以看到现在切换到了研讨会的“监控”步骤,这是一个检查点。

接下来我们要将评估器接入应用。向下滚动可以看到第一步是配置 Langfuse 的评估模型。我跳转到应用程序中,关闭追踪部分并进入“评估器”选项卡。在这里可以看到两种设置方式:一是基于代码的评估器,用于更确定性的应用检查;二是使用 LLM 作为代理(LLM as a Judge)的评估器,适用于从对话历史中提取隐性信息。我们还看到了一些模板,“用户意见不合”就是其中之一。点击它可以看到需要设置 LLM 连接,因此我跳转到此处并迅速停止共享屏幕以隐藏 API Key。

笔记本电脑死机了。这最终是一种使用特定模型来评估发生情况的方法,请稍等片刻。好的,我现在设置了一个新的 LLM 连接,这里再次使用 OpenAI API Key。我通过之前共同设置的配置连接了 OpenAI API Key,当然你也可以连接其他各种模型,如果有自行配置的网关,还可以使用自己的代理。现在跳回评估器页面,点击“创建评估器”,再次选择模板和模型。

我们可以看到第一步是过滤我们要针对的实际观测数据。在这种情况下,我们不针对生成部分,而是针对作为整个追踪根节点的代理(agent)。你还可以看到其他选项,如目标工具调用或生成内容。但在我们的特定案例中,我们只想查看输入部分,即观察用户发送的消息。再次参考说明,我们有特定的方式来定位观测的不同部分:我们选取代理、评估器提示词,并通过花括号在此处拉入上下文。

为了定位对我们相关的追踪部分,我们需要设置 JSON 路径并确保目标正确。对于对话历史,我们实际上要定位整个消息数组,因此将其复制并粘贴到这里。现在可以看到它映射了追踪中的消息历史:汇总交互内容、用户询问了什么、工具做了什么以及生成了何种回复。作为检测“用户意见不合”的第二部分,我们当然还需要定位来自用户的最后一条消息以获取相关信息。

现在可以看到我们将“如何在手机上打开蓝牙”映射到了评估器中,执行后我们就有了第一个实时运行的评估器。可以想象,如果进入一个追踪记录,父亲说“如何打开蓝牙”,随后跟进问“但这个按钮实际上不在那里,我不知道去哪找,你说的话不对”,我们会捕捉到这一情况。这是一个有趣的事件信号,帮助我们理解哪里出了问题。可能在最初的 500 个问题中并非全部失败,但可能有五六七个不够清晰的地方,需要更多细节来深入调查。

“用户意见不合”是我们的第一个例子,再看看还有什么可能有趣的情况。在我们的案例中,我们有一个基于代码的评估器来捕获是否使用了全大写字母。我想在与 Cloud 或 CodeEx 交互时,如果我感到沮丧,可能会使用全大写字母来强调观点。我想许多人在聊天应用中也这样做过,特别是在聊天应用中,这是捕捉用户沮丧情绪的好方法。

在这种情况下是全大写字母,但替代方案也可能是脏话或某些通常不应在聊天中使用的术语。当面对代理时,人们可能会倾向于这样做。为此我们现在要设置一个基于代码的评估器以确保捕捉到这种沮丧情绪。可以看到这里有一个 Python 片段,向下滚动可以看到实际的评估函数已定义,它再次定位 JSON 路径的一部分:提取特定的用户消息并检查其中是否有全大写字母,如果是则返回布尔分数 true。

让我们复制这部分以便接入设置。我只复制底部部分因为上部是静态的,并在此处设置另一个评估器——这次是基于代码的。我们也支持 TypeScript 代码,如果你主要使用 TypeScript 也可以操作,但我们现在选择 Python 代码。我们将其命名为“全大写字母沮丧”。由于我们要使用布尔分数,让我们也添加一个小的说明,以便我们知道如果为 true 则表示他确实因全大写字母而感到沮丧。然后我在底部用我们复制的内容替换这部分。

当然,在这里你可以编写各种自定义代码。无论你想评估什么——无论是查找特定词汇,还是确保某些品牌名称始终正确书写(例如“f”有时大写而我们通常小写)——你都可以捕捉这些情况,以发现潜在错误。现在让我们设置好这个评估器。我们创建了第二个评估器后,还需要考虑要针对哪种观察数据。我们要对实时生产环境中的数据进行监控,目标类型是代理(Agent)。

在这里我再次选择了针对该代理的评估规则。右侧显示我们可以进行小范围测试运行。结果显示返回了“false”,因为此时仅询问关于蓝牙开关的问题,尚未触发其他逻辑。当我们对结果满意后,可以点击执行。顺便提一下,虽然目前是在观察数据上运行,但这同样适用于离线改进过程中的实验测试。

现在我们对在实时观察中运行的效果感到满意,于是点击执行并检查结果是否生效。为了验证这一点,我回到IT支持代理界面,发起一个关于如何开启蓝牙的查询。等待回复后放大屏幕查看细节。虽然字体较小,但内容清晰可见:代理表示无法尝试开启蓝牙,并提醒我之前应该带眼镜。

面对这种情况我们先保持冷静。代理根据系统提示词中的规范处理了该请求,并给出了详细回复。为了测试其交互能力,我故意表示异议:“根本没有这样的蓝牙图标。”代理随即承认我的观点正确。接下来我们查看追踪记录,观察评估器是否已介入分析此次交互过程及结果判定依据。

在详细追踪中,我们可以看到用户消息“如何开启蓝牙?”以及代理的回复内容。系统返回的输出显示评估器已启动,并在左上角标记了相关评分指标。整体代理观察被标记为“用户异议:true”,因为用户在特定情况下指出全大写格式不正确且操作未成功。这一信号表明评估机制正在有效工作,能够捕捉到具体的异常反馈。

理论上,我们可以据此筛选出标记为“用户异议:true”或“全大写挫败感:true”的观察记录,从而找出值得深入分析的问题案例。这些数据来源反映了生产环境中用户的实际行为模式。此外,监控生产中用户试图执行非预期操作的情况也至关重要,这被称为“范围外请求”。

在我们的助手提示词中明确规定了代理仅协助手机IT支持问题,但用户可能涉及打印机或电脑等其他设备。当前范围限定于特定领域,因此我们需要设置此类评估器来识别“范围外请求”。与仅查看最后一条用户消息不同,此处还需结合系统提示词进行动态判断。通过JSON路径配置,我们可以精准定位并监控此类越界行为。

最后我们再次进入评估器页面,选择“范围外请求”模板并针对生成内容设置规则。由于需要引用系统提示词,我们将第一个消息(即系统指令)与最后一条用户消息进行映射。在提示词中定义逻辑:始终对比“系统预期功能”与“用户实际尝试行为”。配置完成后执行该评估器,以便在检测到越界操作时获取通知。

当开发人员尝试使用超出应用范围的功能时,系统会发出警报并记录数据。基于这些信息,我们可以做出明智决策:是修复应用以扩展范围,还是改进用户沟通以减少误解。虽然当前仅为IT支持场景,但在更复杂的应用中,这种机制能帮助捕捉用户误用系统的情况。通过深入分析这些细节,我们可以持续优化产品体验并完善评估监控体系。

复制粘贴现有的内容,但真正深入查看正在发生的事情。因此,每当我们要处理这些数据时,例如现在我们可以使用这些评分来过滤特定的追踪和结果。这里有两个示例,通过这种方式可以洞察这些问题实际发生的频率。完美。这样我们可以连接监控器并查看情况发生什么,现在让我们导入一些生产数据以了解实际发生了什么以及在我们的应用中表现如何。为此我们进入监控模块的底部,这里有一个脚本来导入一些生产信息从而拥有更多数据供实际查看。所以我回到我的仓库并复制我们的命令。

可以想象后台发生的是我们有一组作为数据集的追踪数据。这些信息还包括一些评分,我们将这些直接导入到我们的应用程序的语言实例中。让我们看看是否已经成功导入。再次取出评分过滤器,我们可以看到确实有新数据进入。我们现在拥有大量追踪数据,跨越多个页面。当然问题是我们要如何利用这些数据以及如何找出应用中实际出错或正确的地方。

所有这些数据通常用于指导离线改进流程,确保应用也能正常运行。因此这些生产追踪数据特别是那些值得关注的部分可以用于构建数据集供离线改进流程使用从而打造更好的应用。但今天我们要专注于监控和追踪部分。让我们看看如何使用编码代理来发现应用中更大规模的问题。为此我们将一起安装 Langfuse 技能,我们在设置步骤中有一个小命令我通常直接告诉编码代理为我安装它你也可以单独安装。

我们拥有 CLI 和我们的技能,在我的案例中可以通过 Claude 信任我的应用程序来安装。现在正在发生的是它拉取了我们的 CLI,而 CLI 暴露了我们所有的 API,因此你可以随时访问你的追踪、评分、数据集和实验运行结果也可以通过命令行或编码代理直接启动它们从而更有效地使用 Langfuse。这也是当你最初尝试对应用进行仪器化并获取第一批追踪时可以使用它来自动添加追踪并获得初步洞察。

这里我正在安装 Langfuse 技能,为了查看具体操作过程我转向 Codex它已经在后台安装了。我现在想弄清楚追踪中实际出了什么问题,哪些步骤出错?我们里面有哪些评分?我询问我的编码代理请使用 Langfuse 技能在我们的追踪中寻找问题。自然 Codex 需要一些时间,但为了理解情况发生什么,Codex 现在正在访问我们应用中的实时追踪数据。

它查找询问了什么问题、发现了什么评分,可能有很多大写字母表示的挫败感发生在哪里用户不同意但超出我们官方设置的范围。它还检查是否存在延迟问题、工具调用问题以及任何与我们不希望发生的情况相关的错误,以找出在生产环境中静默失败的地方。既然这正在运行一小段时间,我认为现在是等待 Codex 并回答几个问题的良好时机以防你们有任何问题。

让我们看看是否完成了,是的我们实际上得到了报告我可以将其保存为 Markdown 但我只是简要展示我准备的那个发誓我没有进行 P 值操纵我们可以查看正确的版本但只是想向你展示它的外观。因此我们的编码代理现在运行了我们导入的生产追踪数据,大约有 120 条或 70 条追踪它实际上查看了所有可能出错的维度。

我们现在获得了一份相当详细的报告关于有多少追踪、多少观察结果以及其中有多少是工具调用然后它还生成了一些发现,第一个发现是我们存在静默检索质量失败在搜索帮助库中。这实际上是我们没有评估过的但我们也以前没意识到我们的信息查找工具在查看哪种问题可能对应正确答案时实际上正在静默失败并没有真正执行其应有的功能。

这也是我们看到的第一个问题,但我们也看到检索遗漏增加了延迟和成本我们在工具重试调用中检测到一些问题还可以看到一个评估覆盖差距横跨最近的流量我们实际上没有评估所有内容但只从正在进行的追踪子集中获得信号。简要验证一下 Codex 是否也发现了相同的问题,好的它也检测到提示版本偏离并提到了重试的延迟文本以及监控覆盖分裂。

这样我们就可以发现应用中的这些问题但随后也可以确保找到修复方法从而随着时间的推移改进应用并确保解决实际出现的问题。好的,这里我们收到保存此内容的建议但让我们看看是否也能在这里获得修复方案。最有趣的部分是什么?我实际上想摆脱搜索帮助库那个因为如果它不能真正帮助我们使用这些工具那么我们也可以移除这个。为此我们也可以使用我们的技能

我们的搜索帮助库工具。由于我们现在拥有仓库上下文,它实际上还能帮助我们修复代码中的问题,而不仅仅是 Langfuse 设置方面的问题。是的,现在它开始重新工作并为我们修复应用程序中的这个问题了。但让我们先退一步,理解一下这背后真正需要发生的事情。为此,我们要回到幻灯片部分。

我们今天关注的重点实际上是从生产追踪中捕获信号的部分。我们最初设置了追踪,确保能够逐步查看实际发生的情况:代理使用了哪些工具?输入和输出是什么?我们从这些信号中获取了什么信息。但是,为了使代理随着时间的推移不断改进,我们需要对这些类型的信号做什么呢?

一方面,我们需要维护我们的评估标准。例如,我们曾有过这样的疑问:如何确保代理不会过度关注某些方面,或者没有真正提供有价值的信息?我们需要从这些信号中确保持续优化评估器的设置,并获取所需的信息。

但最重要的是,我们还需要维护数据集。在最初构建应用程序时,你可能知道人们试图做什么,但随着时间推移,你会意识到有很多预先未考虑到的边缘情况。因此,你需要随着时间的推移维护数据集,创建良好的生产示例,将它们添加到离线事件中,并确保能够进行迭代。

无论何时做出更改,都要有信心地发布版本,将其纳入 CI/CD 流程中。确保在引入新更改时不会出现性能回退(regression)。今天,我们只涵盖了 AI 工程循环中在线评估的部分。当然,事情不止于此。

这一切都关乎确保你了解正在发生的事情并捕获有趣的部分——无论是用户分歧、全大写文本还是辱骂性语言,亦或是某种质量评估。基于这些信号,你正在构建并特别维护随时间变化的数据集。

这并非一次性工作。你需要投入精力,持续闭合循环,从而拥有一个能代表用户实际行为的数据集。基于这些数据集,你可以运行实验并评估结果。

这样你总能获得关于应用质量的准确指标,并在部署时确信可以安全发布。这就是我们研讨会的核心部分。我想简要提及一些事项:今天我们只看了其中一部分,但在我们的网站上可以看到这个 Langfuse 研讨会实际上是一个包含八个步骤的完整指南。

我们只能触及其中的一两个模块,但还有提示词管理、数据集设置等功能。这是一个逐步的指导过程,帮助你正确配置所有这些步骤。当然,我们也建议使用技能工具配合你的编码代理来搭建环境。

如果是我们明天开始做这件事,我们会采取以下步骤:首先获取仓库上下文,使用 Langfuse 技能通过命令快速设置追踪功能,以便真正了解应用程序中发生的事情。

然后手动审查追踪记录,深入理解用户的行为模式。最后进入构建生产级追踪配置的阶段,从而开始离线优化工作。非常感谢大家的参与。我还有几个问题要回答,再次感谢各位出席。Mark、Lotte 和我都在场,非常乐意与大家讨论任何问题。

我们还有一个展览摊位,欢迎大家在未来几天过来与我们交流聊天。