db620d33df
CodeQL / Analyze (csharp) (push) Waiting to run
CodeQL / Analyze (python) (push) Waiting to run
dotnet-build-and-test / dotnet-test-functions (push) Has been cancelled
dotnet-build-and-test / paths-filter (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Debug, windows-latest, net9.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, ubuntu-latest, net10.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, ubuntu-latest, net8.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-build (Release, windows-latest, net472) (push) Has been cancelled
dotnet-build-and-test / dotnet-test (Release, integration, true, ubuntu-latest, net10.0) (push) Has been cancelled
dotnet-build-and-test / dotnet-test (Release, integration, true, windows-latest, net472) (push) Has been cancelled
dotnet-build-and-test / dotnet-foundry-hosted-it (push) Has been cancelled
dotnet-build-and-test / dotnet-build-and-test-check (push) Has been cancelled
dotnet-build-and-test / Integration Test Report (push) Has been cancelled
124 lines
5.8 KiB
C#
124 lines
5.8 KiB
C#
// Copyright (c) Microsoft. All rights reserved.
|
|
|
|
// Compaction Pipeline — Progressive context management strategies
|
|
//
|
|
// This sample demonstrates how to use a CompactionProvider with a compaction
|
|
// pipeline as an AIContextProvider for in-run context management. The pipeline
|
|
// chains multiple compaction strategies from gentle to aggressive:
|
|
// 1. ToolResultCompactionStrategy — Collapses old tool-call groups into summaries
|
|
// 2. SummarizationCompactionStrategy — LLM-compresses older conversation spans
|
|
// 3. SlidingWindowCompactionStrategy — Keeps only the most recent N user turns
|
|
// 4. TruncationCompactionStrategy — Emergency token-budget backstop
|
|
|
|
using System.ComponentModel;
|
|
using Azure.AI.Projects;
|
|
using Azure.Identity;
|
|
using Microsoft.Agents.AI;
|
|
using Microsoft.Agents.AI.Compaction;
|
|
using Microsoft.Extensions.AI;
|
|
|
|
var endpoint = Environment.GetEnvironmentVariable("FOUNDRY_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("FOUNDRY_PROJECT_ENDPOINT is not set.");
|
|
var deploymentName = Environment.GetEnvironmentVariable("FOUNDRY_MODEL") ?? "gpt-5.4-mini";
|
|
|
|
// WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production.
|
|
// In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid
|
|
// latency issues, unintended credential probing, and potential security risks from fallback mechanisms.
|
|
AIProjectClient aiProjectClient = new(new Uri(endpoint), new DefaultAzureCredential());
|
|
|
|
// Create a chat client for the agent and a separate one for the summarization strategy.
|
|
// Using the same model for simplicity; in production, use a smaller/cheaper model for summarization.
|
|
IChatClient agentChatClient = aiProjectClient.GetProjectOpenAIClient().GetResponsesClient().AsIChatClient(deploymentName);
|
|
IChatClient summarizerChatClient = aiProjectClient.GetProjectOpenAIClient().GetResponsesClient().AsIChatClient(deploymentName);
|
|
|
|
// Define a tool the agent can use, so we can see tool-result compaction in action.
|
|
[Description("Look up the current price of a product by name.")]
|
|
static string LookupPrice([Description("The product name to look up.")] string productName) =>
|
|
productName.ToUpperInvariant() switch
|
|
{
|
|
"LAPTOP" => "The laptop costs $999.99.",
|
|
"KEYBOARD" => "The keyboard costs $79.99.",
|
|
"MOUSE" => "The mouse costs $29.99.",
|
|
_ => $"Sorry, I don't have pricing for '{productName}'."
|
|
};
|
|
|
|
// Configure the compaction pipeline with one of each strategy, ordered least to most aggressive.
|
|
PipelineCompactionStrategy compactionPipeline =
|
|
new(// 1. Gentle: collapse old tool-call groups into short summaries
|
|
new ToolResultCompactionStrategy(CompactionTriggers.MessagesExceed(7)),
|
|
|
|
// 2. Moderate: use an LLM to summarize older conversation spans into a concise message
|
|
new SummarizationCompactionStrategy(summarizerChatClient, CompactionTriggers.TokensExceed(0x500)),
|
|
|
|
// 3. Aggressive: keep only the last N user turns and their responses
|
|
new SlidingWindowCompactionStrategy(CompactionTriggers.TurnsExceed(4)),
|
|
|
|
// 4. Emergency: drop oldest groups until under the token budget
|
|
new TruncationCompactionStrategy(CompactionTriggers.TokensExceed(0x8000)));
|
|
|
|
// Create the agent with a CompactionProvider that uses the compaction pipeline.
|
|
AIAgent agent =
|
|
agentChatClient
|
|
.AsBuilder()
|
|
// Note: Adding the CompactionProvider at the builder level means it will be applied to all agents
|
|
// built from this builder and will manage context for both agent messages and tool calls.
|
|
.UseAIContextProviders(new CompactionProvider(compactionPipeline))
|
|
.BuildAIAgent(
|
|
new ChatClientAgentOptions
|
|
{
|
|
Name = "ShoppingAssistant",
|
|
ChatOptions = new()
|
|
{
|
|
Instructions =
|
|
"""
|
|
You are a helpful, but long winded, shopping assistant.
|
|
Help the user look up prices and compare products.
|
|
You MUST use the LookupPrice tool for every price question — never answer price questions from memory.
|
|
When responding, Be sure to be extra descriptive and use as
|
|
many words as possible without sounding ridiculous.
|
|
""",
|
|
Tools = [AIFunctionFactory.Create(LookupPrice)]
|
|
},
|
|
// Note: AIContextProviders may be specified here instead of ChatClientBuilder.UseAIContextProviders.
|
|
// Specifying compaction at the agent level skips compaction in the function calling loop.
|
|
//AIContextProviders = [new CompactionProvider(compactionPipeline)]
|
|
});
|
|
|
|
AgentSession session = await agent.CreateSessionAsync();
|
|
|
|
// Helper to print chat history size
|
|
void PrintChatHistory()
|
|
{
|
|
if (session.TryGetInMemoryChatHistory(out var history))
|
|
{
|
|
Console.ForegroundColor = ConsoleColor.Cyan;
|
|
Console.WriteLine($"\n[Messages: #{history.Count}]\n");
|
|
Console.ResetColor();
|
|
}
|
|
}
|
|
|
|
// Run a multi-turn conversation with tool calls to exercise the pipeline.
|
|
string[] prompts =
|
|
[
|
|
"What's the price of a laptop?",
|
|
"How about a keyboard?",
|
|
"And a mouse?",
|
|
"Which product is the cheapest?",
|
|
"Can you compare the laptop and the keyboard for me?",
|
|
"What was the first product I asked about?",
|
|
"Thank you!",
|
|
];
|
|
|
|
foreach (string prompt in prompts)
|
|
{
|
|
Console.ForegroundColor = ConsoleColor.Cyan;
|
|
Console.Write("\n[User] ");
|
|
Console.ResetColor();
|
|
Console.WriteLine(prompt);
|
|
Console.ForegroundColor = ConsoleColor.Cyan;
|
|
Console.Write("\n[Agent] ");
|
|
Console.ResetColor();
|
|
Console.WriteLine(await agent.RunAsync(prompt, session));
|
|
|
|
PrintChatHistory();
|
|
}
|