跳转到内容

Pydantic Logfire 调试与监控

使用大语言模型(LLM)的应用程序面临一些众所周知的挑战:LLM 速度慢不可靠成本高

这些应用程序还面临一些大多数开发者较少遇到的挑战:LLM 变化无常不确定。提示中的微小变化可能会完全改变模型的性能,而且没有可以运行的 EXPLAIN 查询来理解原因。

警告

从软件工程师的角度来看,你可以把 LLM 想象成你听说过的最糟糕的数据库,而且还要更糟。

如果 LLM 不是那么有用,我们根本不会碰它。

要成功构建基于 LLM 的应用程序,我们需要新的工具来理解模型性能以及依赖于它们的应用程序的行为。

那些仅仅让你了解模型表现如何的 LLM 可观测性工具是无用的:调用 LLM 的 API 很简单,但将其构建到应用程序中却很困难。

Pydantic Logfire

Pydantic Logfire 是一个由创建和维护 Pydantic Validation 和 Pydantic AI 的团队开发的可观测性平台。Logfire 旨在使用 OpenTelemetry 让你了解整个应用程序:生成式 AI、经典的预测性 AI、HTTP 流量、数据库查询以及现代应用程序所需的一切。

Pydantic Logfire 是一个商业产品

Logfire 是一个提供商业支持的托管平台,拥有非常慷慨且永久的免费套餐。你可以在几分钟内注册并开始使用 Logfire。Logfire 也可以在企业套餐下进行自托管。

Pydantic AI 内置了对 Logfire 的支持(但可选)。这意味着如果安装并配置了 logfire 包并启用了智能体(agent)的检测(instrumentation),关于智能体运行的详细信息就会发送到 Logfire。否则,几乎没有额外开销,也不会发送任何数据。

这是一个在 Logfire 中显示运行 天气智能体 细节的示例

Weather Agent Logfire

每次智能体运行都会生成一个追踪(trace),并为每个模型请求和工具调用发出跨度(span)。

使用 Logfire

要使用 Logfire,你需要一个 Logfire 账户。Logfire Python SDK 已包含在 pydantic-ai 中。

pip install pydantic-ai
uv add pydantic-ai

或者,如果你使用的是 slim 包,可以通过 logfire 可选组来安装它。

pip install "pydantic-ai-slim[logfire]"
uv add "pydantic-ai-slim[logfire]"

然后使用 Logfire 验证你的本地环境。

 logfire auth
uv run logfire auth

并配置一个项目以发送数据。

 logfire projects new
uv run logfire projects new

(或使用 logfire projects use 命令使用现有项目)

这将在当前工作目录下写入一个 .logfire 目录,Logfire SDK 将在运行时使用它进行配置。

有了这些,你就可以开始使用 Logfire 来检测 Pydantic AI 代码了。

instrument_pydantic_ai.py
import logfire

from pydantic_ai import Agent

logfire.configure()  # (1)!
logfire.instrument_pydantic_ai()  # (2)!

agent = Agent('openai:gpt-4o', instructions='Be concise, reply with one sentence.')
result = agent.run_sync('Where does "hello world" come from?')  # (3)!
print(result.output)
"""
The first known use of "hello, world" was in a 1974 textbook about the C programming language.
"""
  1. logfire.configure() 用于配置 SDK,默认情况下它会从 .logfire 目录中查找写入令牌(write token),但你也可以直接传递一个令牌。
  2. logfire.instrument_pydantic_ai() 启用对 Pydantic AI 的检测。
  3. 由于我们启用了检测,每次运行都会生成一个追踪,并为模型调用和工具函数执行发出跨度。

(这个例子是完整的,可以“按原样”运行)

这将在 Logfire 中显示如下:

Logfire Simple Agent Run

Logfire 文档 详细介绍了如何使用 Logfire,包括如何检测其他库,如 HTTPXFastAPI

由于 Logfire 构建在 OpenTelemetry 之上,你可以使用 Logfire Python SDK 将数据发送到任何 OpenTelemetry 收集器,请参阅下文

调试

为了演示 Logfire 如何让你可视化 Pydantic AI 运行的流程,以下是运行 聊天应用示例 时从 Logfire 获得的视图:

监控性能

我们还可以在 Logfire 中使用 SQL 查询数据来监控应用程序的性能。这是一个在 Logfire 内部使用 Logfire 监控 Pydantic AI 运行的真实示例:

