// SPDX-License-Identifier: MIT
// Copyright (c) 2026 AgentEval Contributors
using AgentEval.Core;
using AgentEval.Exporters;
using AgentEval.MAF;
using AgentEval.Models;
using Azure.AI.OpenAI;
using Microsoft.Extensions.AI;
namespace AgentEval.Samples;
///
/// Sample F7: Cross-Framework Evaluation โ Universal IChatClient Adapter
///
/// Demonstrates the IChatClient.AsEvaluableAgent() one-liner that makes
/// **any LLM provider** evaluable by AgentEval โ zero boilerplate:
/// - Azure OpenAI, OpenAI, Ollama, LM Studio, vLLM, Groq, Together.ai, etc.
/// - Batch evaluation across multiple test cases
/// - Export to Markdown via TestSummary.ToEvaluationReport()
///
/// For MAF tool-calling agents, see Samples 2โ3, 9โ10, 12.
/// For Semantic Kernel integration, see the AgentEval.NuGetConsumer project.
///
/// ๐ค Requires a model provider (Azure OpenAI, Bitdeer, or any OpenAI-compatible endpoint โ see AIConfig)
/// โฑ๏ธ Time to understand: 3 minutes
///
public static class CrossFrameworkEvaluation
{
public static async Task RunAsync()
{
PrintHeader();
if (!AIConfig.IsConfigured)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("โ This sample requires a model provider (Azure OpenAI, Bitdeer, or any OpenAI-compatible endpoint).");
Console.WriteLine(" Set a provider: AZURE_OPENAI_* or BITDEER_API_KEY or OPENAI_COMPATIBLE_* (see AIConfig).");
Console.ResetColor();
SampleOutcome.Skip("no chat provider configured");
return;
}
// โโโ Step 1: Create any IChatClient โโโโโโโโโโโโโโโโโโโโโโโโโโ
Console.WriteLine("๐ Step 1: Create an IChatClient");
Console.WriteLine(" Any provider implementing IChatClient works:");
Console.WriteLine(" โข Azure OpenAI โ new AzureOpenAIClient(...)");
Console.WriteLine(" โข Ollama โ new OllamaChatClient(...)");
Console.WriteLine(" โข Semantic Kernel โ kernel.GetRequiredService()");
Console.WriteLine(" โข LM Studio โ new OpenAIChatClient(...)");
Console.WriteLine();
IChatClient chatClient = AIConfig.CreateChatClient(AIConfig.ModelDeployment);
Console.WriteLine($" โ
Using: {AIConfig.ProviderName} ({AIConfig.ModelDeployment})\n");
// โโโ Step 2: One-liner adapter โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Console.WriteLine("๐ Step 2: Convert to evaluable agent with AsEvaluableAgent()");
var agent = chatClient.AsEvaluableAgent(
name: AIConfig.ModelDeployment,
systemPrompt: "You are a helpful assistant. Answer questions concisely.");
Console.WriteLine($" โ
Agent '{agent.Name}' ready for evaluation\n");
// โโโ Step 3: Define test cases โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Console.WriteLine("๐ Step 3: Define test cases");
var testCases = new List
{
new() { Name = "Capital City", Input = "What is the capital of France?",
ExpectedOutputContains = "Paris", PassingScore = 70 },
new() { Name = "Simple Math", Input = "What is 7 * 8?",
ExpectedOutputContains = "56", PassingScore = 70 },
new() { Name = "Color of Sky", Input = "What color is the sky on a clear day?",
ExpectedOutputContains = "blue", PassingScore = 70 }
};
foreach (var tc in testCases)
Console.WriteLine($" โข {tc.Name}: \"{tc.Input}\" โ expects \"{tc.ExpectedOutputContains}\"");
Console.WriteLine();
// โโโ Step 4: Batch evaluation โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Console.WriteLine("๐ Step 4: Run batch evaluation");
var harness = new MAFEvaluationHarness(verbose: true);
var results = new List();
foreach (var testCase in testCases)
results.Add(await harness.RunEvaluationAsync(agent, testCase));
var summary = new TestSummary("Cross-Framework Evaluation", results);
Console.WriteLine($"\n {(summary.FailedCount == 0 ? "โ
" : "โ")} {summary.TotalCount} tests completed: " +
$"{summary.PassedCount} passed, {summary.FailedCount} failed\n");
foreach (var failed in results.Where(r => !r.Passed))
SampleOutcome.Fail($"'{failed.TestName}' failed: {failed.Details}");
// โโโ Step 5: Export to Markdown โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Console.WriteLine("๐ Step 5: Export results to Markdown");
var report = summary.ToEvaluationReport(
agentName: agent.Name, modelName: AIConfig.ModelDeployment,
endpoint: AIConfig.Endpoint.ToString());
var exporter = ResultExporterFactory.Create(ExportFormat.Markdown);
using var stream = new MemoryStream();
await exporter.ExportAsync(report, stream);
stream.Position = 0;
using var reader = new StreamReader(stream);
var markdown = await reader.ReadToEndAsync();
Console.ForegroundColor = ConsoleColor.DarkGray;
Console.WriteLine(" โโโ Markdown Export โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ");
foreach (var line in markdown.Split('\n').Take(20))
Console.WriteLine($" โ {line.TrimEnd()}");
if (markdown.Split('\n').Length > 20)
Console.WriteLine(" โ ... (truncated)");
Console.WriteLine(" โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ");
Console.ResetColor();
Console.WriteLine();
// โโโ Key Takeaways โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Console.WriteLine("๐ก KEY TAKEAWAYS:");
Console.WriteLine(" โข IChatClient.AsEvaluableAgent() โ one line to make any provider evaluable");
Console.WriteLine(" โข Works with ANY provider: Azure OpenAI, Ollama, Semantic Kernel, etc.");
Console.WriteLine(" โข TestSummary.ToEvaluationReport() โ Markdown, JUnit, JSON, CSV, TRX");
Console.WriteLine(" โข Same evaluation harness, metrics, and export for every framework");
Console.WriteLine();
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine("๐ SEE ALSO:");
Console.WriteLine(" โข Samples 2โ3: MAF tool-calling agents with fluent assertions");
Console.WriteLine(" โข Samples 9โ10: Workflow evaluation with tool tracking");
Console.WriteLine(" โข NuGetConsumer project: Real Semantic Kernel + AgentEval integration");
Console.ResetColor();
Console.WriteLine();
}
// โโโ Header โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
private static void PrintHeader()
{
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine(@"
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ
โ ๐ SAMPLE F7: CROSS-FRAMEWORK EVALUATION โ
โ Universal IChatClient Adapter ยท Any Provider ยท Export โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
");
Console.ResetColor();
}
}