编者按:以下是一篇来自 Dosu 首席执行官 Devin Stein 的客座博客文章Dosu。 Dosu 是一位工程队友,帮助你开发、维护和支持软件。
如今众所周知,构建生产级 LLM 产品非常困难。可靠性对任何产品的成功都至关重要,但当你的产品建立在一系列概率函数之上时,确保可靠性绝非易事。
在Dosu,我们持续迭代我们的产品。对于我们做出的每一次改动,我们都需要了解它对最终用户的影响。评估驱动开发(EDD)让我们能够自信地发布。在过去几个月里,LangSmith 让我们能够轻松监控和搜索 Dosu 的活动,从而规模化地实践 EDD。
什么是 Dosu?
如果你曾在 LangChain GitHub 仓库上花过一些时间,你可能已经见过Dosu,一位帮助开发、维护和支持软件项目的 AI 队友。
Dosu 诞生于我做开源软件维护者的经历,这是一个有回报但出了名耗时的角色。随着我的 OSS 项目越来越受欢迎,我发现自己花在提供支持上的时间远远多于开发新功能。
对于维护者来说,这份责任经常导致倦怠,并促使一些人宣布 issue 破产,这一过程就是简单地关闭所有未解决的 issue 和 PR。OSS 社区也深受这种情况之苦,因为人们常常要等上几天、几周甚至几个月,才能等到维护者回复他们的 issue。
这种现象并非开源独有。在行业内,高达85% 的开发者的时间花在非编码任务上,比如回答临时问题、分诊 issue 和处理开销性事务。
Dosu 把这些任务从开发者的待办清单上拿走,让他们能做自己热爱的事:保持心流、写代码、发布出色的功能。同时,Dosu 也是 OSS 社区的资源,每当社区成员遇到意想不到的问题,或是有只有代码才能回答的新奇问题时,Dosu 都能给他们即时的反馈。
早期
Dosu 于 2023 年 6 月下旬上线。那时,我们的量还足够小,可以逐一检查每一条回复。每天,仅凭grep和print声明,我们仔细梳理了日志,以找出需要改进的地方。
这项工作很辛苦,但对于设计和开发 Dosu 的架构很重要。它帮助我们的团队深入理解人们试图如何使用 Dosu、它擅长处理哪些类型的请求,以及它在哪些方面存在不足。
一旦我们知道需要改进什么,问题就变成了如何改进。与传统代码更新不同,更改 LLM 逻辑并不简单。很难知道一个小改动会如何影响整体性能。很多时候我们看到,对提示词做一点微调会在某个领域带来更好的结果,却在另一个领域造成退化。
我们需要一种方法来衡量改动带来的影响。对于每一次改动,我们都想确保自己是在:
- 在表现良好的领域保持性能
- 在表现挣扎的领域提升性能
正是在这些早期日子里,我们转向了评估驱动开发,以此来衡量我们的进展。
评估驱动开发
评估驱动开发(EDD),就像测试驱动开发一样,为我们提供了开发所依据的最终目标。评估——或称“evals”——是我们理解更新和新功能的基线。EDD 帮助我们理解对 Dosu 的核心逻辑、模型或提示词所做的任何改动会带来什么影响。
借助 EDD,我们有一套定义明确的流程来改进 Dosu:
- 用少量初始评估创建一个新行为
- 向用户发布该新行为
- 在生产环境中监控结果并识别失败模式
- 为每种失败模式向我们的离线评估中添加示例
- 基于更新后的评估进行迭代以提升性能
- 重新发布并重复
在 Dosu 起步时,这套开发工作流对我们很有效,但随着使用量增长,跟上 Dosu 的活动变得困难。
在规模化下保持高质量标准
如今,Dosu 已安装在数千个代码仓库上,全天候生成响应。我们构建了数十个子模块来智能处理不同类型的场景,并且随着模型和该领域研究的发展,我们不断迭代解决问题的方法。
虽然 Dosu 的增长令人兴奋,但也带来了挑战。Dosu 活动量的增加使得几乎无法监控响应并识别生产环境中的失败模式,而这对于我们的 EDD 工作流至关重要。
我们决定是时候升级我们的 LLM 监控技术栈了。我们寻找一款工具,它不仅能帮助我们监控 Dosu 的活动,还要足够灵活以融入我们现有的工作流。我们的一些标准包括:
- 提示词必须存放在 Git 中——秉承 EDD 的理念,我们将提示词视为代码。对提示词的任何更改都必须以与代码更改相同的标准来对待。
- 代码级追踪——Dosu 不仅仅是一系列 LLM 请求。我们希望在单个 trace 内追踪 LLM 请求之间的元数据。
- 易于导出数据——我们已有现成的评估数据集和工具,希望保留它们。
- 可定制且可扩展——LLM 领域发展迅速,构建 LLM 应用没有标准方式。我们希望能够控制追踪哪些元数据,并能够定制工具以满足我们的需求。
我们探索了LLM 监控与评估领域,试图找到一款满足我们需求的产品。在与我们的早期合作伙伴之一 LangChain 团队通话后,我们很高兴地得知 LangSmith 似乎满足了所有条件。
通过 SDK 实现 LangSmith
最让我们对 LangSmith 感到兴奋的,不是它简洁的 UI 或丰富的功能集,而是它的 SDK。LangSmith SDK 提供了我们所追求的细粒度控制和可定制性。
为了试用 LangSmith,我们只需给我们的一些 LLM 相关函数添加一个@traceable装饰器。我们只花了几分钟就完成了埋点,而且一将这些更改推送到生产环境,我们就看到 trace 涌入 LangSmith UI。