Logfire monitoring Pydantic AI

监控 HTTP 请求

“去你的,给我看提示。”

根据 Hamel Husain 颇具影响力的 2024 年博客文章 《Fuck You, Show Me The Prompt.》(请忽略大小写,观点是成立的),能够查看向模型提供商发出的原始 HTTP 请求和响应通常很有用。

要观察向模型提供商发出的原始 HTTP 请求,你可以使用 Logfire 的 HTTPX 检测,因为所有提供商的 SDK 内部都使用 HTTPX 库。

with_logfire_instrument_httpx.py
import logfire

from pydantic_ai import Agent

logfire.configure()
logfire.instrument_pydantic_ai()
logfire.instrument_httpx(capture_all=True)  # (1)!
agent = Agent('openai:gpt-4o')
result = agent.run_sync('What is the capital of France?')
print(result.output)
#> The capital of France is Paris.
  1. 请参阅 logfire.instrument_httpx 文档了解更多详情,capture_all=True 意味着请求和响应的头(header)和体(body)都会被捕获。

Logfire with HTTPX instrumentation

without_logfire_instrument_httpx.py
import logfire

from pydantic_ai import Agent

logfire.configure()
logfire.instrument_pydantic_ai()

agent = Agent('openai:gpt-4o')
result = agent.run_sync('What is the capital of France?')
print(result.output)
#> The capital of France is Paris.

Logfire without HTTPX instrumentation

使用 OpenTelemetry

Pydantic AI 的检测功能使用 OpenTelemetry (OTel),而 Logfire 正是基于 OTel 构建的。

这意味着你可以使用任何 OpenTelemetry 后端来调试和监控 Pydantic AI。

Pydantic AI 遵循 OpenTelemetry 生成式 AI 系统语义约定,所以虽然我们认为使用 Logfire 平台你会获得最佳体验 😉,但你应该能够使用任何支持 GenAI 的 OTel 服务。

Logfire 与其他 OTel 后端

你可以完全免费地使用 Logfire SDK,并将数据发送到任何 OpenTelemetry 后端。

以下是一个配置 Logfire 库以将数据发送到优秀的 otel-tui 的示例——这是一个开源的基于终端的 OTel 后端和查看器(与 Pydantic Validation 无关)。

