mcpField
L
langsmith-evaluator

langsmith-evaluator

github.com/langchain-ai测试与质量11955 次安装10 周前更新
代码仓库

关于 langsmith-evaluator

langsmith-evaluator 介绍在 LangSmith 中定义、运行和上传评估器的方法,面向需要检查 Agent 输出或执行轨迹的开发者。内容涵盖基于 LLM 的评审与自定义代码评估,并区分本地和在线评估流程。

主要功能

  1. 01定义 LLM 评审评估器
  2. 02编写确定性代码评估器
  3. 03捕获运行输出与执行轨迹
  4. 04运行本地及在线评估
  5. 05将代码评估器上传至 LangSmith

适用场景

  1. 01按参考答案评估 Agent 输出
  2. 02验证工具调用轨迹顺序
  3. 03对生产运行执行实时质量检查
  4. 04在 LangSmith 数据集上运行实验

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/langchain-ai/skills-benchmarks --skill langsmith-evaluator

安装后在 Claude Code 中输入/langsmith-evaluator确认已加载。

详细介绍

三个核心组件:**(1)创建评估器** - LLM-as-Judge、自定义代码;**(2)定义运行函数** - 捕获 Agent 输出/执行轨迹以供评估;**(3)运行评估** - 在本地使用 `evaluate()`,或通过上传的评估器自动运行。包含 Python 和 TypeScript 示例。 环境变量
LANGSMITH_API_KEY=lsv2_pt_your_api_key_here          # REQUIRED
LANGSMITH_PROJECT=your-project-name                   # Check this to know which project has traces
LANGSMITH_WORKSPACE_ID=your-workspace-id              # Optional: for org-scoped keys
OPENAI_API_KEY=your_openai_key                        # For LLM as Judge

必须进行身份验证:设置 LANGSMITH_API_KEY 环境变量,或在 CLI 命令中传入 --api-key 标志(首选):

langsmith evaluator list --api-key $LANGSMITH_API_KEY

重要: 在查询或与 LangSmith 交互之前,务必检查环境变量或 .env 文件中的 LANGSMITH_PROJECT。这会告知你相关跟踪记录和数据所在的项目。如果 LangSmith 项目不可用,请自行判断并确定合适的项目。

Python 依赖项

pip install langsmith langchain-openai python-dotenv

CLI 工具(用于上传评估器)

curl -sSL https://raw.githubusercontent.com/langchain-ai/langsmith-cli/main/scripts/install.sh | sh

JavaScript 依赖项

npm install langsmith openai

<crucial_requirement>

黄金法则:先检查,再实现

关键: 在编写任何评估器或提取逻辑之前,你必须:

  1. 运行你的 Agent,使用示例输入并捕获实际输出
  2. 检查输出——打印输出、查询 LangSmith 跟踪记录,并了解确切结构
  3. 只有在此之后,才能编写处理该输出的代码

输出结构会因框架、Agent 类型和配置而有很大差异。切勿假设其结构——务必先验证。当输出中不包含所需数据时,查询 LangSmith 跟踪记录,了解如何从执行过程中提取数据。 </crucial_requirement>

<evaluator_format>

离线评估器与在线评估器

离线评估器(附加到数据集):

  • 函数签名:(run, example)——同时接收运行输出和数据集示例
  • 用途:将 Agent 输出与数据集中的预期值进行比较
  • 上传时使用:--dataset "Dataset Name"

在线评估器(附加到项目):

  • 函数签名:(run)——仅接收运行输出,不接收 example 参数
  • 用途:对生产环境中的运行进行实时质量检查(没有参考数据)
  • 上传时使用:--project "Project Name"

关键——返回格式:

  • 每个评估器只返回一个指标。需要多个指标时,请创建多个评估器函数。
  • 不要返回 {"metric_name": value} 或指标列表,否则会报错。

关键——本地评估器与已上传评估器的差异:

本地 evaluate()上传到 LangSmith
列名Python:根据函数名自动生成。TypeScript:必须包含 key 字段,否则列名为空根据上传时设置的评估器名称生成。不要包含 key——否则会创建重复列
Python run 类型RunTree 对象 → run.outputs(属性访问)dict → run["outputs"](下标访问)。兼容两种情况:run.outputs if hasattr(run, "outputs") else run.get("outputs", {})
TypeScript run 类型始终使用属性访问:run.outputs?.field始终使用属性访问:run.outputs?.field
Python 返回值{"score": value, "comment": "..."}{"score": value, "comment": "..."}
TypeScript 返回值{ key: "name", score: value, comment: "..." }{ score: value, comment: "..." }
</evaluator_format>

