主题
如何在本地读取实验结果
运行评估时,你可能希望在脚本中以编程方式处理结果,而不是在 LangSmith UI 中查看。这在以下场景中很有用:
- CI/CD 流水线:实现质量门禁,在评估分数低于阈值时使构建失败。
- 本地调试:无需 API 调用即可检查和分析结果。
- 自定义聚合:使用你自己的逻辑计算指标和统计信息。
- 集成测试:使用评估结果来控制合并或部署。
本指南展示如何从实验结果中迭代并处理数据,这些结果来自 ExperimentResults 对象,该对象由 Client.evaluate() 返回。
NOTE
本页重点介绍在仍将结果上传到 LangSmith 的同时,以编程方式处理结果。
如果你想在不向 LangSmith 记录任何内容的情况下本地运行评估(用于快速测试或验证),请参阅在本地运行评估,它使用 upload_results=False。
迭代评估结果
evaluate() 函数返回一个可迭代的 ExperimentResults 对象。blocking 参数控制结果何时可用:
blocking=False:立即返回一个迭代器,在结果产生时逐条 yield。这让你可以在评估运行过程中实时处理结果。blocking=True(默认):阻塞直到所有评估完成后再返回。当你迭代结果时,所有数据都已可用。
两种模式返回相同的 ExperimentResults 类型;区别在于函数返回前是否等待完成。使用 blocking=False 进行流式处理和实时调试,或在需要完整数据集时使用 blocking=True 进行批处理。
以下示例演示了 blocking=False。它在结果流入时进行迭代,将其收集到列表中,然后在单独的循环中处理:
python
from langsmith import Client
import random
client = Client()
def target(inputs):
"""Your application or LLM chain"""
return {"output": "MY OUTPUT"}
def evaluator(run, example):
"""Your evaluator function"""
return {"key": "randomness", "score": random.randint(0, 1)}
# Run evaluation with blocking=False to get an iterator
streamed_results = client.evaluate(
target,
data="MY_DATASET_NAME",
evaluators=[evaluator],
blocking=False
)
# Collect results as they stream in
aggregated_results = []
for result in streamed_results:
aggregated_results.append(result)
# Separate loop to avoid logging at the same time as logs from evaluate()
for result in aggregated_results:
print("Input:", result["run"].inputs)
print("Output:", result["run"].outputs)
print("Evaluation Results:", result["evaluation_results"]["results"])
print("--------------------------------")输出类似如下:
Input: {'input': 'MY INPUT'}
Output: {'output': 'MY OUTPUT'}
Evaluation Results: [EvaluationResult(key='randomness', score=1, value=None, comment=None, correction=None, evaluator_info={}, feedback_config=None, source_run_id=UUID('7ebb4900-91c0-40b0-bb10-f2f6a451fd3c'), target_run_id=None, extra=None)]
--------------------------------理解结果结构
迭代器中的每个结果包含:
result["run"]:目标函数的执行。result["run"].inputs:来自你的数据集示例的输入。result["run"].outputs:目标函数产生的输出。result["run"].id:此 run 的唯一 ID。
result["evaluation_results"]["results"]:EvaluationResult对象的列表,每个评估器一个。key:指标名称(来自评估器的返回值)。score:数值分数(通常为 0-1 或布尔值)。comment:可选的说明文本。source_run_id:评估器 run 的 ID。
result["example"]:被评估的数据集示例。result["example"].inputs:输入值。result["example"].outputs:参考输出(如果有)。
示例
实现质量门禁
此示例使用评估结果,根据质量阈值自动通过或拒绝 CI/CD 构建。脚本会遍历结果,计算平均准确率分数,如果准确率低于 85%,则以非零状态码退出。这确保你可以部署符合质量标准的代码变更。
python
from langsmith import Client
import sys
client = Client()
def my_application(inputs):
# Your application logic
return {"response": "..."}
def accuracy_evaluator(run, example):
# Your evaluation logic
is_correct = run.outputs["response"] == example.outputs["expected"]
return {"key": "accuracy", "score": 1 if is_correct else 0}
# Run evaluation
results = client.evaluate(
my_application,
data="my_test_dataset",
evaluators=[accuracy_evaluator],
blocking=False
)
# Calculate aggregate metrics
total_score = 0
count = 0
for result in results:
eval_result = result["evaluation_results"]["results"][0]
total_score += eval_result.score
count += 1
average_accuracy = total_score / count
print(f"Average accuracy: {average_accuracy:.2%}")
# Fail the build if accuracy is too low
if average_accuracy < 0.85:
print("❌ Evaluation failed! Accuracy below 85% threshold.")
sys.exit(1)
print("✅ Evaluation passed!")使用 blocking=True 进行批处理
当你需要执行需要完整数据集的操作(例如计算百分位数、按分数排序或生成汇总报告)时,使用 blocking=True 等待所有评估完成后再处理:
python
# Run evaluation and wait for all results
results = client.evaluate(
target,
data=dataset,
evaluators=[evaluator],
blocking=True # Wait for all evaluations to complete
)
# Process all results after evaluation completes
for result in results:
print("Input:", result["run"].inputs)
print("Output:", result["run"].outputs)
# Access individual evaluation results
for eval_result in result["evaluation_results"]["results"]:
print(f" {eval_result.key}: {eval_result.score}")使用 blocking=True 时,你的处理代码仅在所有评估完成后运行,避免与评估日志的输出混杂。
有关不上传结果运行评估的更多信息,请参阅在本地运行评估。