使用 docker 运行 otel-tui(更多说明请参见 otel-tui 的 readme

终端
docker run --rm -it -p 4318:4318 --name otel-tui ymtdzzz/otel-tui:latest

然后运行,

otel_tui.py
import os

import logfire

from pydantic_ai import Agent

os.environ['OTEL_EXPORTER_OTLP_ENDPOINT'] = 'https://:4318'  # (1)!
logfire.configure(send_to_logfire=False)  # (2)!
logfire.instrument_pydantic_ai()
logfire.instrument_httpx(capture_all=True)

agent = Agent('openai:gpt-4o')
result = agent.run_sync('What is the capital of France?')
print(result.output)
#> Paris
  1. OTEL_EXPORTER_OTLP_ENDPOINT 环境变量设置为你的 OpenTelemetry 后端的 URL。如果你使用的后端需要身份验证,你可能需要设置其他环境变量。当然,这些也可以在进程外部设置,例如使用 export OTEL_EXPORTER_OTLP_ENDPOINT=https://:4318
  2. 我们配置 Logfire 禁用了向 Logfire OTel 后端本身发送数据。如果你移除了 send_to_logfire=False,数据将被同时发送到 Logfire 和你的 OpenTelemetry 后端。

运行以上代码会将追踪数据发送到 otel-tui,它将显示如下:

otel tui simple

运行连接到 otel-tui天气智能体示例展示了如何用它来可视化一个更复杂的追踪:

otel tui weather agent

有关使用 Logfire SDK 向其他后端发送数据的更多信息,请参阅 Logfire 文档

不使用 Logfire 的 OTel

你也可以完全不使用 Logfire,直接从 Pydantic AI 发出 OpenTelemetry 数据。

为此,你需要安装和配置所需的 OpenTelemetry 包。要运行以下示例,请使用:

终端
uv run \
  --with 'pydantic-ai-slim[openai]' \
  --with opentelemetry-sdk \
  --with opentelemetry-exporter-otlp \
  raw_otel.py
raw_otel.py
import os

from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.trace import set_tracer_provider

from pydantic_ai import Agent

os.environ['OTEL_EXPORTER_OTLP_ENDPOINT'] = 'https://:4318'
exporter = OTLPSpanExporter()
span_processor = BatchSpanProcessor(exporter)
tracer_provider = TracerProvider()
tracer_provider.add_span_processor(span_processor)

set_tracer_provider(tracer_provider)

Agent.instrument_all()
agent = Agent('openai:gpt-4o')
result = agent.run_sync('What is the capital of France?')
print(result.output)
#> Paris

其他可观测性后端

因为 Pydantic AI 使用 OpenTelemetry 进行可观测性,所以你可以轻松地将其配置为向任何与 OpenTelemetry 兼容的后端发送数据,而不仅仅是我们的可观测性平台 Pydantic Logfire

以下提供商在 Pydantic AI 中有专门的文档:

高级用法

配置数据格式

Pydantic AI 遵循 OpenTelemetry 生成式 AI 系统语义约定。具体来说,它默认遵循 1.37.0 版本的约定。要使用 1.36.0 版本 或更早版本,请传递 InstrumentationSettings(version=1)(默认是 version=2)。此外,这些语义约定指定消息应作为请求跨度(span)的子级被捕获为单个事件(日志),而 Pydantic AI 默认将这些事件收集到一个 JSON 数组中,并将其设置为请求跨度上的一个名为 events 的大属性。要更改此行为,请使用 event_mode='logs'

instrumentation_settings_event_mode.py
import logfire

from pydantic_ai import Agent

logfire.configure()
logfire.instrument_pydantic_ai(version=1, event_mode='logs')
agent = Agent('openai:gpt-4o')
result = agent.run_sync('What is the capital of France?')
print(result.output)
#> The capital of France is Paris.

这在 Logfire UI 中的显示效果可能不佳,并且将在 Pydantic AI 的未来版本中被移除,但对于向后兼容性可能很有用。

请注意,OpenTelemetry 语义约定仍处于实验阶段,可能会发生变化。

设置 OpenTelemetry SDK 提供者

默认情况下,使用全局的 TracerProviderEventLoggerProvider。这些由 logfire.configure() 自动设置。它们也可以通过 OpenTelemetry Python SDK 中的 set_tracer_providerset_event_logger_provider 函数来设置。你可以使用 InstrumentationSettings 设置自定义提供者。

instrumentation_settings_providers.py
from opentelemetry.sdk._events import EventLoggerProvider
from opentelemetry.sdk.trace import TracerProvider

from pydantic_ai import Agent, InstrumentationSettings

instrumentation_settings = InstrumentationSettings(
    tracer_provider=TracerProvider(),
    event_logger_provider=EventLoggerProvider(),
)

agent = Agent('openai:gpt-4o', instrument=instrumentation_settings)
# or to instrument all agents:
Agent.instrument_all(instrumentation_settings)

检测特定的 Model

instrumented_model_example.py
from pydantic_ai import Agent
from pydantic_ai.models.instrumented import InstrumentationSettings, InstrumentedModel

settings = InstrumentationSettings()
model = InstrumentedModel('openai:gpt-4o', settings)
agent = Agent(model)

排除二进制内容

excluding_binary_content.py
from pydantic_ai import Agent, InstrumentationSettings

instrumentation_settings = InstrumentationSettings(include_binary_content=False)

agent = Agent('openai:gpt-4o', instrument=instrumentation_settings)
# or to instrument all agents:
Agent.instrument_all(instrumentation_settings)

排除提示和补全内容

出于隐私和安全原因,你可能希望在不暴露敏感用户数据或专有提示的情况下,监控你的智能体的行为和性能。Pydantic AI 允许你从检测事件中排除实际内容,同时保留调试和监控所需的结构信息。

当设置 include_content=False 时,Pydantic AI 将从 OpenTelemetry 事件中排除敏感内容,包括用户提示和模型补全、工具调用参数和响应,以及任何其他消息内容。

excluding_sensitive_content.py
from pydantic_ai import Agent
from pydantic_ai.models.instrumented import InstrumentationSettings

instrumentation_settings = InstrumentationSettings(include_content=False)

agent = Agent('openai:gpt-4o', instrument=instrumentation_settings)
# or to instrument all agents:
Agent.instrument_all(instrumentation_settings)

此设置在生产环境中特别有用,因为合规性要求或数据敏感性问题使得限制发送到可观测性平台的内容成为必要。