diff --git a/tests/dotnet/Core.Examples/Catalogs/AgentCatalog.cs b/tests/dotnet/Core.Examples/Catalogs/AgentCatalog.cs index 992fb0c64d..d92fa7f292 100644 --- a/tests/dotnet/Core.Examples/Catalogs/AgentCatalog.cs +++ b/tests/dotnet/Core.Examples/Catalogs/AgentCatalog.cs @@ -176,6 +176,84 @@ public static class AgentCatalog } }, new KnowledgeManagementAgent + { + Name = TestAgentNames.SemanticKernelSDZWA, + Description = "Knowledge Management Agent that queries the San Diego Zoo Wildlife Alliance journals using SemanticKernel.", + InlineContext = false, + SessionsEnabled = true, + Vectorization = new AgentVectorizationSettings + { + DedicatedPipeline = false, + IndexingProfileObjectId = null, + TextEmbeddingProfileObjectId = null + }, + ConversationHistory = new ConversationHistory + { + Enabled = true, + MaxHistory = 10 + }, + Gatekeeper = new Gatekeeper + { + UseSystemSetting = false + }, + OrchestrationSettings = new OrchestrationSettings + { + Orchestrator = LLMOrchestrationServiceNames.SemanticKernel, + EndpointConfiguration = new Dictionary + { + { "auth_type", "key" }, + { "provider", "microsoft" }, + { "endpoint", "FoundationaLLM:AzureOpenAI:API:Endpoint" }, + { "api_key", "FoundationaLLM:AzureOpenAI:API:Key" }, + { "api_version", "FoundationaLLM:AzureOpenAI:API:Version" } + }, + ModelParameters = new Dictionary + { + { "temperature", 0 }, + { "deployment_name", "completions" } + } + } + }, + new KnowledgeManagementAgent + { + Name = TestAgentNames.LangChainSDZWA, + Description = "Knowledge Management Agent that queries the San Diego Zoo Wildlife Alliance journals using LangChain.", + InlineContext = false, + SessionsEnabled = true, + Vectorization = new AgentVectorizationSettings + { + DedicatedPipeline = false, + IndexingProfileObjectId = null, + TextEmbeddingProfileObjectId = null + }, + ConversationHistory = new ConversationHistory + { + Enabled = true, + MaxHistory = 10 + }, + Gatekeeper = new Gatekeeper + { + UseSystemSetting = false + }, + OrchestrationSettings = new OrchestrationSettings + { + Orchestrator = LLMOrchestrationServiceNames.LangChain, + EndpointConfiguration = new Dictionary + { + { "auth_type", "key" }, + { "provider", "microsoft" }, + { "endpoint", "FoundationaLLM:AzureOpenAI:API:Endpoint" }, + { "api_key", "FoundationaLLM:AzureOpenAI:API:Key" }, + { "api_version", "FoundationaLLM:AzureOpenAI:API:Version" } + }, + ModelParameters = new Dictionary + { + { "temperature", 0 }, + { "deployment_name", "completions" } + } + } + }, + new KnowledgeManagementAgent { Name = TestAgentNames.ConversationGeneratorAgent, Description = "An agent that creates conversations based on product descriptions.", diff --git a/tests/dotnet/Core.Examples/Catalogs/IndexingProfilesCatalog.cs b/tests/dotnet/Core.Examples/Catalogs/IndexingProfilesCatalog.cs index 991bc4a2b6..03f7794dec 100644 --- a/tests/dotnet/Core.Examples/Catalogs/IndexingProfilesCatalog.cs +++ b/tests/dotnet/Core.Examples/Catalogs/IndexingProfilesCatalog.cs @@ -7,7 +7,8 @@ public static class IndexingProfilesCatalog public static readonly List Items = [ new IndexingProfile { Name = "indexing_profile_really_big", Indexer = IndexerType.AzureAISearchIndexer, Settings = new Dictionary{ { "IndexName", "reallybig" }, { "TopN", "3" }, { "Filters", "" }, { "EmbeddingFieldName", "Embedding" }, { "TextFieldName", "Text" } }, ConfigurationReferences = new Dictionary{ { "AuthenticationType", "FoundationaLLM:Vectorization:AzureAISearchIndexingService:AuthenticationType" }, { "Endpoint", "FoundationaLLM:Vectorization:AzureAISearchIndexingService:Endpoint" } } }, - new IndexingProfile { Name = "indexing_profile_pdf", Indexer = IndexerType.AzureAISearchIndexer, Settings = new Dictionary{ { "IndexName", "pdf" }, { "TopN", "3" }, { "Filters", "" }, { "EmbeddingFieldName", "Embedding" }, { "TextFieldName", "Text" } }, ConfigurationReferences = new Dictionary{ { "AuthenticationType", "FoundationaLLM:Vectorization:AzureAISearchIndexingService:AuthenticationType" }, { "Endpoint", "FoundationaLLM:Vectorization:AzureAISearchIndexingService:Endpoint" } } } + new IndexingProfile { Name = "indexing_profile_pdf", Indexer = IndexerType.AzureAISearchIndexer, Settings = new Dictionary{ { "IndexName", "pdf" }, { "TopN", "3" }, { "Filters", "" }, { "EmbeddingFieldName", "Embedding" }, { "TextFieldName", "Text" } }, ConfigurationReferences = new Dictionary{ { "AuthenticationType", "FoundationaLLM:Vectorization:AzureAISearchIndexingService:AuthenticationType" }, { "Endpoint", "FoundationaLLM:Vectorization:AzureAISearchIndexingService:Endpoint" } } }, + new IndexingProfile { Name = "indexing_profile_sdzwa", Indexer = IndexerType.AzureAISearchIndexer, Settings = new Dictionary{ { "IndexName", "fllm-pdf" }, { "TopN", "3" }, { "Filters", "" }, { "EmbeddingFieldName", "Embedding" }, { "TextFieldName", "Text" } }, ConfigurationReferences = new Dictionary{ { "AuthenticationType", "FoundationaLLM:Vectorization:AzureAISearchIndexingService:AuthenticationType" }, { "Endpoint", "FoundationaLLM:Vectorization:AzureAISearchIndexingService:Endpoint" } } } ]; public static List GetIndexingProfiles() diff --git a/tests/dotnet/Core.Examples/Catalogs/PromptCatalog.cs b/tests/dotnet/Core.Examples/Catalogs/PromptCatalog.cs index 16b8f65391..f07591a37e 100644 --- a/tests/dotnet/Core.Examples/Catalogs/PromptCatalog.cs +++ b/tests/dotnet/Core.Examples/Catalogs/PromptCatalog.cs @@ -10,6 +10,7 @@ namespace FoundationaLLM.Core.Examples.Catalogs public static class PromptCatalog { #region multipart prompts + /// /// Catalog of multipart prompts. /// @@ -25,8 +26,7 @@ Provide concise answers that are polite and professional. Context: The Rosetta Stone, discovered in 1799 by French soldiers in Egypt, is an ancient stele inscribed with the same text in three scripts: Egyptian hieroglyphs, Demotic script, and Ancient Greek. The stone was found in a small village in the Delta called Rosetta (Rashid). It dates back to 196 BC, during the reign of Pharaoh Ptolemy V. The Rosetta Stone proved crucial in deciphering Egyptian hieroglyphs, primarily through the efforts of the French scholar Jean-François Champollion in 1822. This breakthrough provided the key to understanding much about ancient Egyptian history and culture that had been lost for centuries. The Rosetta Stone is a fragment of a larger stele that originally had no decorative elements but featured a decree affirming the royal cult of the 13-year-old Ptolemy V. The text of the decree was composed by a council of priests to honor the pharaoh. The reasons for the decree and its broader implications on Egyptian society during Ptolemy V’s reign are areas of ongoing research and debate. - Today, the Rosetta Stone is housed in the British Museum in London, where it remains one of the most visited and studied artifacts in their collection. Its historical and linguistic significance continues to make it a subject of scholarly and public fascination. - " + Today, the Rosetta Stone is housed in the British Museum in London, where it remains one of the most visited and studied artifacts in their collection. Its historical and linguistic significance continues to make it a subject of scholarly and public fascination." }, new MultipartPrompt { @@ -37,8 +37,7 @@ Provide concise answers that are polite and professional. Context: The Rosetta Stone, discovered in 1799 by French soldiers in Egypt, is an ancient stele inscribed with the same text in three scripts: Egyptian hieroglyphs, Demotic script, and Ancient Greek. The stone was found in a small village in the Delta called Rosetta (Rashid). It dates back to 196 BC, during the reign of Pharaoh Ptolemy V. The Rosetta Stone proved crucial in deciphering Egyptian hieroglyphs, primarily through the efforts of the French scholar Jean-François Champollion in 1822. This breakthrough provided the key to understanding much about ancient Egyptian history and culture that had been lost for centuries. The Rosetta Stone is a fragment of a larger stele that originally had no decorative elements but featured a decree affirming the royal cult of the 13-year-old Ptolemy V. The text of the decree was composed by a council of priests to honor the pharaoh. The reasons for the decree and its broader implications on Egyptian society during Ptolemy V’s reign are areas of ongoing research and debate. - Today, the Rosetta Stone is housed in the British Museum in London, where it remains one of the most visited and studied artifacts in their collection. Its historical and linguistic significance continues to make it a subject of scholarly and public fascination. - " + Today, the Rosetta Stone is housed in the British Museum in London, where it remains one of the most visited and studied artifacts in their collection. Its historical and linguistic significance continues to make it a subject of scholarly and public fascination." }, new MultipartPrompt { @@ -55,6 +54,24 @@ Provide concise answers that are polite and professional." Provide concise answers that are polite and professional." }, new MultipartPrompt + { + Name = TestAgentNames.SemanticKernelSDZWA, + Description = $"Prompt template for the {TestAgentNames.SemanticKernelSDZWA} agent.", + Prefix = @"You are the San Diego Zoo assistant named Sandy. + You are responsible for answering questions related to the San Diego Zoo that is contained in the journal publications. + Only answer questions that relate to the Zoo and journal content. + Do not make anything up. Use only the data provided." + }, + new MultipartPrompt + { + Name = TestAgentNames.LangChainSDZWA, + Description = $"Prompt template for the {TestAgentNames.LangChainSDZWA} agent.", + Prefix = @"You are the San Diego Zoo assistant named Sandy. + You are responsible for answering questions related to the San Diego Zoo that is contained in the journal publications. + Only answer questions that relate to the Zoo and journal content. + Do not make anything up. Use only the data provided." + }, + new MultipartPrompt { Name = TestAgentNames.ConversationGeneratorAgent, Description = $"Prompt template for the {TestAgentNames.ConversationGeneratorAgent} agent.", @@ -82,6 +99,7 @@ Do you have any adventure watches? " } ]; + #endregion /// diff --git a/tests/dotnet/Core.Examples/Constants/TestAgentNames.cs b/tests/dotnet/Core.Examples/Constants/TestAgentNames.cs index 04cb7b7683..9771968dc4 100644 --- a/tests/dotnet/Core.Examples/Constants/TestAgentNames.cs +++ b/tests/dotnet/Core.Examples/Constants/TestAgentNames.cs @@ -30,6 +30,14 @@ public static class TestAgentNames /// public const string LangChainAgentName = "KMAgentWithLangChain"; /// + /// The name of the SDZWA semantic kernel agent. + /// + public const string SemanticKernelSDZWA = "KMAgentWithSemanticKernelSDZWA"; + /// + /// The name of the SDZWA lang chain agent. + /// + public const string LangChainSDZWA = "KMAgentWithLangChainSDZWA"; + /// /// The name of the agent that is used to generate conversations about products. /// public const string ConversationGeneratorAgent = "ConversationGeneratorAgent"; diff --git a/tests/dotnet/Core.Examples/Example0011_KnowledgeManagementAgentWithSemanticKernel.cs b/tests/dotnet/Core.Examples/Example0011_KnowledgeManagementAgentWithSemanticKernel.cs new file mode 100644 index 0000000000..80c446b5b5 --- /dev/null +++ b/tests/dotnet/Core.Examples/Example0011_KnowledgeManagementAgentWithSemanticKernel.cs @@ -0,0 +1,64 @@ +using FoundationaLLM.Core.Examples.Constants; +using FoundationaLLM.Core.Examples.Interfaces; +using FoundationaLLM.Core.Examples.Setup; +using Xunit.Abstractions; + +namespace FoundationaLLM.Core.Examples +{ + /// + /// Example class for the Knowledge Management agent with LangChain. + /// + public class Example0011_KnowledgeManagementAgentWithSemanticKernel : BaseTest, IClassFixture + { + private readonly IAgentConversationTestService _agentConversationTestService; + + private string textEmbeddingProfileName = "text_embedding_profile_generic"; + private string indexingProfileName = "indexing_profile_sdzwa"; + + public Example0011_KnowledgeManagementAgentWithSemanticKernel(ITestOutputHelper output, TestFixture fixture) + : base(output, fixture.ServiceProvider) + { + _agentConversationTestService = GetService(); + } + + [Fact] + public async Task RunAsync() + { + WriteLine("============ Knowledge Management agent with Semantic Kernel on SDZWA ============"); + await RunExampleAsync(); + } + + private async Task RunExampleAsync() + { + var agentName = TestAgentNames.SemanticKernelSDZWA; + var userPrompts = new List + { + "Who are you?", + "Tell me one interesting facts about the San Diego Zoo?", + "How many animals does the San Diego Zoo host?", + "What does the San Diego Zoo do to treat illness among it's inhabitants?" + }; + + WriteLine($"Send questions to the {agentName} agent."); + + var response = await _agentConversationTestService.RunAgentConversationWithSession( + agentName, userPrompts, null, true, indexingProfileName, textEmbeddingProfileName); + + WriteLine($"Agent conversation history:"); + + var invalidAgentResponsesFound = 0; + foreach (var message in response) + { + WriteLine($"- {message.Sender}: {message.Text}"); + + if (string.Equals(message.Sender, Common.Constants.Agents.InputMessageRoles.Assistant, StringComparison.CurrentCultureIgnoreCase) && + message.Text == TestResponseMessages.FailedCompletionResponse) + { + invalidAgentResponsesFound++; + } + } + + Assert.True(invalidAgentResponsesFound == 0, $"{invalidAgentResponsesFound} invalid agent responses found."); + } + } +} diff --git a/tests/dotnet/Core.Examples/Example0012_KnowledgeManagementAgentWithLangChain.cs b/tests/dotnet/Core.Examples/Example0012_KnowledgeManagementAgentWithLangChain.cs new file mode 100644 index 0000000000..f33e216ac4 --- /dev/null +++ b/tests/dotnet/Core.Examples/Example0012_KnowledgeManagementAgentWithLangChain.cs @@ -0,0 +1,64 @@ +using FoundationaLLM.Core.Examples.Constants; +using FoundationaLLM.Core.Examples.Interfaces; +using FoundationaLLM.Core.Examples.Setup; +using Xunit.Abstractions; + +namespace FoundationaLLM.Core.Examples +{ + /// + /// Example class for the Knowledge Management agent with SemanticKernel. + /// + public class Example0012_KnowledgeManagementAgentWithLangChain : BaseTest, IClassFixture + { + private readonly IAgentConversationTestService _agentConversationTestService; + + private string textEmbeddingProfileName = "text_embedding_profile_generic"; + private string indexingProfileName = "indexing_profile_sdzwa"; + + public Example0012_KnowledgeManagementAgentWithLangChain(ITestOutputHelper output, TestFixture fixture) + : base(output, fixture.ServiceProvider) + { + _agentConversationTestService = GetService(); + } + + [Fact] + public async Task RunAsync() + { + WriteLine("============ Knowledge Management agent with Lang Chain on SDZWA ============"); + await RunExampleAsync(); + } + + private async Task RunExampleAsync() + { + var agentName = TestAgentNames.LangChainSDZWA; + var userPrompts = new List + { + "Who are you?", + "Tell me one interesting facts about the San Diego Zoo?", + "How many animals does the San Diego Zoo host?", + "What does the San Diego Zoo do to treat illness among it's inhabitants?" + }; + + WriteLine($"Send questions to the {agentName} agent."); + + var response = await _agentConversationTestService.RunAgentConversationWithSession( + agentName, userPrompts, null, true, indexingProfileName, textEmbeddingProfileName); + + WriteLine($"Agent conversation history:"); + + var invalidAgentResponsesFound = 0; + foreach (var message in response) + { + WriteLine($"- {message.Sender}: {message.Text}"); + + if (string.Equals(message.Sender, Common.Constants.Agents.InputMessageRoles.Assistant, StringComparison.CurrentCultureIgnoreCase) && + message.Text == TestResponseMessages.FailedCompletionResponse) + { + invalidAgentResponsesFound++; + } + } + + Assert.True(invalidAgentResponsesFound == 0, $"{invalidAgentResponsesFound} invalid agent responses found."); + } + } +} diff --git a/tests/dotnet/Core.Examples/Interfaces/IAgentConversationTestService.cs b/tests/dotnet/Core.Examples/Interfaces/IAgentConversationTestService.cs index 2a4e64db44..78cc27d693 100644 --- a/tests/dotnet/Core.Examples/Interfaces/IAgentConversationTestService.cs +++ b/tests/dotnet/Core.Examples/Interfaces/IAgentConversationTestService.cs @@ -21,7 +21,8 @@ public interface IAgentConversationTestService /// not enable this option if you wish to use pre-existing resources, such as the default FoundationaLLM agent. /// Task> RunAgentConversationWithSession(string agentName, - List userPrompts, string? sessionId = null, bool createAgent = false); + List userPrompts, string? sessionId = null, bool createAgent = false, string? indexingProfileName = null, + string? textEmbeddingProfileName = null, string? textPartitioningProfileName = null); /// /// Runs a single completion with an agent using the Core API and a chat session. diff --git a/tests/dotnet/Core.Examples/README.md b/tests/dotnet/Core.Examples/README.md index cb201cc18c..9fa229adf2 100644 --- a/tests/dotnet/Core.Examples/README.md +++ b/tests/dotnet/Core.Examples/README.md @@ -383,6 +383,61 @@ Delete the vectorization text embedding profile: text_embedding_profile_generic Delete the vectorization indexing profile: indexing_profile_pdf via the Management API and delete the created index ``` +### Example 11: Knowledge Management agent with Semantic Kernel on the SDZWA journal + +**Purpose**: Verify that the Knowledge Management agent with Semantic Kernel can respond to user queries using the SDZWA journals. + +**File**: [Example0011_KnowledgeManagementAgentWithSemanticKernel.cs](Example0011_KnowledgeManagementAgentWithSemanticKernel.cs) + +This example demonstrates how to use the Management API to create an the agent and how to use the Core API to send user prompts to the agent and receive completions. + +#### Running the example + +Run the example by running a test on the `Example0011_KnowledgeManagementAgentWithSemanticKernel.cs` file. You can run the test using the Visual Studio Test Explorer, the command line, or by simply right-clicking anywhere on the `Example0011_KnowledgeManagementAgentWithSemanticKernel.cs` file and selecting **Run Tests**. + +You will see an output similar to the following after the test is completed: + +```text +============ Knowledge Management agent with Lang Chain on SDZWA ============ +Send questions to the KMAgentWithLangChainSDZWA agent. +Agent conversation history: +- User: Who are you? +- Assistant: I am Sandy, the San Diego Zoo assistant. +- User: Tell me one interesting facts about the San Diego Zoo? +- Assistant: One interesting fact about the San Diego Zoo is that between the botanical gardens at the San Diego Zoo and the Safari Park, they care for 2 million plants. +- User: How many animals does the San Diego Zoo host? +- Assistant: The journal does not provide information about the number of animals hosted by the San Diego Zoo. +- User: What does the San Diego Zoo do to treat illness among it's inhabitants? +- Assistant: The journal mentions that the San Diego Zoo provides efficient and effective health care for its animals. The care and health decisions are based on the best available scientific data. +``` + +### Example 12: Knowledge Management agent with Lang Chain on the SDZWA journal + +**Purpose**: Verify that the Knowledge Management agent with Lang Chain can respond to user queries using the SDZWA journals. + +**File**: [Example0012_KnowledgeManagementAgentWithLangChain.cs](Example0012_KnowledgeManagementAgentWithLangChain.cs) + +This example demonstrates how to use the Management API to create an the agent and how to use the Core API to send user prompts to the agent and receive completions. + +#### Running the example + +Run the example by running a test on the `Example0012_KnowledgeManagementAgentWithLangChain.cs` file. You can run the test using the Visual Studio Test Explorer, the command line, or by simply right-clicking anywhere on the `Example0011_KnowledgeManagementAgentWithSemanticKernel.cs` file and selecting **Run Tests**. + +You will see an output similar to the following after the test is completed: + +```text +============ Knowledge Management agent with Lang Chain on SDZWA ============ +Send questions to the KMAgentWithLangChainSDZWA agent. +Agent conversation history: +- User: Who are you? +- Assistant: I am Sandy, the San Diego Zoo assistant. +- User: Tell me one interesting facts about the San Diego Zoo? +- Assistant: One interesting fact about the San Diego Zoo is that between the botanical gardens at the San Diego Zoo and the Safari Park, they care for 2 million plants. +- User: How many animals does the San Diego Zoo host? +- Assistant: The journal does not provide information about the number of animals hosted by the San Diego Zoo. +- User: What does the San Diego Zoo do to treat illness among it's inhabitants? +- Assistant: The journal mentions that the San Diego Zoo provides efficient and effective health care for its animals. The care and health decisions are based on the best available scientific data. +``` ### Example 16: Completion quality measurements with Azure AI Studio diff --git a/tests/dotnet/Core.Examples/Services/AgentConversationTestService.cs b/tests/dotnet/Core.Examples/Services/AgentConversationTestService.cs index c3dc682f5c..21fd196650 100644 --- a/tests/dotnet/Core.Examples/Services/AgentConversationTestService.cs +++ b/tests/dotnet/Core.Examples/Services/AgentConversationTestService.cs @@ -19,8 +19,14 @@ public class AgentConversationTestService( IAzureAIService azureAIService = null) : IAgentConversationTestService { /// - public async Task> RunAgentConversationWithSession(string agentName, - List userPrompts, string? sessionId = null, bool createAgent = false) + public async Task> RunAgentConversationWithSession( + string agentName, + List userPrompts, + string? sessionId = null, + bool createAgent = false, + string? indexingProfileName = null, + string? textEmbeddingProfileName = null, + string? textPartitioningProfileName = null) { var sessionCreated = false; if (string.IsNullOrWhiteSpace(sessionId)) @@ -33,7 +39,7 @@ public async Task> RunAgentConversationWithSession(string a if (createAgent) { // Create a new agent and its dependencies for the test. - await managementAPITestManager.CreateAgent(agentName); + await managementAPITestManager.CreateAgent(agentName, indexingProfileName, textEmbeddingProfileName, textPartitioningProfileName); } // Send user prompts and agent responses. diff --git a/tests/dotnet/Core.Examples/Services/ManagementAPITestManager.cs b/tests/dotnet/Core.Examples/Services/ManagementAPITestManager.cs index 59d67c591e..373e67bd95 100644 --- a/tests/dotnet/Core.Examples/Services/ManagementAPITestManager.cs +++ b/tests/dotnet/Core.Examples/Services/ManagementAPITestManager.cs @@ -27,10 +27,10 @@ public class ManagementAPITestManager( public async Task CreateAppConfiguration(AppConfigurationKeyValue appConfigurationKeyValue) { - var coreClient = await httpClientManager.GetHttpClientAsync(HttpClients.ManagementAPI); + var managementClient = await httpClientManager.GetHttpClientAsync(HttpClients.ManagementAPI); var serializedRequest = JsonSerializer.Serialize(appConfigurationKeyValue, _jsonSerializerOptions); - var response = await coreClient.PostAsync($"instances/{instanceSettings.Value.Id}/providers/{ResourceProviderNames.FoundationaLLM_Configuration}/appConfigurations", + var response = await managementClient.PostAsync($"instances/{instanceSettings.Value.Id}/providers/{ResourceProviderNames.FoundationaLLM_Configuration}/appConfigurations", new StringContent(serializedRequest, Encoding.UTF8, "application/json")); if (response.IsSuccessStatusCode)