mcpField
L
langsmith-evaluator

langsmith-evaluator

github.com/langchain-aiテスト・品質1645.0k 回インストール1 日前に更新
リポジトリ

langsmith-evaluator について

Agent の出力を LLM による判定や独自コードで評価する LangSmith 評価器の作成・実行を支援するスキルです。ローカル評価と、データセットやプロジェクトに紐づく評価器を扱い、Python と TypeScript の手順を含みます。

主な機能

  1. 01LLM による判定とコード評価器
  2. 02Agent 出力を取得する実行関数
  3. 03evaluate() によるローカル評価
  4. 04データセットとプロジェクトの評価器管理
  5. 05Python と TypeScript の手順

活用シーン

  1. 01データセットの例に対する Agent 出力の採点
  2. 02参照例なしで本番実行を確認
  3. 03アップロード前に評価ロジックをローカルで検証
  4. 04抽出ロジック作成前に実行出力と trace を確認

インストール

コマンドをコピーしてターミナルで実行します。

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

インストール後、Claude Code で/langsmith-evaluatorを入力して読み込まれたか確認します。

詳細

3 つの主要コンポーネント:**(1)評価器の作成** - LLM-as-Judge、カスタムコード、**(2)実行関数の定義** - 評価用にエージェントの出力/軌跡を記録、**(3)評価の実行** - `evaluate()` を使ってローカルで実行するか、アップロード済みの評価器を使って自動実行します。Python と TypeScript の例も含まれています。 環境変数
LANGSMITH_API_KEY=your-api-key                        # Alternative to `langsmith auth login`
LANGSMITH_ENDPOINT=https://api.smith.langchain.com   # SDK/CLI environment
LANGSMITH_PROJECT=your-project-name                   # Default for trace/run queries only
LANGSMITH_WORKSPACE_ID=your-workspace-id              # Optional: for org-scoped keys
OPENAI_API_KEY=your-openai-key                        # For locally executed OpenAI judges

保存済みの CLI プロファイルで認証します(推奨):

langsmith auth login
langsmith auth info

または、LANGSMITH_API_KEY を設定します。非表示の --api-key フラグは互換性のために引き続き使用できますが、コマンドやログにキーを直接記載しないでください。保存済みのプロファイルから選択する場合は、--profile または LANGSMITH_PROFILE を使用します。

重要: LANGSMITH_PROJECT はトレースと実行のクエリのデフォルトを指定しますが、評価器の対象は選択しません。評価器の作成とアップロードには、明示的に --dataset または --project を指定する必要があります。

CLI と SDK の認証は別々です: CLI の OAuth プロファイルで認証されるのは langsmith ... コマンドのみです。Python および TypeScript の SDK がこのプロファイルを自動的に使用することはありません。評価器の CRUD で SDK を使用する前に、LANGSMITH_ENDPOINT、LANGSMITH_API_KEY、および必要に応じて LANGSMITH_WORKSPACE_ID が langsmith auth info と同じ環境およびワークスペースを対象としていることを確認してください。CLI と SDK が異なる環境を対象としている場合は、作業を中止してください。

SDK を使った CRUD を行う前に、読み取り専用の事前確認を実行してください:

from langsmith import Client

client = Client()
client.read_dataset(dataset_name="My Dataset")

Python の依存関係

pip install langsmith langchain-openai python-dotenv

CLI ツール

curl -fsSL https://cli.langsmith.com/install.sh | sh
langsmith self-update

JavaScript の依存関係

npm install langsmith openai

<cli_feedback> 実際に CLI でエラーが発生した場合、文書化されていない回避策が必要だった場合、出力が分かりにくかった場合、または機能が不足していた場合は、タスク内の問題ごとに簡潔な製品フィードバックを 1 件送信してください。通常の成功や、CLI と無関係な低い評価スコア/アプリケーションのエラーは報告しないでください。

CLI の要件: langsmith feedback には LangSmith CLI v0.2.58 以降が必要です。インストール済みのバージョンは langsmith --version で確認してください。

