// 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(); } }