Agent Framework には、エージェントの品質、安全性、正確性を測定できる評価フレームワークが組み込まれています。 開発時に高速なローカル チェックを実行したり、Azure AI Foundryのクラウドベースのエバリュエーターを使用して運用グレードの評価を行ったり、両方を 1 回の評価実行で組み合わせたりすることができます。
評価フレームワークは、いくつかの重要な原則を中心に設計されています。
- プロバイダーに依存しない — コア評価の種類とオーケストレーション関数は、任意の評価プロバイダーと連携します。
- ゼロ摩擦 - 最小限のコードで"エージェントがある"から"私は評価結果を得る"に進みます。
- 段階的な開示 - 単純なシナリオでは、ほぼゼロのコードが必要です。 高度なシナリオは、同じプリミティブに基づいて構築されます。
主要な概念
評価フレームワークは、次の 3 種類に基づいて構築されています。
| タイプ | Purpose |
|---|---|
| EvalItem | 評価には1つの項目があり、完全な会話を包括し、分割戦略を用いてクエリと応答を導き出します。 |
| エバリュエータ | 項目 (ローカル チェック、Azure AI Foundry、またはカスタム実装) をスコア付けするプロバイダー。 |
| EvalResults | 評価実行の集計結果 - 成功/失敗数、項目ごとの詳細、およびオプションのポータル リンク。 |
.NETでは、評価フレームワークは Microsoft.Extensions.AI.Evaluation に基づいて構築されます。 エバリュエーターは IAgentEvaluator インターフェイスを実装し、オーケストレーションは AIAgent と Runの拡張メソッドを通じて提供されます。
コア型は、Microsoft.Agents.AI 名前空間にあります。
using Microsoft.Agents.AI;
Pythonでは、評価フレームワークはコア agent_framework パッケージの一部です。 エバリュエーターは Evaluator プロトコルを実装し、オーケストレーションは evaluate_agent() および evaluate_workflow() 関数を介して提供されます。
from agent_framework import (
evaluate_agent,
evaluate_workflow,
EvalItem,
EvalResults,
LocalEvaluator,
)
ローカル エバリュエーター
LocalEvaluator は、API 呼び出しなしでローカルでチェックを実行します。内部ループ開発、CI スモーク テスト、高速反復に最適です。 これは、任意の数のチェック関数を受け入れ、すべての項目にそれぞれを適用します。
組み込みチェック
Agent Framework には、一般的なシナリオの組み込みチェックが付属しています。
using Microsoft.Agents.AI;
var local = new LocalEvaluator(
EvalChecks.KeywordCheck("weather", "temperature"), // Response must contain these keywords
EvalChecks.ToolCalledCheck("get_weather") // Agent must have called this tool
);
カスタム関数エバリュエーター
FunctionEvaluator.Create()を使用して、エバリュエーター チェックとして関数をラップします。 必要なデータに応じて、複数のオーバーロードを使用できます。
using Microsoft.Agents.AI;
var local = new LocalEvaluator(
// Simple: check only the response text
FunctionEvaluator.Create("is_concise",
(string response) => response.Split(' ').Length < 500),
// With expected output: compare against ground truth
FunctionEvaluator.Create("mentions_city",
(string response, string? expectedOutput) =>
expectedOutput != null && response.Contains(expectedOutput, StringComparison.OrdinalIgnoreCase)),
// Full context: access the complete EvalItem
FunctionEvaluator.Create("used_search",
(EvalItem item) => item.Conversation.Any(m =>
m.Text?.Contains("search", StringComparison.OrdinalIgnoreCase) == true))
);
組み込みチェック
Agent Framework には、一般的なシナリオの組み込みチェックが付属しています。
| 検査 | 動作内容 |
|---|---|
keyword_check(*keywords) |
応答には、指定されたすべてのキーワードが含まれている必要があります |
tool_called_check(*tool_names) |
エージェントは、指定されたツールを呼び出している必要があります |
tool_calls_present |
すべての expected_tool_calls 名が会話に表示されます (順序なし、エクストラ OK) |
tool_call_args_match |
名前と引数の一致に基づくツール呼び出しが期待されます (引数のサブセットの一致) |
from agent_framework import (
LocalEvaluator,
keyword_check,
tool_called_check,
tool_calls_present,
tool_call_args_match,
)
local = LocalEvaluator(
keyword_check("weather", "temperature"), # Response must contain these keywords
tool_called_check("get_weather"), # Agent must have called this tool
tool_calls_present, # All expected tool call names were made
tool_call_args_match, # Expected tool calls match on name + args
)
カスタム関数エバリュエーター
@evaluatorデコレーターを使用して、エバリュエーター チェックとして任意の関数をラップします。 関数の パラメーター名 によって、 EvalItemから受け取るデータが決まります。
from agent_framework import evaluator, LocalEvaluator
@evaluator
def is_concise(response: str) -> bool:
"""Check response is under 500 words."""
return len(response.split()) < 500
@evaluator
def mentions_city(response: str, expected_output: str) -> bool:
"""Check response contains the expected city name."""
return expected_output.lower() in response.lower()
@evaluator
def used_tools(conversation: list, tools: list) -> float:
"""Score based on tool usage. Returns 0.0–1.0 (>= 0.5 passes)."""
tool_calls = [c for m in conversation for c in (m.contents or []) if c.type == "function_call"]
return min(len(tool_calls) / max(len(tools), 1), 1.0)
local = LocalEvaluator(is_concise, mentions_city, used_tools)
サポートされているパラメーター名: query、 response、 expected_output、 expected_tool_calls、 conversation、 tools、 context。
戻り値の型: bool、float (≥ 0.5 = 合格)、dict、score または passed キーを使用したCheckResult。 非同期関数は自動的に処理されます。
Azure AI Foundry 評価者
FoundryEvals は、Azure AI Foundry の評価サービスに接続して、クラウドベースの LLM の判断評価を行います。 結果は、ダッシュボードと比較ビューを使用して Foundry ポータルで表示できます。
using Microsoft.Agents.AI.AzureAI;
var foundry = new FoundryEvals(chatConfiguration, FoundryEvals.Relevance, FoundryEvals.Coherence);
from agent_framework.foundry import FoundryEvals
evals = FoundryEvals(
project_client=project_client,
model="gpt-4o",
evaluators=[FoundryEvals.RELEVANCE, FoundryEvals.COHERENCE],
)
既定では、 FoundryEvals は 関連性、 一貫性、 タスクの準拠エバリュ エーターを実行します。 項目にツール定義が含まれている場合、 ツール呼び出しの精度が自動的に追加されます。
使用可能な評価者
FoundryEvals には、すべての組み込みエバリュエーター名の定数が用意されています。
| カテゴリ | エバリュエーター |
|---|---|
| エージェントの動作 |
intent_resolution、task_adherence、task_completion、task_navigation_efficiency |
| ツールの使用方法 |
tool_call_accuracy、tool_selection、tool_input_accuracy、tool_output_utilization、tool_call_success |
| Quality |
coherence、 fluency、 relevance、 groundedness、 response_completeness、 similarity |
| Safety |
violence、sexual、self_harm、hate_unfairness |
注
FoundryEvals には、AI モデルのデプロイを含むAzure AI Foundry プロジェクトが必要です。
modelパラメーターは、LLM ジャッジとして使用するモデルを指定します。
エージェントを評価する
最も単純な評価シナリオでは、テスト クエリに対してエージェントを実行し、応答をスコア付けします。 統計的に意味のある評価のために、複数の多様なクエリを提供します。
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.Foundry;
var foundry = new FoundryEvals(chatConfiguration, FoundryEvals.Relevance, FoundryEvals.Coherence);
AgentEvaluationResults results = await agent.EvaluateAsync(
new[]
{
"What's the weather in Seattle?",
"Plan a weekend trip to Portland",
"What restaurants are near Pike Place?",
},
foundry);
results.AssertAllPassed(); // Throws if any item failed
EvaluateAsync は、 AIAgentの拡張メソッドです。 クエリごとに 1 回エージェントを実行し、各対話を EvalItemに変換し、バッチをエバリュエーターに渡します。
from agent_framework import evaluate_agent
from agent_framework.foundry import FoundryEvals
evals = FoundryEvals(
project_client=project_client,
model="gpt-4o",
evaluators=[FoundryEvals.RELEVANCE, FoundryEvals.COHERENCE],
)
results = await evaluate_agent(
agent=my_agent,
queries=[
"What's the weather in Seattle?",
"Plan a weekend trip to Portland",
"What restaurants are near Pike Place?",
],
evaluators=evals,
)
for r in results:
print(f"{r.provider}: {r.passed}/{r.total}")
r.raise_for_status() # Raises EvalNotPassedError if any item failed
evaluate_agent はクエリごとに 1 回エージェントを実行し、各対話を EvalItemに変換し、バッチをエバリュエーターに渡します。 エバリュエーター プロバイダーごとに 1 つの EvalResults を返します。
繰り返しを使用して一貫性を測定する
各クエリを複数回実行して、非決定論的な動作を検出します。
AgentEvaluationResults results = await agent.EvaluateAsync(
new[] { "What's the weather in Seattle?" },
foundry,
numRepetitions: 3); // Each query runs 3 times independently
// Results contain 3 items (1 query × 3 repetitions)
results = await evaluate_agent(
agent=my_agent,
queries=["What's the weather in Seattle?"],
evaluators=evals,
num_repetitions=3, # Each query runs 3 times independently
)
# Results contain 3 items (1 query × 3 repetitions)
期待される出力で評価する
正しさを評価するために、真の信頼できる答えを提供します。 期待される出力は、クエリと位置的に対になっています。
AgentEvaluationResults results = await agent.EvaluateAsync(
new[] { "What's 2+2?", "Capital of France?" },
foundry,
expectedOutput: new[] { "4", "Paris" });
必要なツール呼び出しを指定することもできます。
AgentEvaluationResults results = await agent.EvaluateAsync(
new[] { "What's the weather in NYC?" },
new LocalEvaluator(EvalChecks.ToolCalledCheck("get_weather")),
expectedToolCalls: new[]
{
new[] { new ExpectedToolCall("get_weather") },
});
from agent_framework import evaluate_agent, ExpectedToolCall
results = await evaluate_agent(
agent=my_agent,
queries=["What's 2+2?", "Capital of France?"],
expected_output=["4", "Paris"],
evaluators=evals,
)
必要なツール呼び出しを指定することもできます。
results = await evaluate_agent(
agent=my_agent,
queries=["What's the weather in NYC?"],
expected_tool_calls=[ExpectedToolCall("get_weather", {"location": "NYC"})],
evaluators=local,
)
既存の応答を評価する
ログまたは以前の実行からのエージェント応答が既にある場合は、エージェントを再実行せずに直接評価します。
var response = await agent.RunAsync(new[] { new ChatMessage(ChatRole.User, "What's the weather?") });
AgentEvaluationResults results = await agent.EvaluateAsync(
new[] { response },
new[] { "What's the weather?" },
foundry);
from agent_framework import Message, evaluate_agent
response = await agent.run([Message("user", ["What's the weather?"])])
results = await evaluate_agent(
agent=agent,
responses=response,
queries="What's the weather?",
evaluators=evals,
)
会話分割戦略
複数ターンの会話は、評価のためにクエリと応答の半分に分割する必要があります。 分割方法によって、 評価対象が決まります。
| 戦略 | 行動 | 最適な用途 |
|---|---|---|
| 最終ターン (既定) | 最後のユーザー メッセージで分割します。 それまでのすべてがクエリ コンテキストです。その後のすべてが応答です。 | 特定の時点での応答品質 |
| 完全 | 最初のユーザー メッセージはクエリです。残りの部分全体が応答です。 | タスクの完了と全体的な軌道 |
| ターンごと | 各ユーザーとアシスタントのやり取りは、累積されたコンテキストを考慮して個別に評価されます。 | きめ細かい分析 |
// Full conversation as context
AgentEvaluationResults results = await agent.EvaluateAsync(
new[] { "Plan a 3-day trip to Paris" },
foundry,
splitter: ConversationSplitters.Full);
// Per-turn: each exchange scored independently
var items = EvalItem.PerTurnItems(conversation);
var perTurnResults = await evaluator.EvaluateAsync(items);
IConversationSplitterを実装することで、カスタム スプリッターを実装することもできます。
public class SplitBeforeToolCall : IConversationSplitter
{
public (IReadOnlyList<ChatMessage> QueryMessages, IReadOnlyList<ChatMessage> ResponseMessages) Split(
IReadOnlyList<ChatMessage> conversation)
{
// Custom split logic
for (int i = 0; i < conversation.Count; i++)
{
if (conversation[i].Text?.Contains("tool_call") == true)
return (conversation.Take(i).ToList(), conversation.Skip(i).ToList());
}
return ConversationSplitters.LastTurn.Split(conversation);
}
}
from agent_framework import evaluate_agent, ConversationSplit
# Full conversation as context
results = await evaluate_agent(
agent=agent,
queries=["Plan a 3-day trip to Paris"],
evaluators=evals,
conversation_split=ConversationSplit.FULL,
)
# Per-turn: each exchange scored independently
from agent_framework import EvalItem
items = EvalItem.per_turn_items(conversation)
# Pass items directly to an evaluator
per_turn_results = await evaluator.evaluate(items)
カスタムスプリッター(会話を受け取り、(query_messages, response_messages)を返すことができる任意の呼び出し可能なもの)を提供することもできます。
def split_before_memory(conversation):
"""Split just before a memory-retrieval tool call."""
for i, msg in enumerate(conversation):
for c in msg.contents or []:
if c.type == "function_call" and c.name == "retrieve_memory":
return conversation[:i], conversation[i:]
# Fallback to default
return EvalItem._split_last_turn_static(conversation)
results = await evaluate_agent(
agent=agent,
queries=queries,
evaluators=evals,
conversation_split=split_before_memory,
)
ワークフローを評価する
エージェントごとの内訳を使用してマルチエージェント ワークフローを評価します。 フレームワークは、各サブエージェントの相互作用を抽出し、ワークフローの全体的な出力と共に個別に評価します。
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.AzureAI;
Run run = await workflowRunner.RunAsync(workflow, "Plan a trip to Paris");
AgentEvaluationResults results = await run.EvaluateAsync(
new FoundryEvals(chatConfiguration, FoundryEvals.Relevance));
Console.WriteLine($"Overall: {results.Passed}/{results.Total}");
// Per-agent breakdown
if (results.SubResults != null)
{
foreach (var (name, sub) in results.SubResults)
{
Console.WriteLine($" {name}: {sub.Passed}/{sub.Total}");
}
}
results.AssertAllPassed();
from agent_framework import evaluate_workflow
from agent_framework.foundry import FoundryEvals
evals = FoundryEvals(project_client=project_client, model="gpt-4o")
result = await workflow.run("Plan a trip to Paris")
eval_results = await evaluate_workflow(
workflow=workflow,
workflow_result=result,
evaluators=evals,
)
for r in eval_results:
print(f"{r.provider}: {r.passed}/{r.total}")
for name, sub in r.sub_results.items():
print(f" {name}: {sub.passed}/{sub.total}")
queriesを直接渡すこともできます。フレームワークによってワークフローが実行されます。
eval_results = await evaluate_workflow(
workflow=workflow,
queries=["Plan a trip to Paris", "Book a flight to London"],
evaluators=evals,
)
複数のエバリュエーターを混在する
ローカル チェックとクラウドベースのエバリュエーターを 1 つの評価で一緒に実行します。 各エバリュエーターは、独自の EvalResultsを生成します。
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.AzureAI;
IReadOnlyList<AgentEvaluationResults> results = await agent.EvaluateAsync(
new[] { "What's the weather in Seattle?" },
evaluators: new IAgentEvaluator[]
{
new LocalEvaluator(
EvalChecks.KeywordCheck("weather"),
FunctionEvaluator.Create("is_helpful", (string r) => r.Split(' ').Length > 10)),
new FoundryEvals(chatConfiguration, FoundryEvals.Relevance, FoundryEvals.Coherence),
});
// results[0] = local evaluator results
// results[1] = Foundry evaluator results
foreach (var r in results)
{
Console.WriteLine($"{r.Provider}: {r.Passed}/{r.Total}");
}
from agent_framework import evaluate_agent, evaluator, LocalEvaluator, keyword_check
from agent_framework.foundry import FoundryEvals
@evaluator
def is_helpful(response: str) -> bool:
return len(response.split()) > 10
foundry = FoundryEvals(
project_client=project_client,
model="gpt-4o",
evaluators=[FoundryEvals.RELEVANCE, FoundryEvals.COHERENCE],
)
results = await evaluate_agent(
agent=agent,
queries=["What's the weather in Seattle?"],
evaluators=[
LocalEvaluator(is_helpful, keyword_check("weather")),
foundry,
],
)
# results[0] = local evaluator results
# results[1] = Foundry evaluator results
for r in results:
print(f"{r.provider}: {r.passed}/{r.total}")
MEAI 評価者
.NET評価フレームワークは、Microsoft.Extensions.AI.Evaluationエバリュエーターと直接統合されています。 MEAIの品質と安全性のエバリュエーターは、アダプタなしで動作します。
using Microsoft.Extensions.AI.Evaluation;
using Microsoft.Extensions.AI.Evaluation.Quality;
using Microsoft.Extensions.AI.Evaluation.Safety;
// Quality evaluators
AgentEvaluationResults results = await agent.EvaluateAsync(
new[] { "What's the weather?" },
new CompositeEvaluator(
new RelevanceEvaluator(),
new CoherenceEvaluator(),
new GroundednessEvaluator()),
chatConfiguration: new ChatConfiguration(evalClient));
// Safety evaluators
AgentEvaluationResults safetyResults = await agent.EvaluateAsync(
new[] { "What's the weather?" },
new ContentHarmEvaluator(),
chatConfiguration: new ChatConfiguration(evalClient));
ヒント
MEAI エバリュエーターを使用する場合は、評価モデル用に構成されたチャット クライアントで chatConfiguration パラメーターを指定します。 このクライアントは、LLM-as-judge エバリュエーターによって応答をスコア付けするために使用されます。
注
この機能の Go サポートは近日公開予定です。 最新の状態については、 Agent Framework Go リポジトリ を参照してください。