langsmith feedback --help で feedback <note> と --category が使えることを確認してください。使用できない場合は、生の HTTP や未リリースのビルドを使わず、フィードバックの送信を省略してください。既存の認証済みプロファイル、エンドポイント、ワークスペースを使用してください。フィードバックは BYOC リレー経由の場合も含め、LangSmith Cloud に送信されます。スタンドアロンのセルフホスト環境では送信を省略してください。ユーザー/組織の制限を守り、送信権限が不明な場合は事前に確認してください。

期待される CLI の動作と実際の動作、および回避策を、自分の言葉で要約してください。シークレット、顧客データ、評価器のプロンプト、データセットの内容、トレースのペイロード、完全なスタックトレース、コピーしたコマンド出力、生の引数、環境変数の値、ローカルパス、リソース識別子は絶対に送信しないでください。CLI によってバージョン/OS/アーキテクチャが追加されますが、ノートの内容は秘匿されません。安全に秘匿できない場合は送信を省略してください。

bug、feature-request、usability、documentation、other のいずれかを選択してください。これは CLI 製品へのフィードバックであり、評価器のスコアやコメントではありません。以下は形式の例のみです。実際に問題が発生していない限り送信しないでください:

langsmith feedback --category feature-request --format json "Please support selecting a single evaluator by ID when display names collide."

失敗したフィードバック送信やレート制限されたフィードバック送信を再試行しないでください。失敗を回避するために認証情報やエンドポイントを切り替えないでください。また、フィードバックを理由に元のタスクを中断しないでください。 </cli_feedback>

<crucial_requirement>

黄金律:実装前に確認する

重要: 評価器や抽出ロジックを書く前に、必ず以下を行ってください:

  1. サンプル入力でエージェントを実行し、実際の出力を取得する
  2. 出力を確認する - 出力を表示し、LangSmith のトレースをクエリして、正確な構造を把握する
  3. その後で初めて、その出力を処理するコードを書く

出力構造は、フレームワーク、エージェントの種類、設定によって大きく異なります。構造を決めつけず、必ず事前に確認してください。出力に必要なデータが含まれていない場合は、LangSmith のトレースをクエリし、実行からのデータ抽出方法を把握してください。 </crucial_requirement>

<evaluator_format>

オフライン評価器とオンライン評価器

オフライン評価器(データセットに紐づけます):

  • 関数シグネチャ:(run, example) — 実行結果とデータセットの例の両方を受け取ります
  • 用途:エージェントの出力をデータセット内の期待値と比較します
  • アップロード方法:--dataset "Dataset Name"

オンライン評価器(プロジェクトに紐づけます):

  • 関数シグネチャ:(run) — 実行結果のみを受け取り、exampleパラメーターは受け取りません
  • 用途:本番環境での実行をリアルタイムで品質チェックします(参照データなし)
  • アップロード方法:--project "Project Name"