<evaluator_types>

  • LLM-as-Judge - 使用大模型对输出评分。最适用于主观质量评估(准确性、实用性、相关性)。
  • 自定义代码 - 确定性逻辑。最适用于客观检查(完全匹配、执行轨迹验证、格式合规性)。 </evaluator_types>

<llm_judge>

LLM-as-Judge 评估器

注意: CLI 目前不支持上传 LLM-as-Judge 评估器——仅支持代码评估器。对于针对数据集的评估,强烈建议定义本地评估器,并通过 evaluate(evaluators=[...]) 使用。

```python from typing import TypedDict, Annotated from langchain_openai import ChatOpenAI

class Grade(TypedDict): reasoning: Annotated[str, ..., "Explain your reasoning"] is_accurate: Annotated[bool, ..., "True if response is accurate"]

judge = ChatOpenAI(model="gpt-4o-mini", temperature=0).with_structured_output(Grade, method="json_schema", strict=True)

async def accuracy_evaluator(run, example): run_outputs = run.outputs if hasattr(run, "outputs") else run.get("outputs", {}) or {} example_outputs = example.outputs if hasattr(example, "outputs") else example.get("outputs", {}) or {} grade = await judge.ainvoke([{"role": "user", "content": f"Expected: {example_outputs}\nActual: {run_outputs}\nIs this accurate?"}]) return {"score": 1 if grade["is_accurate"] else 0, "comment": grade["reasoning"]}

</python>

<typescript>
```javascript
import OpenAI from "openai";

const openai = new OpenAI();

async function accuracyEvaluator(run, example) {
    const runOutputs = run.outputs ?? {};
    const exampleOutputs = example.outputs ?? {};

    const response = await openai.chat.completions.create({
    model: "gpt-4o-mini",
    temperature: 0,
    response_format: { type: "json_object" },
    messages: [
        { role: "system", content: 'Respond with JSON: {"is_accurate": boolean, "reasoning": string}' },
        { role: "user", content: `Expected: ${JSON.stringify(exampleOutputs)}\nActual: ${JSON.stringify(runOutputs)}\nIs this accurate?` }
    ]
    });

    const grade = JSON.parse(response.choices[0].message.content);
    return { score: grade.is_accurate ? 1 : 0, comment: grade.reasoning };
}

<code_evaluators>

自定义代码评估器

编写评估器前:

  1. 检查数据集,了解预期的字段名称(参见上方的 Golden Rule)
  2. 测试运行函数,并确认其输出结构与数据集架构一致
  3. 查询 LangSmith 跟踪记录以调试任何不匹配
```python def trajectory_evaluator(run, example): run_outputs = run.outputs if hasattr(run, "outputs") else run.get("outputs", {}) or {} example_outputs = example.outputs if hasattr(example, "outputs") else example.get("outputs", {}) or {} # IMPORTANT: Replace these placeholders with your actual field names # 1. Query your LangSmith trace to see what fields exist in run outputs # 2. Check your dataset schema for expected field names # Note: Trajectory data may not appear in default output - verify against trace! actual = run_outputs.get("YOUR_TRAJECTORY_FIELD", []) expected = example_outputs.get("YOUR_EXPECTED_FIELD", []) return {"score": 1 if actual == expected else 0, "comment": f"Expected {expected}, got {actual}"} ``` ```javascript function trajectoryEvaluator(run, example) { const runOutputs = run.outputs ?? {}; const exampleOutputs = example.outputs ?? {}; // IMPORTANT: Replace these placeholders with your actual field names // 1. Query your LangSmith trace to see what fields exist in run outputs // 2. Check your dataset schema for expected field names const actual = runOutputs.YOUR_TRAJECTORY_FIELD ?? []; const expected = exampleOutputs.YOUR_EXPECTED_FIELD ?? []; const match = JSON.stringify(actual) === JSON.stringify(expected); return { score: match ? 1 : 0, comment: `Expected ${JSON.stringify(expected)}, got ${JSON.stringify(actual)}` }; } ```

<run_functions>

定义运行函数

运行函数会执行你的 Agent,并返回用于评估的输出。

重要——先测试运行函数: 编写评估器前,你必须测试运行函数并检查实际输出结构。输出形式会因框架、Agent 类型和配置而异。

