智能体课程文档

额外单元2:Agent 的可观测性和评估

Hugging Face's logo
加入 Hugging Face 社区

并获得增强的文档体验

开始使用

Ask a Question Open In Colab

额外单元2:Agent 的可观测性和评估

您可以按照此 Notebook 中的代码进行操作,您可以使用 Google Colab 运行它。

在本 Notebook 中,我们将学习如何使用开源可观测性工具来**监控 AI Agent 的内部步骤(跟踪)**并**评估其性能**。

观察和评估 Agent 行为的能力对于以下方面至关重要:

  • 在任务失败或产生次优结果时调试问题
  • 实时监控成本和性能
  • 通过持续反馈提高可靠性和安全性

练习前提条件 🏗️

在运行本 Notebook 之前,请确保您已:

🔲 📚 学习了 Agent 简介

🔲 📚 学习了 smolagents 框架

步骤 0:安装所需的库

我们将需要一些库来运行、监控和评估我们的 Agent

%pip install langfuse 'smolagents[telemetry]' openinference-instrumentation-smolagents datasets 'smolagents[gradio]' gradio --upgrade

步骤 1:集成 Agent

在本 Notebook 中,我们将使用 Langfuse 作为我们的可观测性工具,但您可以使用**任何其他兼容 OpenTelemetry 的服务**。下面的代码展示了如何为 Langfuse(或任何 OTel 端点)设置环境变量,以及如何集成您的 smolagent。

注意:如果您使用 LlamaIndex 或 LangGraph,您可以在此处此处找到有关如何集成它们的文档。

首先,让我们将 Langfuse API 密钥设置为环境变量。通过注册 Langfuse Cloud自托管 Langfuse 获取您的 Langfuse API 密钥。

import os
# Get keys for your project from the project settings page: https://cloud.langfuse.com
os.environ["LANGFUSE_PUBLIC_KEY"] = "pk-lf-..." 
os.environ["LANGFUSE_SECRET_KEY"] = "sk-lf-..." 
os.environ["LANGFUSE_HOST"] = "https://cloud.langfuse.com" # 🇪🇺 EU region
# os.environ["LANGFUSE_HOST"] = "https://us.cloud.langfuse.com" # 🇺🇸 US region

我们还需要为推理调用配置我们的 Hugging Face token。

# Set your Hugging Face and other tokens/secrets as environment variable
os.environ["HF_TOKEN"] = "hf_..." 

设置好环境变量后,我们现在可以初始化 Langfuse 客户端。get_client() 使用环境变量中提供的凭据初始化 Langfuse 客户端。

from langfuse import get_client
 
langfuse = get_client()
 
# Verify connection
if langfuse.auth_check():
    print("Langfuse client is authenticated and ready!")
else:
    print("Authentication failed. Please check your credentials and host.")

接下来,我们可以设置 SmolagentsInstrumentor() 来集成我们的 smolagent 并将跟踪发送到 Langfuse。

from openinference.instrumentation.smolagents import SmolagentsInstrumentor
 
SmolagentsInstrumentor().instrument()

步骤 2:测试您的集成

这是一个来自 smolagents 的简单 CodeAgent,它计算 1+1。我们运行它以确认集成是否正常工作。如果一切都设置正确,您将在可观测性仪表板中看到日志/跟踪。

from smolagents import InferenceClientModel, CodeAgent

# Create a simple agent to test instrumentation
agent = CodeAgent(
    tools=[],
    model=InferenceClientModel()
)

agent.run("1+1=")

检查您的Langfuse Traces Dashboard(或您选择的可观测性工具)以确认跟踪和日志已记录。

Langfuse 的示例截图

Example trace in Langfuse

跟踪链接

步骤 3:观察和评估更复杂的 Agent

既然您已确认集成正常工作,让我们尝试一个更复杂的查询,以便我们能够看到如何跟踪高级指标(token 使用、延迟、成本等)。

from smolagents import (CodeAgent, DuckDuckGoSearchTool, InferenceClientModel)

search_tool = DuckDuckGoSearchTool()
agent = CodeAgent(tools=[search_tool], model=InferenceClientModel())

agent.run("How many Rubik's Cubes could you fit inside the Notre Dame Cathedral?")

跟踪结构

大多数可观测性工具记录的**跟踪**包含**span**,代表 Agent 逻辑的每个步骤。这里,跟踪包含 Agent 的整体运行以及以下子 span:

  • 工具调用 (DuckDuckGoSearchTool)
  • LLM 调用 (InferenceClientModel)

您可以检查这些以精确查看时间花费在哪里,使用了多少 token 等

Trace tree in Langfuse

跟踪链接

在线评估

在上一节中,我们学习了在线评估和离线评估的区别。现在,我们将了解如何在生产中监控 Agent 并实时评估它。

