Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Bu öğreticide, OpenAI modelinin sohbet yanıtını değerlendirmek için bir MSTest uygulaması oluşturacaksınız. Test uygulaması değerlendirmeleri gerçekleştirmek, model yanıtlarını önbelleğe almak ve raporlar oluşturmak için Microsoft.Extensions.AI.Evaluation kitaplıklarını kullanır. Öğreticide hem yerleşik hem de özel değerlendiriciler kullanılır. Yerleşik kalite değerlendiricileri (Microsoft.Extensions.AI.Evaluation.Quality paketinden) değerlendirmeleri gerçekleştirmek için bir LLM kullanır; özel değerlendirici yapay zeka kullanmaz.
Önkoşullar
- .NET 8 veya sonraki bir sürümü
- Visual Studio Code (isteğe bağlı)
Yapay zeka hizmetini yapılandırma
Azure portalını kullanarak bir Azure OpenAI hizmeti ve modeli sağlamak için Azure OpenAI Hizmeti kaynağı oluşturma ve dağıtma makalesindeki adımları tamamlayın. "Model dağıtma" adımında gpt-4o modeli seçin.
Test uygulamasını oluşturma
Yapay zeka modeline bağlanan bir MSTest projesi oluşturmak için gpt-4o aşağıdaki adımları tamamlayın.
Terminal penceresinde, uygulamanızı oluşturmak istediğiniz dizine gidin ve komutuyla
dotnet newyeni bir MSTest uygulaması oluşturun:dotnet new mstest -o TestAIWithReportingTestAIWithReportingdizinine gidin ve gerekli paketleri uygulamanıza ekleyin:dotnet add package Azure.AI.OpenAI dotnet add package Azure.Identity dotnet add package Microsoft.Extensions.AI.Abstractions dotnet add package Microsoft.Extensions.AI.Evaluation dotnet add package Microsoft.Extensions.AI.Evaluation.Quality dotnet add package Microsoft.Extensions.AI.Evaluation.Reporting dotnet add package Microsoft.Extensions.AI.OpenAI --prerelease dotnet add package Microsoft.Extensions.Configuration dotnet add package Microsoft.Extensions.Configuration.UserSecretsAzure OpenAI uç noktanız, model adınız ve kiracı kimliğiniz için uygulama gizli dizilerini eklemek amacıyla aşağıdaki komutları çalıştırın.
dotnet user-secrets init dotnet user-secrets set AZURE_OPENAI_ENDPOINT <your-Azure-OpenAI-endpoint> dotnet user-secrets set AZURE_OPENAI_GPT_NAME gpt-4o dotnet user-secrets set AZURE_TENANT_ID <your-tenant-ID>Ortamınıza bağlı olarak kiracı kimliği gerekli olmayabilir. Bu durumda, onu DefaultAzureCredential kodundan kaldırın.
Yeni uygulamayı kendi seçtiğiniz düzenleyicide açın.
Test uygulaması kodunu ekleme
Test1.cs dosyasını MyTests.cs olarak yeniden adlandırın, sonra dosyayı açın ve sınıfını olarak
MyTestsyeniden adlandırın. BoşTestMethod1yöntemi silin.Dosyanın en üstüne gerekli
usingyönergeleri ekleyin.using Azure.AI.OpenAI; using Azure.Identity; using Microsoft.Extensions.AI.Evaluation; using Microsoft.Extensions.AI; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.AI.Evaluation.Reporting.Storage; using Microsoft.Extensions.AI.Evaluation.Reporting; using Microsoft.Extensions.AI.Evaluation.Quality;TestContext özelliğini sınıfına ekleyin.
// The value of the TestContext property is populated by MSTest. public TestContext? TestContext { get; set; }GetAzureOpenAIChatConfigurationyöntemini ekleyin, bu yöntem değerlendirme aracının modelle iletişim kurmasını sağlayan IChatClient'yi oluşturur.private static ChatConfiguration GetAzureOpenAIChatConfiguration() { IConfigurationRoot config = new ConfigurationBuilder().AddUserSecrets<MyTests>().Build(); string endpoint = config["AZURE_OPENAI_ENDPOINT"]; string model = config["AZURE_OPENAI_GPT_NAME"]; string tenantId = config["AZURE_TENANT_ID"]; // Get an instance of Microsoft.Extensions.AI's <see cref="IChatClient"/> // interface for the selected LLM endpoint. AzureOpenAIClient azureClient = new( new Uri(endpoint), new DefaultAzureCredential(new DefaultAzureCredentialOptions() { TenantId = tenantId })); IChatClient client = azureClient.GetChatClient(deploymentName: model).AsIChatClient(); // Create an instance of <see cref="ChatConfiguration"/> // to communicate with the LLM. return new ChatConfiguration(client); }Raporlama işlevini ayarlayın.
private string ScenarioName => $"{TestContext!.FullyQualifiedTestClassName}.{TestContext.TestName}"; private static string ExecutionName => $"{DateTime.Now:yyyyMMddTHHmmss}"; private static readonly ReportingConfiguration s_defaultReportingConfiguration = DiskBasedReportingConfiguration.Create( storageRootPath: "C:\\TestReports", evaluators: GetEvaluators(), chatConfiguration: GetAzureOpenAIChatConfiguration(), enableResponseCaching: true, executionName: ExecutionName);Senaryo adı
Senaryo adı, geçerli test yönteminin tam adı olarak ayarlanır. Ancak, CreateScenarioRunAsync(String, String, IEnumerable<String>, IEnumerable<String>, CancellationToken) öğesini çağırdığınızda bunu istediğiniz herhangi bir dizeye ayarlayabilirsiniz. Senaryo adı seçme konusunda dikkat edilmesi gereken bazı noktalar şunlardır:
- Disk tabanlı depolama kullanılırken senaryo adı, ilgili değerlendirme sonuçlarının depolandığı klasörün adı olarak kullanılır. Bu nedenle, adın oldukça kısa tutulması ve dosya ve dizin adlarında izin verilmeyen karakterlerden kaçınılması iyi bir fikirdir.
- Varsayılan olarak, oluşturulan değerlendirme raporu senaryo adlarını üzerine
.böler, böylece sonuçlar uygun gruplandırma, iç içe yerleştirme ve toplama ile hiyerarşik bir görünümde görüntülenebilir. Bu, özellikle senaryo adının ilgili test yönteminin tam adına ayarlandığı durumlarda kullanışlıdır, çünkü sonuçların hiyerarşideki ad alanlarına ve sınıf adlarına göre gruplandırılmasına izin verir. Ancak, senaryolarınız için en uygun raporlama hiyerarşisini oluşturmak için kendi özel senaryo adlarınıza nokta (.) ekleyerek de bu özelliğin avantajlarından yararlanabilirsiniz.
Yürütme adı
Yürütme adı, değerlendirme sonuçları depolandığında aynı değerlendirme çalıştırmasının (veya test çalıştırmasının) parçası olan değerlendirme sonuçlarını gruplandırmak için kullanılır. oluştururken ReportingConfigurationbir yürütme adı sağlamazsanız, tüm değerlendirme çalıştırmaları aynı varsayılan yürütme adını
Defaultkullanır. Bir çalıştırmanın sonuçları, bir sonraki çalıştırmayla üzerine yazılır ve böylece farklı çalıştırmalardaki sonuçları karşılaştırma imkanını kaybedersiniz.Bu örnekte yürütme adı olarak bir zaman damgası kullanılır. Projenizde birden fazla test varsa, testlerde kullanılan tüm raporlama yapılandırmalarında aynı yürütme adını kullanarak sonuçların doğru gruplandığından emin olun.
Daha gerçekçi bir senaryoda, farklı derlemelere yayılan ve farklı test işlemlerinde yürütülen değerlendirme amaçlı testlerde aynı yürütme adını paylaşmak isteyebilirsiniz. Bu gibi durumlarda, testleri çalıştırmadan önce ortam değişkenini uygun bir yürütme adıyla (CI/CD sisteminiz tarafından atanan geçerli derleme numarası gibi) güncelleştirmek için bir betik kullanabilirsiniz. Ya da derleme sisteminiz monoton olarak artan derleme dosyası sürümleri oluşturuyorsa,
dosyasını test kodunun içinden okuyabilir ve bunu farklı ürün sürümleri arasında sonuçları karşılaştırmak için yürütme adı olarak kullanabilirsiniz. Raporlama yapılandırması
A ReportingConfiguration tanımlar:
- Çağrılarak CreateScenarioRunAsync(String, String, IEnumerable<String>, IEnumerable<String>, CancellationToken) oluşturulan her ScenarioRun için çağrılması gereken değerlendirici kümesi.
- Değerlendiricilerin kullanması gereken LLM uç noktası (bkz ReportingConfiguration.ChatConfiguration. ).
- Senaryo çalıştırma sonuçlarının nasıl ve nerede depolanması gerekir.
- Senaryo çalıştırmalarıyla ilgili LLM yanıtlarının nasıl önbelleğe alınacağı belirlenmelidir.
- Sonuçların raporlanması sırasında kullanılacak senaryo çalıştırma adı.
Bu test disk tabanlı raporlama yapılandırması kullanır.
Ayrı bir dosyada, IEvaluator öğesini uygulayan özel bir değerlendirici olan
WordCountEvaluatorsınıfını ekleyin.using System.Text.RegularExpressions; using Microsoft.Extensions.AI; using Microsoft.Extensions.AI.Evaluation; namespace TestAIWithReporting; public class WordCountEvaluator : IEvaluator { public const string WordCountMetricName = "Words"; public IReadOnlyCollection<string> EvaluationMetricNames => [WordCountMetricName]; /// <summary> /// Counts the number of words in the supplied string. /// </summary> private static int CountWords(string? input) { if (string.IsNullOrWhiteSpace(input)) { return 0; } MatchCollection matches = Regex.Matches(input, @"\b\w+\b"); return matches.Count; } /// <summary> /// Provides a default interpretation for the supplied <paramref name="metric"/>. /// </summary> private static void Interpret(NumericMetric metric) { if (metric.Value is null) { metric.Interpretation = new EvaluationMetricInterpretation( EvaluationRating.Unknown, failed: true, reason: "Failed to calculate word count for the response."); } else { if (metric.Value <= 100 && metric.Value > 5) metric.Interpretation = new EvaluationMetricInterpretation( EvaluationRating.Good, reason: "The response was between 6 and 100 words."); else metric.Interpretation = new EvaluationMetricInterpretation( EvaluationRating.Unacceptable, failed: true, reason: "The response was either too short or greater than 100 words."); } } public ValueTask<EvaluationResult> EvaluateAsync( IEnumerable<ChatMessage> messages, ChatResponse modelResponse, ChatConfiguration? chatConfiguration = null, IEnumerable<EvaluationContext>? additionalContext = null, CancellationToken cancellationToken = default) { // Count the number of words in the supplied <see cref="modelResponse"/>. int wordCount = CountWords(modelResponse.Text); string reason = $"This {WordCountMetricName} metric has a value of {wordCount} because " + $"the evaluated model response contained {wordCount} words."; // Create a <see cref="NumericMetric"/> with value set to the word count. // Include a reason that explains the score. var metric = new NumericMetric(WordCountMetricName, value: wordCount, reason); // Attach a default <see cref="EvaluationMetricInterpretation"/> for the metric. Interpret(metric); return new ValueTask<EvaluationResult>(new EvaluationResult(metric)); } },
WordCountEvaluatoryanıtta bulunan sözcük sayısını sayar. Bazı değerlendiricilerden farklı olarak yapay zekaya dayalı değildir.EvaluateAsyncyöntemi, sözcük sayısını içeren bir EvaluationResultNumericMetric değerini döndürür.yöntemi ayrıca
EvaluateAsyncölçüme varsayılan bir yorum ekler. Algılanan sözcük sayısı 6 ile 100 arasındaysa, varsayılan yorum ölçümü iyi (kabul edilebilir) olarak kabul eder. Aksi takdirde ölçüm başarısız olarak kabul edilir. Gerekirse, bu varsayılan yorum çağıran tarafından geçersiz kılınabilir.geri dön
MyTests.csiçinde, değerlendirmede kullanılacak değerlendiricileri toplamak için bir fonksiyon ekleyin.private static IEnumerable<IEvaluator> GetEvaluators() { IEvaluator relevanceEvaluator = new RelevanceEvaluator(); IEvaluator coherenceEvaluator = new CoherenceEvaluator(); IEvaluator wordCountEvaluator = new WordCountEvaluator(); return [relevanceEvaluator, coherenceEvaluator, wordCountEvaluator]; }Sistem istemi ChatMessageeklemek için bir yöntem ekleyin, sohbet seçeneklerini tanımlayın ve modelden belirli bir soruya yanıt isteyin.
private static async Task<(IList<ChatMessage> Messages, ChatResponse ModelResponse)> GetAstronomyConversationAsync( IChatClient chatClient, string astronomyQuestion) { const string SystemPrompt = """ You're an AI assistant that can answer questions related to astronomy. Keep your responses concise and under 100 words. Use the imperial measurement system for all measurements in your response. """; IList<ChatMessage> messages = [ new ChatMessage(ChatRole.System, SystemPrompt), new ChatMessage(ChatRole.User, astronomyQuestion) ]; var chatOptions = new ChatOptions { Temperature = 0.0f, ResponseFormat = ChatResponseFormat.Text }; ChatResponse response = await chatClient.GetResponseAsync(messages, chatOptions); return (messages, response); }Bu öğreticideki test, LLM'nin bir astronomi sorusuna verdiği yanıtı değerlendirir. ReportingConfiguration yanıt önbelleğe alma etkinleştirildiğinden ve sağlanan IChatClient her zaman bu raporlama yapılandırması kullanılarak oluşturulan ScenarioRun'dan getirildiğinden, test için LLM yanıtı önbelleğe alınır ve tekrar kullanılır. Karşılık gelen önbellek girdisinin süresi dolana kadar (varsayılan olarak 14 gün içinde) veya LLM uç noktası veya sorulan soru gibi herhangi bir istek parametresi değiştirilene kadar yanıt yeniden kullanılır.
Yanıtı doğrulamak için bir yöntem ekleyin.
/// <summary> /// Runs basic validation on the supplied <see cref="EvaluationResult"/>. /// </summary> private static void Validate(EvaluationResult result) { // Retrieve the score for relevance from the <see cref="EvaluationResult"/>. NumericMetric relevance = result.Get<NumericMetric>(RelevanceEvaluator.RelevanceMetricName); Assert.IsFalse(relevance.Interpretation!.Failed, relevance.Reason); Assert.IsTrue(relevance.Interpretation.Rating is EvaluationRating.Good or EvaluationRating.Exceptional); // Retrieve the score for coherence from the <see cref="EvaluationResult"/>. NumericMetric coherence = result.Get<NumericMetric>(CoherenceEvaluator.CoherenceMetricName); Assert.IsFalse(coherence.Interpretation!.Failed, coherence.Reason); Assert.IsTrue(coherence.Interpretation.Rating is EvaluationRating.Good or EvaluationRating.Exceptional); // Retrieve the word count from the <see cref="EvaluationResult"/>. NumericMetric wordCount = result.Get<NumericMetric>(WordCountEvaluator.WordCountMetricName); Assert.IsFalse(wordCount.Interpretation!.Failed, wordCount.Reason); Assert.IsTrue(wordCount.Interpretation.Rating is EvaluationRating.Good or EvaluationRating.Exceptional); Assert.IsFalse(wordCount.ContainsDiagnostics()); Assert.IsTrue(wordCount.Value > 5 && wordCount.Value <= 100); }Tip
Ölçümlerin her birinde puanın nedenini açıklayan bir
Reasonözellik bulunur. Bunun nedeni oluşturulan rapora dahil edilir ve ilgili ölçümün kartındaki bilgi simgesine tıklayarak görüntülenebilir.Son olarak test yönteminin kendisini ekleyin.
[TestMethod] public async Task SampleAndEvaluateResponse() { // Create a <see cref="ScenarioRun"/> with the scenario name // set to the fully qualified name of the current test method. await using ScenarioRun scenarioRun = await s_defaultReportingConfiguration.CreateScenarioRunAsync( ScenarioName, additionalTags: ["Moon"]); // Use the <see cref="IChatClient"/> that's included in the // <see cref="ScenarioRun.ChatConfiguration"/> to get the LLM response. (IList<ChatMessage> messages, ChatResponse modelResponse) = await GetAstronomyConversationAsync( chatClient: scenarioRun.ChatConfiguration!.ChatClient, astronomyQuestion: "How far is the Moon from the Earth at its closest and furthest points?"); // Run the evaluators configured in <see cref="s_defaultReportingConfiguration"/> against the response. EvaluationResult result = await scenarioRun.EvaluateAsync(messages, modelResponse); // Run some basic validation on the evaluation result. Validate(result); }Bu test yöntemi:
Oluşturur ScenarioRun.
await usingunsuru,ScenarioRunöğesinin doğru bir şekilde atılmasını ve bu değerlendirme sonuçlarının sonuç deposunda doğru bir şekilde kalıcı hale gelmesini sağlar.LLM'nin belirli bir astronomi sorusuna verdiği yanıtı alır. Değerlendirme için kullanılacak olanın aynısıIChatClient, değerlendirilmekte olan birincil LLM
GetAstronomyConversationAsyncsağlamak için yöntemine geçirilir. (Buna ek olarak, bu, değerlendirmecilerin değerlendirmelerini dahili olarak gerçekleştirmek için kullandığı LLM işlemlerinde yanıt önbelleğe almayı etkinleştirir.) Yanıt önbelleğe alma ile LLM yanıtı aşağıdaki şekillerde elde edilir:- Geçerli testin ilk çalıştırmasında doğrudan LLM uç noktasından veya önbelleğe alınan girişin süresi dolduysa sonraki çalıştırmalarda (varsayılan olarak 14 gün).
- Testin sonraki çalıştırmalarında
s_defaultReportingConfigurationyapılandırılan (disk tabanlı) yanıt önbelleğinden.
Değerlendiricileri yanıt üzerinde çalıştırır. LLM yanıtı gibi sonraki çalıştırmalarda da değerlendirme, içinde
s_defaultReportingConfigurationyapılandırılan (disk tabanlı) yanıt önbelleğinden getirilir.Değerlendirme sonucu üzerinde bazı temel doğrulamalar çalıştırır.
Bu adım isteğe bağlıdır ve çoğunlukla tanıtım amaçlıdır. Gerçek dünyadaki değerlendirmelerde, ÜRÜNÜNÜz (ve kullanılan modeller) geliştikçe LLM yanıtları ve değerlendirme puanları zaman içinde değişebileceğinden tek tek sonuçları doğrulamak istemeyebilirsiniz. Bu durumda tek tek değerlendirme testlerinin "başarısız olmasını" ve CI/CD işlem hatlarınızda derlemeleri engellemesini istemeyebilirsiniz. Bunun yerine, oluşturulan rapora güvenmek ve zaman içinde farklı senaryolarda değerlendirme puanlarının genel eğilimlerini izlemek daha iyi olabilir (ve yalnızca birden çok farklı testte değerlendirme puanlarında önemli bir düşüş olduğunda tek tek derlemelerde başarısız olabilir). Burada bazı nüanslar bulunmaktadır ve bireysel sonuçların doğrulanıp doğrulanmaması kararı, belirli kullanım senaryosuna bağlı olarak değişebilir.
Yöntem döndüğünde
scenarioRunnesnesi yok edilir ve değerlendirme sonucu,s_defaultReportingConfiguration'de yapılandırılan (disk tabanlı) sonuç deposunda saklanır.
Testi/değerlendirmeyi çalıştırma
Örneğin CLI komutunu dotnet test kullanarak veya Test Gezgini aracılığıyla tercih ettiğiniz test iş akışını kullanarak testi çalıştırın.
Rapor oluşturma
Terminal penceresinden aşağıdaki komutu çalıştırarak Microsoft.Extensions.AI.Evaluation.Console .NET aracını yükleyin:
dotnet tool install --local Microsoft.Extensions.AI.Evaluation.ConsoleTip
Önce bir bildirim dosyası oluşturmanız gerekebilir. Bu ve yerel araçları yükleme hakkında daha fazla bilgi için bkz. Yerel araçlar.
Aşağıdaki komutu çalıştırarak bir rapor oluşturun:
dotnet tool run aieval report --path <path\to\your\cache\storage> --output report.htmlreport.htmldosyasını açın. Şuna benzer bir şey olmalı.
Sonraki Adımlar
- Test sonuçlarının depolandığı dizine gidin (varsayılan konum
C:\TestReports, ancak ReportingConfiguration öğesini oluşturduğunuzda konumu değiştirmediyseniz). Alt dizinresultsiçerisinde, her test çalıştırması için zaman damgasıExecutionNameile adlandırılmış bir klasör olduğuna dikkat edin. Bu klasörlerin her birinin içinde her senaryo adı için bir klasör bulunur; bu örnekte projedeki tek bir test yöntemidir. Bu klasör iletiler, yanıt ve değerlendirme sonucu dahil olmak üzere tüm verileri içeren bir JSON dosyası içerir. - Değerlendirmeyi genişletin. İşte birkaç fikir:
- Yanıtta kullanılan ölçüm sistemini belirlemek için yapay zeka kullanan bir değerlendirici gibi ek bir özel değerlendirici ekleyin.
- LlM'den birden çok yanıtı değerlendiren bir yöntem gibi başka bir test yöntemi ekleyin. Her yanıt farklı olabileceğinden, bir soruya en az birkaç yanıt örneklemek ve değerlendirmek iyidir. Bu durumda, her çağrı yaptığınızda CreateScenarioRunAsync(String, String, IEnumerable<String>, IEnumerable<String>, CancellationToken) bir yineleme adı belirtirsiniz.