调试工作流:

  1. 使用示例输入运行一次 Agent
  2. 查询跟踪记录以查看执行结构
  3. 打印原始输出,并对照跟踪记录验证输出是否包含正确的数据
  4. 根据需要调整运行函数
  5. 确认输出与数据集架构一致

尽最大努力让运行函数的输出与数据集架构一致。 这样评估器就会简单且可复用。如果无法匹配,评估器必须知道如何提取并比较双方的正确字段。

```python def run_agent(inputs: dict) -> dict: result = your_agent.run(inputs) # ALWAYS inspect output shape first - run this, check the print, query traces print(f"DEBUG - type: {type(result)}, keys: {result.keys() if hasattr(result, 'keys') else 'N/A'}") print(f"DEBUG - value: {result}") return {"output": result} # Adjust to match your dataset schema ``` ```javascript async function runAgent(inputs) { const result = await yourAgent.invoke(inputs); // ALWAYS inspect output shape first console.log("DEBUG - type:", typeof result, "keys:", Object.keys(result)); console.log("DEBUG - value:", result); return { output: result }; // Adjust to match your dataset schema } ```
捕获执行轨迹

对于执行轨迹评估,运行函数必须捕获执行期间的工具调用。

重要: 运行输出格式会因框架和 Agent 类型而有很大差异。实现前,你必须先检查:

LangGraph Agent(LangChain OSS): 使用 stream_mode="debug" 和 subgraphs=True 捕获嵌套子 Agent 的工具调用。

import uuid

def run_agent_with_trajectory(agent, inputs: dict) -> dict:
    config = {"configurable": {"thread_id": f"eval-{uuid.uuid4()}"}}
    trajectory = []
    final_result = None

    for chunk in agent.stream(inputs, config=config, stream_mode="debug", subgraphs=True):
        # STEP 1: Print chunks to understand the structure
        print(f"DEBUG chunk: {chunk}")

        # STEP 2: Write extraction based on YOUR observed structure
        # ... your extraction logic here ...

    # IMPORTANT: After running, query the LangSmith trace to verify
    # your trajectory data is complete. Default output may be missing
    # tool calls that appear in the trace.
    return {"output": final_result, "trajectory": trajectory}

自定义 / 非 LangChain Agent:

  1. 先检查输出——运行 Agent 并检查结果结构。执行轨迹数据可能已包含在输出中(例如 result.tool_calls、result.steps 等)
  2. 回调 / 钩子——如果框架支持执行回调,请注册一个钩子,在每次调用时记录工具名称
  3. 解析执行日志——作为最后手段,从结构化日志或跟踪数据中提取工具名称

关键是在工具执行时捕获工具名称,而不是在定义时捕获。 </run_functions>

## 将评估器上传到 LangSmith

重要 — 自动运行行为: 上传到数据集的评估器会在你对该数据集运行实验时自动运行。你无需将它们传递给 evaluate()——只需针对数据集运行 Agent,上传的评估器就会自动执行。

重要 — 本地与已上传的评估器: 已上传的评估器在沙盒环境中运行,可访问的包非常有限。只能使用内置库或标准库导入,并将所有导入语句放在评估器函数体内部。对于数据集(离线)评估器,建议先使用 evaluate(evaluators=[...]) 在本地运行——这样你就可以访问所有包。

重要 — 代码评估器与结构化评估器:

  • 代码评估器(CLI 上传的评估器):在无法使用外部包的受限环境中运行。适用于确定性逻辑(精确匹配、轨迹验证)。
  • 结构化评估器(LLM 作为评审):通过 LangSmith UI 配置,使用特定的载荷格式,包含模型、提示词和架构。CLI 目前不支持此格式。

重要 — 选择正确的目标:

  • --dataset:签名为 (run, example) 的离线评估器——用于与预期值进行比较
  • --project:签名为 (run) 的在线评估器——用于实时质量检查

必须指定其中一项。不支持全局评估器。

# List all evaluators
langsmith evaluator list --api-key $LANGSMITH_API_KEY

# Upload offline evaluator (attached to dataset)
langsmith evaluator upload my_evaluators.py \
  --name "Trajectory Match" --function trajectory_evaluator \
  --dataset "My Dataset" --replace --api-key $LANGSMITH_API_KEY

# Upload online evaluator (attached to project)
langsmith evaluator upload my_evaluators.py \
  --name "Quality Check" --function quality_check \
  --project "Production Agent" --replace --api-key $LANGSMITH_API_KEY

