Ohhnews

分类导航

$ cd ..
Jetbrains Blog原文

JetBrains 发布 Tracy:专为 Kotlin 设计的 AI 可观测性库

#kotlin#人工智能#可观测性#软件开发#工具库

Tracy 是一个开源的 Kotlin 库,旨在几分钟内为 AI 驱动的应用程序添加生产级的可观测性。它能帮助你调试故障、测量执行时间,并跟踪模型调用、工具调用以及你自定义应用逻辑中的 LLM 使用情况。最终,全面的可观测性确保你能够获取所需的确切数据,以理解现实世界的应用行为,从高层趋势到细粒度追踪进行性能分析,并支持全面的在线和离线评估。

它与常见的 Kotlin/LLM 技术栈(包括 OkHttpKtor 客户端,以及 OpenAIAnthropicGemini 客户端)无缝集成,同时底层依赖于 OpenTelemetry。这种架构保证了你在追踪数据处理上的完全灵活性,既支持将数据导出到任何兼容的后端(如 Jaeger、Zipkin 或 Grafana),也支持与专门的 LLM 工程平台(如 LangfuseW&B Weave)直接集成。

虽然 Spring AI 或 Koog 等成熟的 AI 框架提供了内置的可观测性,但 LLM 调用必须通过其框架 API 进行才能被追踪,且它们无法轻松追踪内部应用流程。相比之下,Tracy 通过 API 或 HTTP 客户端插桩,帮助你监控 LLM 的使用情况。它还通过注释 Kotlin 函数或代码块,帮助你理清 AI 组件之间或内部 AI 代理状态之间的时序和因果关系。

通过开源 Tracy,我们邀请你共同扩展其功能——无论是请求新的 AI 后端和 API 客户端集成,还是提交实现这些功能的 Pull Request。

AI 可观测性的组成部分以及 Tracy 的帮助

作为工程师,无论是在现有应用中添加可观测性,还是从零开始构建新应用,我们都希望能够追踪、存储和分析以下内容:

  1. LLM 调用元数据,包括调用的 API、模型及其参数。在开发过程中,我们可能还需要跟踪 LLM 的输入和输出以进行调试,同时确保在生产环境中不对其进行追踪。
  2. 指向及源自 LLM 调用的应用逻辑流程——即特定调用的来源以及涉及哪些工具。

想象一个简单的 LLM 聊天应用,它向用户打招呼,并利用工具使问候语更个性化。使用 OpenAI 客户端,应用代码可能如下所示:

$ kotlin
/** LLM 工具接口 */
interface Tool<T> {
   /** 工具调用 */
   fun execute(): T
}

/** 从系统中获取当前用户名 */
class GetUserName() : Tool<GetUserName.UserNameResult> { ... }

/** 获取当前日期和时间 */
class GetCurrentDateTime() : Tool<GetCurrentDateTime.DateTimeResult> { ... }

fun main() {
   // 使用环境变量创建 OpenAI 客户端
   val client: OpenAIClient = OpenAIOkHttpClient.fromEnv()
   ...
   val params = ResponseCreateParams.builder()
       .model(ChatModel.GPT_4O_MINI)
       .maxOutputTokens(2048)
       .addTool(GetUserName::class.java)
       .addTool(GetCurrentDateTime::class.java)
       .input(ResponseCreateParams.Input.ofResponse(inputs))
       .build()

   // 获取响应。
   // 在实际应用中,它会使用循环来处理工具调用。
   val response: Response = client.responses().create(params)
   ...
   println(finalGreeting)
}

这里需要追踪的重点是:

  1. 问候代理被调用的事实。
  2. LLM 调用。
  3. 工具执行过程。

我们可以使用基础的 OpenTelemetry SDK,但这需要手动添加插桩代码,且会导致工具调用追踪的代码重复。

在理想情况下,我们应该能够配置一次工具追踪,并让所有实现自动被追踪,从而确保永远不会出现新增工具未被追踪的情况。Tracy 使这一设想成为现实。

使用 Tracy 添加可观测性

Tracy 提供了三个高级 API,帮助我们全面覆盖聊天应用的追踪需求。

作用域 Span (Scoped spans)

withSpan API 允许你创建作用域 Span。这些 Span 在代码块开始时自动激活,在代码块结束时终止,从而确保正确的嵌套和计时。

$ kotlin
fun main() {
   // 封装到 withSpan 中,确保所有嵌套事件都将作为问候代理工作的一部分被追踪。
   withSpan("Greeting agent") {
       ...
   }  
}

LLM 客户端插桩

LLM 调用是任何 AI 代理的关键部分。它们决定了应用的成本、延迟和效率,也是出现问题时首要调查的对象。这就是为什么向 LLM 客户端添加可观测性应该是直接的,并且对代码库的修改应降至最低。例如,向 OpenAI 客户端添加插桩非常简单:

$ kotlin
val client = OpenAIOkHttpClient.fromEnv()
// 所有使用该插桩客户端进行的调用都会被追踪。
instrument(client)

默认情况下,客户端插桩仅追踪元数据。若要追踪可能包含敏感数据的 LLM 输入和输出,必须通过编程方式显式启用:

$ kotlin
TracingManager.traceSensitiveContent()

或者,你也可以通过将 TRACY_CAPTURE_INPUTTRACY_CAPTURE_OUTPUT 环境变量设置为 true 在运行时启用它。

工具调用与函数追踪

LLM 非常“青睐”工具:它们帮助 LLM 有效完成确定性任务、节省 Token 并与运行环境交互。作为开发者,我们也喜欢工具,但为代码库中的每一个 LLM 工具添加可观测性是一项单调且容易遗忘的任务。

虽然装饰器在 Python 框架中处理此类场景非常出色,但 Kotlin 开发者此前只能羡慕。Tracy 改变了这一现状。通过基于注解的追踪,你只需在接口方法上添加 @Trace 注解,即可在所有实现类中启用追踪。如果你有想要追踪的独立方法,操作同样简单。@Trace 注解同样适用于单个方法或函数。

$ kotlin
/** LLM 工具接口 */
interface Tool<T> {
   // 现在所有工具调用都会被追踪
   @Trace(name = "Tool Call")
   fun execute(): T
}

总结

从应用中捕获遥测数据只是成功了一半。另一半是将数据路由到合适的后端进行存储和分析。虽然我们强烈建议使用专门针对 LLM 追踪的可观测性解决方案,且 Tracy 开箱即用地支持 Langfuse 和 W&B Weave,但它也提供了轻松将追踪数据发送到任何 OpenTelemetry 兼容后端、文件或控制台的方法。该仓库包含了许多示例,本文示例的完整代码可在此获取

[LOADING...]

使用 Tracy 配置遥测数据导出到 Langfuse 只需几秒钟。最终,你将获得一个包含 LLM 和工具调用的分层应用追踪视图。

未来展望

我们坚信,无论未来几年 LLM 的发展速度如何,可观测性始终是高效且可靠的 AI 工程的基石。无论底层 LLM 变得多么强大,使用它们的应用程序在开发和生产环境中仍需调试与评估。我们开发 Tracy 正是为了响应这一需求,旨在将生产级的 AI 可观测性带入 Kotlin 生态系统。

这仅仅是个开始!你可以通过提交 Issue、提交 Pull Request,或者在你的项目中尝试 Tracy 并分享反馈,为 Kotlin AI 生态系统的成长做出贡献。让我们一起开启追踪之旅吧!