重要 — 戻り値の形式:

  • 各評価器が返すメトリクスは1つのみです。複数のメトリクスを使う場合は、評価器関数を複数作成してください。
  • {"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による判定 — LLMを使って出力を評価します。主観的な品質(正確性、有用性、関連性)の評価に最適です。
  • カスタムコード — 決定論的なロジックを使います。客観的なチェック(完全一致、軌跡の検証、形式への準拠)に最適です。 </evaluator_types>

<llm_judge>

LLMによる判定評価器

langsmith evaluator create-llmを使って、サーバー管理のLLMによる判定の実行ルールを作成します。--model-configと、--datasetまたは--projectのいずれか一方が必要です。--promptと--schemaのJSONファイルを指定するか、--hub-refでPrompt Hubの参照先を指定してください。

LLMによる判定の実行ルールをネイティブCLIで操作する

以下のネイティブなライフサイクルでは、データセットまたはプロジェクトに紐づくLLMによる判定評価器を管理します。

作成

langsmith evaluator create-llm \
  --name "Accuracy Judge" \
  --dataset "My Dataset" \
  --prompt prompt.json \
  --schema schema.json \
  --model-config model.json

オンライン評価器の場合は--datasetの代わりに--projectを使用してください。判定プロンプトがPrompt Hubに保存されている場合は、--promptと--schemaの代わりに--hub-ref owner/prompt:latestを使用してください。

モデル設定

--model-config には、サーバーがサポートするシリアライズ済みモデル設定が必要です。ローカルの LangChain モデルコンストラクターから model.json を決して作成しないでください。正常に動作している LangSmith 評価器、LangSmith 評価器 UI、または対象環境の別の文書化されたソースから取得してください。評価器を作成または置き換える前に、対象サーバーでシリアライズ済みモデルクラスが許可されていることを確認してください。

langsmith evaluator get では、シリアライズ済みモデル設定の全体をエクスポートできません。Deserialization ... is not allowed というエラーで作成に失敗した場合、モデル設定にサーバーの許可リストで禁止されているクラスが含まれています。推測したシリアライズ済みオブジェクトで再試行しないでください。サポートされている設定を入手するか、環境管理者に問い合わせてください。

読み取り

# List all attached evaluator rules
langsmith evaluator list --format json

# Get every rule with this exact display name
langsmith evaluator get "Accuracy Judge"

# Narrow project rules with a project session ID
langsmith evaluator get "Accuracy Judge" --session-id <project-session-id>

get は表示名を基準にするため、複数のルールが返される場合があります。ルールのメタデータと選択された LLM フィールドは表示されますが、インラインのプロンプト、スキーマ、モデル設定全体はエクスポートされません。

更新/置き換え

個別の update サブコマンドはありません。同じ名前と対象を指定し、--replace を付けて create-llm を再実行してください。CLI から、該当するルールに PATCH を適用する前に確認が求められます。希望する LLM 設定全体をあらためて指定してください。

langsmith evaluator create-llm \
  --name "Accuracy Judge" \
  --dataset "My Dataset" \
  --prompt prompt-v2.json \
  --schema schema-v2.json \
  --model-config model-v2.json \
  --replace

削除

# Inspect every match before deleting
langsmith evaluator get "Accuracy Judge"
langsmith evaluator delete "Accuracy Judge"

delete は名前を基準に削除し、異なるデータセットやプロジェクトにまたがっていても、その表示名を持つすべてのワークスペース実行ルールを削除します。該当するルールが複数あり、そのうち 1 つだけを削除する必要がある場合は、ネイティブの delete コマンドを使わずに中止してください。ID を正確に指定した削除は、現時点では langsmith evaluator で公開されていません。

ローカル開発を素早く進める場合や、ローカルパッケージが必要なジャッジを使う場合は、ローカル評価器を定義し、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. データセットを調べ、想定されるフィールド名を把握します(上記のゴールデンルールを参照)
  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>

実行関数の定義

実行関数はエージェントを実行し、評価用の出力を返します。

重要 — 実行関数を最初にテストしてください: 評価器を作成する前に、必ず実行関数をテストし、実際の出力構造を確認してください。出力の形状は、フレームワーク、エージェントの種類、設定によって異なります。

デバッグのワークフロー:

  1. サンプル入力でエージェントを 1 回実行します
  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 } ``` ### 軌跡の記録

軌跡を評価するには、実行中にツール呼び出しを記録するよう、run 関数を実装する必要があります。

重要: 実行結果の形式は、フレームワークやエージェントの種類によって大きく異なります。実装する前に必ず確認してください。

LangGraph エージェント(LangChain OSS): stream_mode="debug" と subgraphs=True を使用して、ネストされたサブエージェントのツール呼び出しを記録します。

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 エージェント:

  1. まず出力を確認する — エージェントを実行し、結果の構造を確認します。軌跡データがすでに出力に含まれている場合があります(例:result.tool_calls、result.steps など)。
  2. コールバック/フック — フレームワークが実行コールバックに対応している場合は、呼び出しごとにツール名を記録するフックを登録します。
  3. 実行ログを解析する — 最終手段として、構造化ログやトレースデータからツール名を抽出します。

重要なのは、定義時ではなく実行時にツール名を記録することです。 </run_functions>

## Evaluator を LangSmith にアップロードする

重要 — 自動実行の動作: データセットにアップロードした Evaluator は、そのデータセットで実験を実行すると自動的に実行されます。evaluate() に渡す必要はありません。エージェントをデータセットに対して実行するだけで、アップロード済みの Evaluator が自動的に実行されます。

重要 — ローカルとアップロード済みの違い: アップロード済みの Evaluator は、パッケージへのアクセスが非常に制限されたサンドボックス環境で実行されます。組み込み/標準ライブラリのインポートのみを使用し、すべてのインポートを Evaluator 関数の本体内に記述してください。データセット(オフライン)Evaluator では、まず evaluate(evaluators=[...]) を使ってローカルでの実行を推奨します。これにより、すべてのパッケージにアクセスできます。

重要 — コード Evaluator と構造化 Evaluator:

  • コード Evaluator: langsmith evaluator upload でアップロードします。外部パッケージを使えない制限付き環境で実行され、決定論的なロジックに適しています。
  • 構造化 Evaluator(LLM-as-Judge): モデル設定と、プロンプト/スキーマファイルまたは --hub-ref を使って、langsmith evaluator create-llm で作成します。

重要 — 適切な対象を選択する:

  • --dataset:(run, example) シグネチャを持つオフライン Evaluator。期待値との比較に使用します。
  • --project:(run) シグネチャを持つオンライン Evaluator。リアルタイムの品質チェックに使用します。

いずれかを指定する必要があります。グローバル Evaluator には対応していません。

# List all attached evaluator rules
langsmith evaluator list

# Inspect matching rules by display name
langsmith evaluator get "Trajectory Match"

# Inspect project rules by session ID (not project name)
langsmith evaluator get --session-id <project-session-id>

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

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

# Replace an existing rule with the same name and target (prompts first)
langsmith evaluator upload \
  --name "Trajectory Match" \
  --function trajectory_evaluator \
  --dataset "My Dataset" \
  --replace \
  my_evaluators.py

# Delete by display name (prompts first)
langsmith evaluator delete "Trajectory Match"

重要 — 安全性に関する注意:

  • upload --replace と create-llm --replace は、まず一致するルールとプロンプトをパッチします。
  • delete NAME は、その表示名を持つワークスペース内のすべてのルールを削除します。複数の対象にまたがる可能性があるため、先に get NAME を実行して、一致するすべての項目を確認してください。
  • ユーザーから明示的な依頼がない限り、--yes フラグは絶対に使用しないでください。
CRUD の検証

ユーザーから依頼されたライフサイクル操作のみを検証してください。

  • CLI と SDK の呼び出しが、同じ環境とワークスペースを対象にしていることを確認します。
  • list と get を使って作成を検証します。
  • 依頼があった場合は、--replace を使った置き換えを検証します。
  • 削除のテストには、一意で破棄可能な名前と明示的な許可がある場合に限り実行します。
  • 名前が複数のルールに一致し、目的の対象を安全に特定できない場合は中止します。

<best_practices>

  1. LLM 判定には構造化出力を使用する — 自由記述テキストの解析より信頼性が高くなります。
  2. データセットの種類に合った Evaluator を選ぶ
    • 最終応答 → 品質評価には LLM as Judge
    • 軌跡 → シーケンス評価にはカスタムコード
  3. LLM 判定には非同期処理を使用する — 評価を並列実行できます。
  4. Evaluator を個別にテストする — まず既知の良い例/悪い例で検証します。
  5. 適切な言語を選ぶ
    • Python:Python エージェント、LangChain 統合に使用します。
    • JavaScript:TypeScript/Node.js エージェントに使用します。 </best_practices>

<running_evaluations>

評価の実行

アップロード済みの Evaluator は実験を実行すると自動的に実行されるため、コードは不要です。ローカル Evaluator は、開発/テスト用に直接渡します。

```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",
});
## よくある問題

期待した結果と出力が一致しない: LangSmith のトレースを確認してください。各ステップの正確な入力と出力が記録されています。確認した内容と、抽出しようとしている内容を比較してください。

評価器ごとにメトリクスは 1 つ: {"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)

コメント