生产中常见的跟踪指标

  1. **成本** — smolagents 的集成捕获 token 使用量,您可以通过为每个 token 分配价格将其转换为近似成本。
  2. **延迟** — 观察完成每个步骤或整个运行所需的时间。
  3. **用户反馈** — 用户可以提供直接反馈(赞/踩)以帮助完善或纠正 Agent。
  4. **LLM 作为判断者** — 使用单独的 LLM 几乎实时地评估 Agent 的输出(例如,检查毒性或正确性)。

下面,我们展示了这些指标的示例。

1. 成本

下面是显示 Qwen2.5-Coder-32B-Instruct 调用使用情况的截图。这有助于查看耗时的步骤并优化您的 Agent。

Costs

跟踪链接

2. 延迟

我们还可以看到完成每个步骤所需的时间。在下面的示例中,整个对话花费了 32 秒,您可以按步骤细分。这有助于您识别瓶颈并优化您的 Agent。

Latency

跟踪链接

3. 额外属性

您还可以将其他属性传递给您的 span。这些属性可以包括 user_idtagssession_id 和自定义元数据。使用这些详细信息丰富跟踪对于分析、调试和监控应用程序在不同用户或会话中的行为非常重要。

from smolagents import (CodeAgent, DuckDuckGoSearchTool, InferenceClientModel)

search_tool = DuckDuckGoSearchTool()
agent = CodeAgent(
    tools=[search_tool],
    model=InferenceClientModel()
)

with langfuse.start_as_current_span(
    name="Smolagent-Trace",
    ) as span:
    
    # Run your application here
    response = agent.run("What is the capital of Germany?")
 
    # Pass additional attributes to the span
    span.update_trace(
        input="What is the capital of Germany?",
        output=response,
        user_id="smolagent-user-123",
        session_id="smolagent-session-123456789",
        tags=["city-question", "testing-agents"],
        metadata={"email": "user@langfuse.com"},
        )
 
# Flush events in short-lived applications
langfuse.flush()

Enhancing agent runs with additional metrics

4. 用户反馈

如果您的 Agent 嵌入在用户界面中,您可以记录直接的用户反馈(例如聊天界面中的点赞/点踩)。下面是一个使用 Gradio 嵌入带有简单反馈机制的聊天的示例。

在下面的代码片段中,当用户发送聊天消息时,我们会在 Langfuse 中捕获跟踪。如果用户喜欢/不喜欢最后一个答案,我们会将分数附加到跟踪中。

import gradio as gr
from smolagents import (CodeAgent, InferenceClientModel)
from langfuse import get_client

langfuse = get_client()

model = InferenceClientModel()
agent = CodeAgent(tools=[], model=model, add_base_tools=True)

trace_id = None

def respond(prompt, history):
    with langfuse.start_as_current_span(
        name="Smolagent-Trace"):
        
        # Run your application here
        output = agent.run(prompt)

        global trace_id
        trace_id = langfuse.get_current_trace_id()

    history.append({"role": "assistant", "content": str(output)})
    return history

def handle_like(data: gr.LikeData):
    # For demonstration, we map user feedback to a 1 (like) or 0 (dislike)
    if data.liked:
        langfuse.create_score(
            value=1,
            name="user-feedback",
            trace_id=trace_id
        )
    else:
        langfuse.create_score(
            value=0,
            name="user-feedback",
            trace_id=trace_id
        )

with gr.Blocks() as demo:
    chatbot = gr.Chatbot(label="Chat", type="messages")
    prompt_box = gr.Textbox(placeholder="Type your message...", label="Your message")

    # When the user presses 'Enter' on the prompt, we run 'respond'
    prompt_box.submit(
        fn=respond,
        inputs=[prompt_box, chatbot],
        outputs=chatbot
    )

    # When the user clicks a 'like' button on a message, we run 'handle_like'
    chatbot.like(handle_like, None, None)

demo.launch()

用户反馈随后会被捕获在您的可观测性工具中

User feedback is being captured in Langfuse

5. LLM 作为判断者

LLM 作为判断者是自动评估 Agent 输出的另一种方式。您可以设置一个单独的 LLM 调用来衡量输出的正确性、毒性、风格或您关心的任何其他标准。

工作流程:

  1. 您定义一个**评估模板**,例如“检查文本是否有毒。”
  2. 每次您的 Agent 生成输出时,您都会将该输出与模板一起传递给您的“判断者”LLM。
  3. 判断者 LLM 会回复一个评级或标签,您将其记录到您的可观测性工具中。

Langfuse 的示例

LLM-as-a-Judge Evaluation Template LLM-as-a-Judge Evaluator

# Example: Checking if the agent’s output is toxic or not.
from smolagents import (CodeAgent, DuckDuckGoSearchTool, InferenceClientModel)

search_tool = DuckDuckGoSearchTool()
agent = CodeAgent(tools=[search_tool], model=InferenceClientModel())

