智能体课程文档
额外单元2:Agent 的可观测性和评估
并获得增强的文档体验
开始使用
额外单元2:Agent 的可观测性和评估
在本 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 的示例截图
步骤 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 等
在线评估
在上一节中,我们学习了在线评估和离线评估的区别。现在,我们将了解如何在生产中监控 Agent 并实时评估它。
生产中常见的跟踪指标
- **成本** — smolagents 的集成捕获 token 使用量,您可以通过为每个 token 分配价格将其转换为近似成本。
- **延迟** — 观察完成每个步骤或整个运行所需的时间。
- **用户反馈** — 用户可以提供直接反馈(赞/踩)以帮助完善或纠正 Agent。
- **LLM 作为判断者** — 使用单独的 LLM 几乎实时地评估 Agent 的输出(例如,检查毒性或正确性)。
下面,我们展示了这些指标的示例。
1. 成本
下面是显示 Qwen2.5-Coder-32B-Instruct
调用使用情况的截图。这有助于查看耗时的步骤并优化您的 Agent。
2. 延迟
我们还可以看到完成每个步骤所需的时间。在下面的示例中,整个对话花费了 32 秒,您可以按步骤细分。这有助于您识别瓶颈并优化您的 Agent。
3. 额外属性
您还可以将其他属性传递给您的 span。这些属性可以包括 user_id
、tags
、session_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()
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()
用户反馈随后会被捕获在您的可观测性工具中
5. LLM 作为判断者
LLM 作为判断者是自动评估 Agent 输出的另一种方式。您可以设置一个单独的 LLM 调用来衡量输出的正确性、毒性、风格或您关心的任何其他标准。
工作流程:
- 您定义一个**评估模板**,例如“检查文本是否有毒。”
- 每次您的 Agent 生成输出时,您都会将该输出与模板一起传递给您的“判断者”LLM。
- 判断者 LLM 会回复一个评级或标签,您将其记录到您的可观测性工具中。
Langfuse 的示例
# 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?")
您可以看到此示例的答案被判定为“无毒”。
6. 可观测性指标概述
所有这些指标都可以在仪表板中一起可视化。这使您能够快速查看 Agent 在多个会话中的表现,并帮助您跟踪随时间变化的质量指标。
离线评估
在线评估对于实时反馈至关重要,但您还需要**离线评估**——在开发之前或期间进行系统检查。这有助于在将更改推广到生产之前保持质量和可靠性。
数据集评估
在离线评估中,您通常:
- 拥有一个基准数据集(包含提示和预期输出对)
- 在该数据集上运行您的 Agent
- 将输出与预期结果进行比较,或使用额外的评分机制
下面,我们将通过 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
在数据集上运行 Agent
我们定义了一个辅助函数 run_smolagent()
,它:
- 启动 Langfuse span
- 在提示上运行我们的 Agent
- 在 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 等)
- 工具(搜索与不搜索)
- 提示(不同的系统消息)
然后,在您的可观测性工具中并排比较它们
总结
在本 Notebook 中,我们介绍了如何:
- **设置可观测性**:使用 smolagents + OpenTelemetry 导出器
- **检查集成**:通过运行一个简单的 Agent
- **捕获详细指标**:通过可观测性工具(成本、延迟等)
- **收集用户反馈**:通过 Gradio 界面
- **使用 LLM 作为判断者**:自动评估输出
- **执行离线评估**:使用基准数据集
🤗 祝您编码愉快!
< > 在 GitHub 上更新