mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
.NET: [BREAKING] Support Checkpoint Serialization (#735)
* feat: Support Checkpoint Serialization * Implements serialization roundtripping for checkpoints. * Adds support for JSON serialization * Adds FileSystem-based checkpoint persistence * fix: Executor State does not deserialize correctly The StateManager was not properly handling delay-deserialized values. * Fix PortableValue handling in StateManager (this makes it delegate to PortableValue the uwnrapping) * Fix UnitTest to actually test checkpoint serialization * Additional review comment fixes --------- Co-authored-by: Chris <66376200+crickman@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
Unverified
parent
2a04c4197e
commit
2015f0dc09
+1
-1
@@ -32,7 +32,7 @@ public static class Program
|
||||
var workflow = WorkflowHelper.GetWorkflow();
|
||||
|
||||
// Create checkpoint manager
|
||||
var checkpointManager = new CheckpointManager();
|
||||
var checkpointManager = CheckpointManager.Default;
|
||||
var checkpoints = new List<CheckpointInfo>();
|
||||
|
||||
// Execute the workflow and save checkpoints
|
||||
|
||||
@@ -31,7 +31,7 @@ public static class Program
|
||||
var workflow = WorkflowHelper.GetWorkflow();
|
||||
|
||||
// Create checkpoint manager
|
||||
var checkpointManager = new CheckpointManager();
|
||||
var checkpointManager = CheckpointManager.Default;
|
||||
var checkpoints = new List<CheckpointInfo>();
|
||||
|
||||
// Execute the workflow and save checkpoints
|
||||
|
||||
+4
-4
@@ -34,7 +34,7 @@ public static class Program
|
||||
var workflow = WorkflowHelper.GetWorkflow();
|
||||
|
||||
// Create checkpoint manager
|
||||
var checkpointManager = new CheckpointManager();
|
||||
var checkpointManager = CheckpointManager.Default;
|
||||
var checkpoints = new List<CheckpointInfo>();
|
||||
|
||||
// Execute the workflow and save checkpoints
|
||||
@@ -102,9 +102,9 @@ public static class Program
|
||||
|
||||
private static ExternalResponse HandleExternalRequest(ExternalRequest request)
|
||||
{
|
||||
if (request.Port.Request == typeof(SignalWithNumber))
|
||||
var signal = request.DataAs<SignalWithNumber>();
|
||||
if (signal is not null)
|
||||
{
|
||||
var signal = (SignalWithNumber)request.Data;
|
||||
switch (signal.Signal)
|
||||
{
|
||||
case NumberSignal.Init:
|
||||
@@ -119,7 +119,7 @@ public static class Program
|
||||
}
|
||||
}
|
||||
|
||||
throw new NotSupportedException($"Request {request.Port.Request} is not supported");
|
||||
throw new NotSupportedException($"Request {request.PortInfo.RequestType} is not supported");
|
||||
}
|
||||
|
||||
private static int ReadIntegerFromConsole(string prompt)
|
||||
|
||||
+7
-7
@@ -75,10 +75,10 @@ public static class Program
|
||||
// After the email assistant writes a response, it will be sent to the send email executor
|
||||
.AddEdge(emailAssistantExecutor, sendEmailExecutor)
|
||||
// Save the analysis result to the database if summary is not needed
|
||||
.AddEdge(
|
||||
.AddEdge<AnalysisResult>(
|
||||
emailAnalysisExecutor,
|
||||
databaseAccessExecutor,
|
||||
condition: analysisResult => analysisResult is AnalysisResult result && result.EmailLength <= LongEmailThreshold)
|
||||
condition: analysisResult => analysisResult is not null && analysisResult.EmailLength <= LongEmailThreshold)
|
||||
// Save the analysis result to the database with summary
|
||||
.AddEdge(emailSummaryExecutor, databaseAccessExecutor);
|
||||
var workflow = builder.Build<ChatMessage>();
|
||||
@@ -107,21 +107,21 @@ public static class Program
|
||||
/// Creates a partitioner for routing messages based on the analysis result.
|
||||
/// </summary>
|
||||
/// <returns>A function that takes an analysis result and returns the target partitions.</returns>
|
||||
private static Func<object?, int, IEnumerable<int>> GetPartitioner()
|
||||
private static Func<AnalysisResult?, int, IEnumerable<int>> GetPartitioner()
|
||||
{
|
||||
return (analysisResult, targetCount) =>
|
||||
{
|
||||
if (analysisResult is AnalysisResult result)
|
||||
if (analysisResult is not null)
|
||||
{
|
||||
if (result.spamDecision == SpamDecision.Spam)
|
||||
if (analysisResult.spamDecision == SpamDecision.Spam)
|
||||
{
|
||||
return [0]; // Route to spam handler
|
||||
}
|
||||
else if (result.spamDecision == SpamDecision.NotSpam)
|
||||
else if (analysisResult.spamDecision == SpamDecision.NotSpam)
|
||||
{
|
||||
List<int> targets = [1]; // Route to the email assistant
|
||||
|
||||
if (result.EmailLength > LongEmailThreshold)
|
||||
if (analysisResult.EmailLength > LongEmailThreshold)
|
||||
{
|
||||
targets.Add(2); // Route to the email summarizer too
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ internal sealed class Program
|
||||
// Run the workflow, just like any other workflow
|
||||
string input = this.GetWorkflowInput();
|
||||
|
||||
CheckpointManager checkpointManager = new();
|
||||
CheckpointManager checkpointManager = CheckpointManager.Default;
|
||||
Checkpointed<StreamingRun> run = await InProcessExecution.StreamAsync(workflow, input, checkpointManager);
|
||||
|
||||
bool isComplete = false;
|
||||
@@ -151,7 +151,7 @@ internal sealed class Program
|
||||
Debug.WriteLine($"ACTION EXIT #{actionComplete.ActionId} [{actionComplete.ActionType}]");
|
||||
break;
|
||||
|
||||
case ExecutorFailureEvent executorFailure:
|
||||
case ExecutorFailedEvent executorFailure:
|
||||
Debug.WriteLine($"STEP ERROR #{executorFailure.ExecutorId}: {executorFailure.Data?.Message ?? "Unknown"}");
|
||||
break;
|
||||
|
||||
@@ -256,7 +256,7 @@ internal sealed class Program
|
||||
}
|
||||
private static InputResponse HandleExternalRequest(ExternalRequest request)
|
||||
{
|
||||
InputRequest? message = request.Data as InputRequest;
|
||||
InputRequest? message = request.Data.As<InputRequest>();
|
||||
string? userInput = null;
|
||||
do
|
||||
{
|
||||
|
||||
+3
-3
@@ -50,9 +50,9 @@ public static class Program
|
||||
|
||||
private static ExternalResponse HandleExternalRequest(ExternalRequest request)
|
||||
{
|
||||
if (request.Port.Request == typeof(NumberSignal))
|
||||
if (request.DataIs<NumberSignal>())
|
||||
{
|
||||
var signal = (NumberSignal)request.Data;
|
||||
var signal = request.DataAs<NumberSignal>();
|
||||
switch (signal)
|
||||
{
|
||||
case NumberSignal.Init:
|
||||
@@ -67,7 +67,7 @@ public static class Program
|
||||
}
|
||||
}
|
||||
|
||||
throw new NotSupportedException($"Request {request.Port.Request} is not supported");
|
||||
throw new NotSupportedException($"Request {request.PortInfo.RequestType} is not supported");
|
||||
}
|
||||
|
||||
private static int ReadIntegerFromConsole(string prompt)
|
||||
|
||||
Reference in New Issue
Block a user