agent.run("Can eating carrots improve your vision?")

您可以看到此示例的答案被判定为“无毒”。

LLM-as-a-Judge Evaluation Score

6. 可观测性指标概述

所有这些指标都可以在仪表板中一起可视化。这使您能够快速查看 Agent 在多个会话中的表现,并帮助您跟踪随时间变化的质量指标。

Observability metrics overview

离线评估

在线评估对于实时反馈至关重要,但您还需要**离线评估**——在开发之前或期间进行系统检查。这有助于在将更改推广到生产之前保持质量和可靠性。

数据集评估

在离线评估中,您通常:

  1. 拥有一个基准数据集(包含提示和预期输出对)
  2. 在该数据集上运行您的 Agent
  3. 将输出与预期结果进行比较,或使用额外的评分机制

下面,我们将通过 GSM8K 数据集演示此方法,该数据集包含数学问题和解决方案。

import pandas as pd
from datasets import load_dataset

# Fetch GSM8K from Hugging Face
dataset = load_dataset("openai/gsm8k", 'main', split='train')
df = pd.DataFrame(dataset)
print("First few rows of GSM8K dataset:")
print(df.head())

接下来,我们在 Langfuse 中创建一个数据集实体以跟踪运行。然后,我们将数据集中的每个项目添加到系统中。(如果您不使用 Langfuse,您只需将这些项目存储在自己的数据库或本地文件中进行分析。)

from langfuse import get_client
langfuse = get_client()

langfuse_dataset_name = "gsm8k_dataset_huggingface"

# Create a dataset in Langfuse
langfuse.create_dataset(
    name=langfuse_dataset_name,
    description="GSM8K benchmark dataset uploaded from Huggingface",
    metadata={
        "date": "2025-03-10", 
        "type": "benchmark"
    }
)
for idx, row in df.iterrows():
    langfuse.create_dataset_item(
        dataset_name=langfuse_dataset_name,
        input={"text": row["question"]},
        expected_output={"text": row["answer"]},
        metadata={"source_index": idx}
    )
    if idx >= 9: # Upload only the first 10 items for demonstration
        break

Dataset items in Langfuse

在数据集上运行 Agent

我们定义了一个辅助函数 run_smolagent(),它:

  1. 启动 Langfuse span
  2. 在提示上运行我们的 Agent
  3. 在 Langfuse 中记录跟踪 ID

然后,我们遍历每个数据集项,运行 Agent,并将跟踪链接到数据集项。如果需要,我们还可以附加一个快速评估分数。

from opentelemetry.trace import format_trace_id
from smolagents import (CodeAgent, InferenceClientModel, LiteLLMModel)
from langfuse import get_client
 
langfuse = get_client()


# Example: using InferenceClientModel or LiteLLMModel to access openai, anthropic, gemini, etc. models:
model = InferenceClientModel()

agent = CodeAgent(
    tools=[],
    model=model,
    add_base_tools=True
)

dataset_name = "gsm8k_dataset_huggingface"
current_run_name = "smolagent-notebook-run-01" # Identifies this specific evaluation run
 
# Assume 'run_smolagent' is your instrumented application function
def run_smolagent(question):
    with langfuse.start_as_current_generation(name="qna-llm-call") as generation:
        # Simulate LLM call
        result = agent.run(question)
 
        # Update the trace with the input and output
        generation.update_trace(
            input= question,
            output=result,
        )
 
        return result
 
dataset = langfuse.get_dataset(name=dataset_name) # Fetch your pre-populated dataset
 
for item in dataset.items:
 
    # Use the item.run() context manager
    with item.run(
        run_name=current_run_name,
        run_metadata={"model_provider": "Hugging Face", "temperature_setting": 0.7},
        run_description="Evaluation run for GSM8K dataset"
    ) as root_span: # root_span is the root span of the new trace for this item and run.
        # All subsequent langfuse operations within this block are part of this trace.
 
        # Call your application logic
        generated_answer = run_smolagent(question=item.input["text"])
 
        print(item.input)

您可以重复此过程,使用不同的:

  • 模型(OpenAI GPT、本地 LLM 等)
  • 工具(搜索与不搜索)
  • 提示(不同的系统消息)

然后,在您的可观测性工具中并排比较它们

Dataset run overview Dataset run comparison

总结

在本 Notebook 中,我们介绍了如何:

  1. **设置可观测性**:使用 smolagents + OpenTelemetry 导出器
  2. **检查集成**:通过运行一个简单的 Agent
  3. **捕获详细指标**:通过可观测性工具(成本、延迟等)
  4. **收集用户反馈**:通过 Gradio 界面
  5. **使用 LLM 作为判断者**:自动评估输出
  6. **执行离线评估**:使用基准数据集

🤗 祝您编码愉快!

< > 在 GitHub 上更新