mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
d3f0c33180
* Checkpoint * Checkpoint * Stable * Strategies * Updated * Encoding * Formatting * Cleanup * Formatting * Tests * Tuning * Update tests * Test update * Remove working solution * Add sample to solution * Sample readyme * Experimental * Format * Formatting * Encoding * Support IChatReducer * Sample output formatting * Initial plan * Replace CompactingChatClient with MessageCompactionContextProvider Co-authored-by: crickman <66376200+crickman@users.noreply.github.com> * Boundary condition * Fix encoding * Fix cast * Test coverage * Namespace * Improvements * Efficiency * Cleanup * Detect service managed conversation * Fix namespace * Fix merge * Fix test expectation * Update dotnet/src/Microsoft.Agents.AI.Abstractions/InMemoryChatHistoryProvider.cs Co-authored-by: westey <164392973+westey-m@users.noreply.github.com> * Address PR comments (x1) * Update comment * Update comments * Clean-up * Format output * Sync sample comment * Fix condition * Adjust data-flow * Address comments (x2) * Direct compaction * Fix summarization content * Argument check / fix count calculation * Minor follow-up * Diagnostics * Minor updates * Fix state test * Fix sliding window perf * Stable state keys * Increase size computation * Formatting * Add README.md for Agent_Step18_CompactionPipeline sample (#4574) * Sample comments * Updated * Update dotnet/src/Microsoft.Agents.AI/Compaction/MessageIndex.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update dotnet/tests/Microsoft.Agents.AI.UnitTests/Compaction/CompactionProviderTests.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update dotnet/src/Microsoft.Agents.AI/Compaction/MessageIndex.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Address copilot comments * Fix namespace * Comments / convensions * Prefix `MessageGroup` and `MessageIndex` * Fix sliding window * Update dotnet/src/Microsoft.Agents.AI/Compaction/SummarizationCompactionStrategy.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update dotnet/src/Microsoft.Agents.AI.Abstractions/InMemoryChatHistoryProvider.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Python alignment * Fix merge * Fix equality, readme, and sample * Readme update and ToolResult fix * Update dotnet/src/Microsoft.Agents.AI/Compaction/SummarizationCompactionStrategy.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update dotnet/samples/02-agents/Agents/Agent_Step18_CompactionPipeline/README.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Simplify readme * Update dotnet/samples/02-agents/Agents/Agent_Step18_CompactionPipeline/README.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Remove example * Remove unused --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: westey <164392973+westey-m@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
209 lines
6.4 KiB
C#
209 lines
6.4 KiB
C#
// Copyright (c) Microsoft. All rights reserved.
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.Agents.AI.Compaction;
|
|
using Microsoft.Extensions.AI;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace Microsoft.Agents.AI.UnitTests.Compaction;
|
|
|
|
/// <summary>
|
|
/// Contains tests for the <see cref="PipelineCompactionStrategy"/> class.
|
|
/// </summary>
|
|
public class PipelineCompactionStrategyTests
|
|
{
|
|
[Fact]
|
|
public async Task CompactAsyncExecutesAllStrategiesInOrderAsync()
|
|
{
|
|
// Arrange
|
|
List<string> executionOrder = [];
|
|
TestCompactionStrategy strategy1 = new(
|
|
_ =>
|
|
{
|
|
executionOrder.Add("first");
|
|
return false;
|
|
});
|
|
|
|
TestCompactionStrategy strategy2 = new(
|
|
_ =>
|
|
{
|
|
executionOrder.Add("second");
|
|
return false;
|
|
});
|
|
|
|
PipelineCompactionStrategy pipeline = new(strategy1, strategy2);
|
|
CompactionMessageIndex groups = CompactionMessageIndex.Create(
|
|
[
|
|
new ChatMessage(ChatRole.User, "Hello"),
|
|
new ChatMessage(ChatRole.Assistant, "Hi!"),
|
|
]);
|
|
|
|
// Act
|
|
await pipeline.CompactAsync(groups);
|
|
|
|
// Assert
|
|
Assert.Equal(["first", "second"], executionOrder);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task CompactAsyncReturnsFalseWhenNoStrategyCompactsAsync()
|
|
{
|
|
// Arrange
|
|
TestCompactionStrategy strategy1 = new(_ => false);
|
|
|
|
PipelineCompactionStrategy pipeline = new(strategy1);
|
|
CompactionMessageIndex groups = CompactionMessageIndex.Create(
|
|
[
|
|
new ChatMessage(ChatRole.User, "Hello"),
|
|
new ChatMessage(ChatRole.Assistant, "Hi!"),
|
|
]);
|
|
|
|
// Act
|
|
bool result = await pipeline.CompactAsync(groups);
|
|
|
|
// Assert
|
|
Assert.False(result);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task CompactAsyncReturnsTrueWhenAnyStrategyCompactsAsync()
|
|
{
|
|
// Arrange
|
|
TestCompactionStrategy strategy1 = new(_ => false);
|
|
TestCompactionStrategy strategy2 = new(_ => true);
|
|
|
|
PipelineCompactionStrategy pipeline = new(strategy1, strategy2);
|
|
CompactionMessageIndex groups = CompactionMessageIndex.Create(
|
|
[
|
|
new ChatMessage(ChatRole.User, "Hello"),
|
|
new ChatMessage(ChatRole.Assistant, "Hi!"),
|
|
]);
|
|
|
|
// Act
|
|
bool result = await pipeline.CompactAsync(groups);
|
|
|
|
// Assert
|
|
Assert.True(result);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task CompactAsyncContinuesAfterFirstCompactionAsync()
|
|
{
|
|
// Arrange
|
|
TestCompactionStrategy strategy1 = new(_ => true);
|
|
TestCompactionStrategy strategy2 = new(_ => false);
|
|
|
|
PipelineCompactionStrategy pipeline = new(strategy1, strategy2);
|
|
CompactionMessageIndex groups = CompactionMessageIndex.Create(
|
|
[
|
|
new ChatMessage(ChatRole.User, "Hello"),
|
|
new ChatMessage(ChatRole.Assistant, "Hi!"),
|
|
]);
|
|
|
|
// Act
|
|
await pipeline.CompactAsync(groups);
|
|
|
|
// Assert — both strategies were called
|
|
Assert.Equal(1, strategy1.ApplyCallCount);
|
|
Assert.Equal(1, strategy2.ApplyCallCount);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task CompactAsyncComposesStrategiesEndToEndAsync()
|
|
{
|
|
// Arrange — pipeline: first exclude oldest 2 non-system groups, then exclude 2 more
|
|
static void ExcludeOldest2(CompactionMessageIndex index)
|
|
{
|
|
int excluded = 0;
|
|
foreach (CompactionMessageGroup group in index.Groups)
|
|
{
|
|
if (!group.IsExcluded && group.Kind != CompactionGroupKind.System && excluded < 2)
|
|
{
|
|
group.IsExcluded = true;
|
|
excluded++;
|
|
}
|
|
}
|
|
}
|
|
|
|
TestCompactionStrategy phase1 = new(
|
|
index =>
|
|
{
|
|
ExcludeOldest2(index);
|
|
return true;
|
|
});
|
|
|
|
TestCompactionStrategy phase2 = new(
|
|
index =>
|
|
{
|
|
ExcludeOldest2(index);
|
|
return true;
|
|
});
|
|
|
|
PipelineCompactionStrategy pipeline = new(phase1, phase2);
|
|
|
|
CompactionMessageIndex groups = CompactionMessageIndex.Create(
|
|
[
|
|
new ChatMessage(ChatRole.System, "You are helpful."),
|
|
new ChatMessage(ChatRole.User, "Q1"),
|
|
new ChatMessage(ChatRole.Assistant, "A1"),
|
|
new ChatMessage(ChatRole.User, "Q2"),
|
|
new ChatMessage(ChatRole.Assistant, "A2"),
|
|
new ChatMessage(ChatRole.User, "Q3"),
|
|
]);
|
|
|
|
// Act
|
|
bool result = await pipeline.CompactAsync(groups);
|
|
|
|
// Assert — system is preserved, phase1 excluded Q1+A1, phase2 excluded Q2+A2 → System + Q3
|
|
Assert.True(result);
|
|
Assert.Equal(2, groups.IncludedGroupCount);
|
|
|
|
List<ChatMessage> included = [.. groups.GetIncludedMessages()];
|
|
Assert.Equal(2, included.Count);
|
|
Assert.Equal("You are helpful.", included[0].Text);
|
|
Assert.Equal("Q3", included[1].Text);
|
|
|
|
Assert.Equal(1, phase1.ApplyCallCount);
|
|
Assert.Equal(1, phase2.ApplyCallCount);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task CompactAsyncEmptyPipelineReturnsFalseAsync()
|
|
{
|
|
// Arrange
|
|
PipelineCompactionStrategy pipeline = new(new List<CompactionStrategy>());
|
|
CompactionMessageIndex groups = CompactionMessageIndex.Create([new ChatMessage(ChatRole.User, "Hello")]);
|
|
|
|
// Act
|
|
bool result = await pipeline.CompactAsync(groups);
|
|
|
|
// Assert
|
|
Assert.False(result);
|
|
}
|
|
|
|
/// <summary>
|
|
/// A simple test implementation of <see cref="CompactionStrategy"/> that delegates to a synchronous callback.
|
|
/// </summary>
|
|
private sealed class TestCompactionStrategy : CompactionStrategy
|
|
{
|
|
private readonly Func<CompactionMessageIndex, bool> _applyFunc;
|
|
|
|
public TestCompactionStrategy(Func<CompactionMessageIndex, bool> applyFunc)
|
|
: base(CompactionTriggers.Always)
|
|
{
|
|
this._applyFunc = applyFunc;
|
|
}
|
|
|
|
public int ApplyCallCount { get; private set; }
|
|
|
|
protected override ValueTask<bool> CompactCoreAsync(CompactionMessageIndex index, ILogger logger, CancellationToken cancellationToken)
|
|
{
|
|
this.ApplyCallCount++;
|
|
return new(this._applyFunc(index));
|
|
}
|
|
}
|
|
}
|