# Delete
langsmith evaluator delete "Trajectory Match" --api-key $LANGSMITH_API_KEY

重要 — 安全提示:

  • CLI 会在执行破坏性操作前提示确认
  • 除非用户明确要求,否则切勿使用 --yes 标志

<best_practices>

  1. 对 LLM 评审使用结构化输出——比解析自由文本更可靠
  2. 让评估器与数据集类型匹配
    • 最终回答 → 使用 LLM 作为评审来评估质量
    • 轨迹 → 使用自定义代码来评估序列
  3. 对 LLM 评审使用异步方式——支持并行评估
  4. 独立测试评估器——先使用已知的好坏示例进行验证
  5. 选择合适的语言
    • Python:用于 Python Agent 和 langchain 集成
    • JavaScript:用于 TypeScript/Node.js Agent </best_practices>

<running_evaluations>

运行评估

已上传的评估器会在运行实验时自动运行——无需编写代码。本地评估器则需直接传入,用于开发或测试。

```python from langsmith import evaluate

Uploaded evaluators run automatically

results = evaluate(run_agent, data="My Dataset", experiment_prefix="eval-v1")

Or pass local evaluators for testing

results = evaluate(run_agent, data="My Dataset", evaluators=[my_evaluator], experiment_prefix="eval-v1")

</python>

<typescript>
```javascript
import { evaluate } from "langsmith/evaluation";

// Uploaded evaluators run automatically
const results = await evaluate(runAgent, {
  data: "My Dataset",
  experimentPrefix: "eval-v1",
});

// Or pass local evaluators for testing
const results = await evaluate(runAgent, {
  data: "My Dataset",
  evaluators: [myEvaluator],
  experimentPrefix: "eval-v1",
});
丰富的实验元数据

将 metadata={...} 传递给 evaluate(),即可为实验添加结构化信息标签。保留键 models、prompts 和 tools 会自动填充 LangSmith 实验界面中的专用列,便于按模型、提供方、提示词版本或工具范围筛选和比较运行结果。其他键均以自由格式元数据的形式存储。

```python EXPERIMENT_METADATA = { "models": ["openai:gpt-4o-mini"], "prompts": ["my-org/my-eval-prompt:abc12345"], "tools": [ { "name": "web_search", "description": "Search the web for information", "parameters": { "type": "object", "properties": {"query": {"type": "string"}}, "required": ["query"], }, }, ], }

results = evaluate( run_agent, data="My Dataset", evaluators=[my_evaluator], experiment_prefix="eval-v1", metadata=EXPERIMENT_METADATA, )

</python>

<typescript>
```javascript
const EXPERIMENT_METADATA = {
  models: ["openai:gpt-4o-mini"],
  prompts: ["my-org/my-eval-prompt:abc12345"],
  tools: [
    {
      name: "web_search",
      description: "Search the web for information",
      parameters: {
        type: "object",
        properties: { query: { type: "string" } },
        required: ["query"],
      },
    },
  ],
};

const results = await evaluate(runAgent, {
  data: "My Dataset",
  evaluators: [myEvaluator],
  experimentPrefix: "eval-v1",
  metadata: EXPERIMENT_METADATA,
});

不要将机密信息放入元数据中——元数据会持久保存并显示在 LangSmith UI 中。 </running_evaluations>

## 常见问题

**输出与预期不符:**查询 LangSmith 跟踪记录。它会显示每个步骤的精确输入和输出——将你找到的内容与要提取的内容进行比较。

**每个评估器只能有一个指标:**返回 {"score": value, "comment": "..."}。如需多个指标,请创建多个独立函数。

**字段名称不匹配:**运行函数的输出必须与数据集架构完全一致。先使用 client.read_example(example_id) 检查数据集。

**RunTree 与 dict(仅限 Python):**本地 evaluate() 会传入 RunTree,已上传的评估器则接收 dict。请同时处理这两种类型:

run_outputs = run.outputs if hasattr(run, "outputs") else run.get("outputs", {}) or {}

TypeScript 始终使用属性访问:run.outputs?.field

- [LangSmith 评估概念](https://docs.langchain.com/langsmith/evaluation-concepts) - [自定义代码评估器](https://changelog.langchain.com/announcements/custom-code-evaluators-in-langsmith) - [OpenEvals — 现成的评估器](https://github.com/langchain-ai/openevals)

评论

支持 Markdown