这个@traceable装饰器一个意想不到的绝佳特性是,它可以将函数的和LLM 调用 trace 发送到 LangSmith。这让我们能够在 LangSmith UI 的单个 trace 中看到原始函数输入、渲染后的提示词模板以及 LLM 输出。

开箱即用,LangSmith 让我们对 Dosu 的所有活动都有了可见性。下一步是利用 LangSmith 识别失败模式,并将其集成到我们的 EDD 工作流中。
发现失败
Dosu 会收到用户的大量请求——从关于代码库的简单问题,到升级到新库版本时的错误堆栈,再到询问某个功能的进展。Dosu 可能的输入越多,可能的失败模式就越多。
在尝试识别失败模式或 Dosu 处理不佳的请求时,我们有多种信号可供观察,例如:
- 显式反馈:由 ChatGPT 普及的经典点赞/点踩反馈。
- 用户情绪:当用户在 GitHub issue 上与 Dosu 交互时,他们的回复通常能表明是否Dosu 提供了帮助
- 内部错误:LLM 可能因多种原因失败。输入或输出是否过大?生成的响应是否符合期望的 schema?
- 响应时间:在 Dosu,我们优先考虑质量而非速度;然而,理解响应为何缓慢很重要。有些请求需要快速响应,而另一些则需要较慢但更精确的响应。
LangSmith 的高级搜索功能让识别异常行为变得容易。我们可以使用一系列条件进行搜索,包括:显式用户反馈、最近的错误事件、响应时间延迟或负面情绪。LangSmith 还允许我们为每个 trace 附加额外的元数据,以进一步扩展其搜索能力。

我们已经识别出许多未曾预见的失败模式。例如,我们发现当用户分享数千行日志或 OpenAI embedding 的原始浮点值时,会出现响应极其缓慢的模式。
我们团队最喜欢的失败案例之一发生在 Dosu 被要求给一个 pull request 打标签时。Dosu 没有给 pull request 打标签,而是决定告诉用户它当晚要去看的演唱会,它对此很兴奋。Dosu 是不是 Swiftie 尚无定论。

一旦发现失败模式,EDD 工作流程与之前相同。
- 我们在 LangSmith 中搜索更多示例
- 将它们添加到我们的评估数据集
- 针对评估进行迭代
- 推送新版本的 Dosu,然后重复。
自动化评估数据集收集
在 Dosu,评估驱动开发的未来一片光明。我们团队正在进一步定制 LangSmith,以便能够从生产流量中自动构建评估数据集。我们希望让 Dosu 的工程师尽可能简单地根据对话主题、用户群体、请求类别等来整理数据集。
Dosu 与 LangChain 的合作中存在一种有趣的飞轮效应。LangSmith 帮助我们更快迭代,以提升 Dosu 的性能。Dosu 的改进直接转化为减轻 LangChain 团队的维护和支持负担,让他们能花更多时间交付 LangSmith 的功能,这反过来又加速了 Dosu 的开发。如此循环往复!
PS:Dosu 正在招聘!请联系 jobs*@dosu.dev*