diff --git a/dotnet/agent-framework-dotnet.slnx b/dotnet/agent-framework-dotnet.slnx index 920da0589e..04eb1f54b9 100644 --- a/dotnet/agent-framework-dotnet.slnx +++ b/dotnet/agent-framework-dotnet.slnx @@ -52,6 +52,7 @@ + diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step16_ChatReduction/Agent_Step16_ChatReduction.csproj b/dotnet/samples/GettingStarted/Agents/Agent_Step16_ChatReduction/Agent_Step16_ChatReduction.csproj new file mode 100644 index 0000000000..8298cfe6e8 --- /dev/null +++ b/dotnet/samples/GettingStarted/Agents/Agent_Step16_ChatReduction/Agent_Step16_ChatReduction.csproj @@ -0,0 +1,21 @@ + + + + Exe + net9.0 + + enable + enable + + + + + + + + + + + + + diff --git a/dotnet/samples/GettingStarted/Agents/Agent_Step16_ChatReduction/Program.cs b/dotnet/samples/GettingStarted/Agents/Agent_Step16_ChatReduction/Program.cs new file mode 100644 index 0000000000..365bdca371 --- /dev/null +++ b/dotnet/samples/GettingStarted/Agents/Agent_Step16_ChatReduction/Program.cs @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft. All rights reserved. + +// This sample shows how to use a chat history reducer to keep the context within model size limits. +// Any implementation of Microsoft.Extensions.AI.IChatReducer can be used to customize how the chat history is reduced. +// NOTE: this feature is only supported where the chat history is stored locally, such as with OpenAI Chat Completion. +// Where the chat history is stored server side, such as with Azure Foundry Agents, the service must manage the chat history size. + +using Azure.AI.OpenAI; +using Azure.Identity; +using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; +using OpenAI; + +var endpoint = Environment.GetEnvironmentVariable("AZURE_OPENAI_ENDPOINT") ?? throw new InvalidOperationException("AZURE_OPENAI_ENDPOINT is not set."); +var deploymentName = Environment.GetEnvironmentVariable("AZURE_OPENAI_DEPLOYMENT_NAME") ?? "gpt-4o-mini"; + +const string JokerName = "Joker"; +const string JokerInstructions = "You are good at telling jokes."; + +// Construct the agent, and provide a factory to create an in-memory chat message store with a reducer that keeps only the last 2 non-system messages. +AIAgent agent = new AzureOpenAIClient( + new Uri(endpoint), + new AzureCliCredential()) + .GetChatClient(deploymentName) + .CreateAIAgent(new ChatClientAgentOptions + { + Name = JokerName, + Instructions = JokerInstructions, + ChatMessageStoreFactory = ctx => new InMemoryChatMessageStore(new MessageCountingChatReducer(2), ctx.SerializedState, ctx.JsonSerializerOptions) + }); + +AgentThread thread = agent.GetNewThread(); + +// Invoke the agent and output the text result. +Console.WriteLine(await agent.RunAsync("Tell me a joke about a pirate.", thread)); + +// Get the chat history to see how many messages are stored. +IList? chatHistory = thread.GetService>(); +Console.WriteLine($"\nChat history has {chatHistory?.Count} messages.\n"); + +// Invoke the agent a few more times. +Console.WriteLine(await agent.RunAsync("Tell me a joke about a robot.", thread)); +Console.WriteLine($"\nChat history has {chatHistory?.Count} messages.\n"); +Console.WriteLine(await agent.RunAsync("Tell me a joke about a lemur.", thread)); +Console.WriteLine($"\nChat history has {chatHistory?.Count} messages.\n"); + +// At this point, the chat history has exceeded the limit and the original message will not exist anymore, +// so asking a follow up question about it will not work as expected. +Console.WriteLine(await agent.RunAsync("Tell me the joke about the pirate again, but add emojis and use the voice of a parrot.", thread)); + +Console.WriteLine($"\nChat history has {chatHistory?.Count} messages.\n"); diff --git a/dotnet/samples/GettingStarted/Agents/README.md b/dotnet/samples/GettingStarted/Agents/README.md index 1078dafbfd..31290f9637 100644 --- a/dotnet/samples/GettingStarted/Agents/README.md +++ b/dotnet/samples/GettingStarted/Agents/README.md @@ -41,6 +41,7 @@ Before you begin, ensure you have the following prerequisites: |[Using memory with an agent](./Agent_Step13_Memory/)|This sample demonstrates how to create a simple memory component and use it with an agent| |[Using middleware with an agent](./Agent_Step14_Middleware/)|This sample demonstrates how to use middleware with an agent| |[Using plugins with an agent](./Agent_Step15_Plugins/)|This sample demonstrates how to use plugins with an agent| +|[Reducing chat history size](./Agent_Step16_ChatReduction/)|This sample demonstrates how to reduce the chat history to constrain its size, where chat history is maintained locally| ## Running the samples from the console