mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Initial draft of actor runtime abstractions (#197)
* Initial draft of actor runtime abstractions
This commit is contained in:
-9
@@ -6,24 +6,15 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Shared.Diagnostics;
|
||||
using OpenAI;
|
||||
using OpenAI.Assistants;
|
||||
using OpenAI.Audio;
|
||||
using OpenAI.Chat;
|
||||
using OpenAI.Embeddings;
|
||||
|
||||
#pragma warning disable CA1031 // Do not catch general exception types
|
||||
#pragma warning disable SA1005 // Single line comments should begin with single space
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>$(ProjectsTargetFrameworks)</TargetFrameworks>
|
||||
<TargetFrameworks Condition="'$(Configuration)' == 'Debug'">$(ProjectsDebugTargetFrameworks)</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<RootNamespace>GettingStarted</RootNamespace>
|
||||
<OutputType>Library</OutputType>
|
||||
@@ -12,6 +7,13 @@
|
||||
<NoWarn>$(NoWarn);CA1707;CA1716;IDE0009;IDE1006;OPENAI001;</NoWarn>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<InjectSharedSamples>true</InjectSharedSamples>
|
||||
<InjectSharedThrow>true</InjectSharedThrow>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>$(ProjectsTargetFrameworks)</TargetFrameworks>
|
||||
<TargetFrameworks Condition="'$(Configuration)' == 'Debug'">$(ProjectsDebugTargetFrameworks)</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -29,6 +31,12 @@
|
||||
<PackageReference Include="OpenTelemetry" />
|
||||
<PackageReference Include="OpenTelemetry.Exporter.Console" />
|
||||
<PackageReference Include="OpenTelemetry.Extensions.Hosting" />
|
||||
<PackageReference Include="coverlet.collector" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" />
|
||||
<PackageReference Include="Moq" />
|
||||
<PackageReference Include="xunit" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" />
|
||||
<PackageReference Include="System.Linq.Async" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -42,11 +50,11 @@
|
||||
<Using Include="Microsoft.Shared.SampleUtilities" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<InjectSharedThrow>true</InjectSharedThrow>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
<Using Include="Xunit.Abstractions" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="Resources\*">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Text.Json;
|
||||
|
||||
namespace Microsoft.Extensions.AI.Agents.Runtime.Samples;
|
||||
|
||||
/// <summary>
|
||||
/// Example demonstrating how to use the InMemoryActorStateStorage.
|
||||
/// </summary>
|
||||
public static class InMemoryActorStateStorageExample
|
||||
{
|
||||
/// <summary>
|
||||
/// Demonstrates the basic usage of InMemoryActorStateStorage.
|
||||
/// </summary>
|
||||
/// <returns>A task representing the asynchronous operation.</returns>
|
||||
public static async Task RunAsync()
|
||||
{
|
||||
// Create an in-memory actor state storage
|
||||
var storage = new InMemoryActorStateStorage();
|
||||
|
||||
// Create an actor ID
|
||||
var actorId = new ActorId("ExampleActor", "instance1");
|
||||
|
||||
Console.WriteLine("=== InMemoryActorStateStorage Example ===");
|
||||
Console.WriteLine();
|
||||
|
||||
// 1. Write some initial state
|
||||
Console.WriteLine("1. Writing initial state...");
|
||||
var initialOperations = new List<ActorStateWriteOperation>
|
||||
{
|
||||
new SetValueOperation("name", JsonSerializer.SerializeToElement("John Doe")),
|
||||
new SetValueOperation("age", JsonSerializer.SerializeToElement(30)),
|
||||
new SetValueOperation("city", JsonSerializer.SerializeToElement("Seattle"))
|
||||
};
|
||||
|
||||
var writeResult = await storage.WriteStateAsync(actorId, initialOperations, "0").ConfigureAwait(false);
|
||||
Console.WriteLine($" Write successful: {writeResult.Success}");
|
||||
Console.WriteLine($" New ETag: {writeResult.ETag}");
|
||||
Console.WriteLine($" Actor count: {storage.ActorCount}");
|
||||
Console.WriteLine($" Key count for actor: {storage.GetKeyCount(actorId)}");
|
||||
Console.WriteLine();
|
||||
|
||||
// 2. Read the state back
|
||||
Console.WriteLine("2. Reading state back...");
|
||||
var readOperations = new List<ActorStateReadOperation>
|
||||
{
|
||||
new GetValueOperation("name"),
|
||||
new GetValueOperation("age"),
|
||||
new GetValueOperation("city"),
|
||||
new GetValueOperation("nonexistent"), // This won't exist
|
||||
new ListKeysOperation(continuationToken: null) // List all keys
|
||||
};
|
||||
|
||||
var readResult = await storage.ReadStateAsync(actorId, readOperations).ConfigureAwait(false);
|
||||
Console.WriteLine($" Current ETag: {readResult.ETag}");
|
||||
Console.WriteLine(" Results:");
|
||||
|
||||
foreach (var result in readResult.Results)
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
case GetValueResult getValue:
|
||||
Console.WriteLine($" - Get value: {getValue.Value?.ToString() ?? "null"}");
|
||||
break;
|
||||
|
||||
case ListKeysResult listKeys:
|
||||
Console.WriteLine($" - Keys: [{string.Join(", ", listKeys.Keys)}]");
|
||||
break;
|
||||
}
|
||||
}
|
||||
Console.WriteLine();
|
||||
|
||||
// 3. Update some values
|
||||
Console.WriteLine("3. Updating state...");
|
||||
var updateOperations = new List<ActorStateWriteOperation>
|
||||
{
|
||||
new SetValueOperation("age", JsonSerializer.SerializeToElement(31)), // Update age
|
||||
new SetValueOperation("email", JsonSerializer.SerializeToElement("john@example.com")), // Add email
|
||||
new RemoveKeyOperation("city") // Remove city
|
||||
};
|
||||
|
||||
var updateResult = await storage.WriteStateAsync(actorId, updateOperations, writeResult.ETag).ConfigureAwait(false);
|
||||
Console.WriteLine($" Update successful: {updateResult.Success}");
|
||||
Console.WriteLine($" New ETag: {updateResult.ETag}");
|
||||
Console.WriteLine($" Key count for actor: {storage.GetKeyCount(actorId)}");
|
||||
Console.WriteLine();
|
||||
|
||||
// 4. Try to update with wrong ETag (should fail)
|
||||
Console.WriteLine("4. Trying to update with wrong ETag...");
|
||||
var failingOperations = new List<ActorStateWriteOperation>
|
||||
{
|
||||
new SetValueOperation("shouldFail", JsonSerializer.SerializeToElement("this should fail"))
|
||||
};
|
||||
|
||||
var failResult = await storage.WriteStateAsync(actorId, failingOperations, "wrong-etag").ConfigureAwait(false);
|
||||
Console.WriteLine($" Update successful: {failResult.Success}");
|
||||
Console.WriteLine($" Current ETag: {failResult.ETag}");
|
||||
Console.WriteLine();
|
||||
|
||||
// 5. Read final state
|
||||
Console.WriteLine("5. Reading final state...");
|
||||
var finalReadOperations = new List<ActorStateReadOperation>
|
||||
{
|
||||
new ListKeysOperation(continuationToken: null)
|
||||
};
|
||||
|
||||
var finalReadResult = await storage.ReadStateAsync(actorId, finalReadOperations).ConfigureAwait(false);
|
||||
var finalKeys = finalReadResult.Results.OfType<ListKeysResult>().First();
|
||||
Console.WriteLine($" Final keys: [{string.Join(", ", finalKeys.Keys)}]");
|
||||
|
||||
// 6. Read each value
|
||||
foreach (var key in finalKeys.Keys)
|
||||
{
|
||||
var valueReadOperations = new List<ActorStateReadOperation>
|
||||
{
|
||||
new GetValueOperation(key)
|
||||
};
|
||||
|
||||
var valueReadResult = await storage.ReadStateAsync(actorId, valueReadOperations).ConfigureAwait(false);
|
||||
var getValue = valueReadResult.Results.OfType<GetValueResult>().First();
|
||||
Console.WriteLine($" - {key}: {getValue.Value}");
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("=== Example Complete ===");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user