mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
.NET Workflows - Declarative update for AzureAgentProvider usage (#907)
* Updated * Update dotnet/src/Microsoft.Agents.Workflows.Declarative/Extensions/IWorkflowContextExtensions.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Constant / override * Namespace * Protect against race * Simplify collection usage * Rollback name resolution * One more rollback --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
@@ -43,15 +42,20 @@ public sealed class AzureAgentProvider(string projectEndpoint, TokenCredential p
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async Task CreateMessageAsync(string conversationId, ChatMessage conversationMessage, CancellationToken cancellationToken = default)
|
||||
public override Task CreateMessageAsync(string conversationId, ChatMessage conversationMessage, CancellationToken cancellationToken = default)
|
||||
{
|
||||
await this.GetAgentsClient().Messages.CreateMessageAsync(
|
||||
// TODO: Switch to asynchronous "CreateMessageAsync", when fix properly applied:
|
||||
// BUG: https://github.com/Azure/azure-sdk-for-net/issues/52571
|
||||
// PR: https://github.com/Azure/azure-sdk-for-net/pull/52653
|
||||
this.GetAgentsClient().Messages.CreateMessage(
|
||||
conversationId,
|
||||
role: s_roleMap[conversationMessage.Role.Value.ToUpperInvariant()],
|
||||
contentBlocks: GetContent(),
|
||||
attachments: null,
|
||||
metadata: GetMetadata(),
|
||||
cancellationToken).ConfigureAwait(false);
|
||||
cancellationToken);
|
||||
|
||||
return Task.CompletedTask;
|
||||
|
||||
Dictionary<string, string>? GetMetadata()
|
||||
{
|
||||
|
||||
+30
@@ -1,5 +1,6 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Agents.Workflows.Declarative.Interpreter;
|
||||
@@ -36,6 +37,35 @@ internal static class IWorkflowContextExtensions
|
||||
public static FormulaValue ReadState(this IWorkflowContext context, string key, string? scopeName = null) =>
|
||||
DeclarativeContext(context).State.Get(key, scopeName);
|
||||
|
||||
public static async ValueTask QueueConversationUpdateAsync(this IWorkflowContext context, string conversationId)
|
||||
{
|
||||
RecordValue conversation = (RecordValue)context.ReadState(SystemScope.Names.Conversation, VariableScopeNames.System);
|
||||
conversation.UpdateField("Id", FormulaValue.New(conversationId));
|
||||
await context.QueueSystemUpdateAsync(SystemScope.Names.Conversation, conversation).ConfigureAwait(false);
|
||||
await context.QueueSystemUpdateAsync(SystemScope.Names.ConversationId, FormulaValue.New(conversationId)).ConfigureAwait(false);
|
||||
|
||||
await context.AddEventAsync(new ConversationUpdateEvent(conversationId)).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
// Ensure "System.Conversation.Id" and "System.ConversationId" are properly initialized when referenced.
|
||||
public static async ValueTask EnsureWorkflowConversationAsync(this IWorkflowContext context, WorkflowAgentProvider agentProvider, StringExpression expression, CancellationToken cancellationToken)
|
||||
{
|
||||
if (expression.IsVariableReference &&
|
||||
expression.VariableReference.IsVariableReferenceWithScope(VariableScopeNames.System, out string? variableName))
|
||||
{
|
||||
if (string.Equals(variableName, SystemScope.Names.Conversation, StringComparison.Ordinal) ||
|
||||
string.Equals(variableName, SystemScope.Names.ConversationId, StringComparison.Ordinal))
|
||||
{
|
||||
FormulaValue variableValue = context.ReadState(SystemScope.Names.ConversationId, VariableScopeNames.System);
|
||||
if (variableValue is BlankValue)
|
||||
{
|
||||
string conversationId = await agentProvider.CreateConversationAsync(cancellationToken).ConfigureAwait(false);
|
||||
await context.QueueConversationUpdateAsync(conversationId).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static DeclarativeWorkflowContext DeclarativeContext(IWorkflowContext context)
|
||||
{
|
||||
if (context is not DeclarativeWorkflowContext declarativeContext)
|
||||
|
||||
+4
-2
@@ -17,8 +17,10 @@ internal sealed class AddConversationMessageExecutor(AddConversationMessage mode
|
||||
{
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
StringExpression conversationExpression = Throw.IfNull(this.Model.ConversationId, $"{nameof(this.Model)}.{nameof(this.Model.ConversationId)}");
|
||||
string conversationId = this.Evaluator.GetValue(conversationExpression).Value;
|
||||
Throw.IfNull(this.Model.ConversationId, $"{nameof(this.Model)}.{nameof(this.Model.ConversationId)}");
|
||||
await context.EnsureWorkflowConversationAsync(agentProvider, this.Model.ConversationId, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
string conversationId = this.Evaluator.GetValue(this.Model.ConversationId).Value;
|
||||
|
||||
ChatMessage newMessage = new(this.Model.Role.Value.ToChatRole(), [.. this.GetContent()]) { AdditionalProperties = this.GetMetadata() };
|
||||
|
||||
|
||||
+4
-1
@@ -17,7 +17,10 @@ internal sealed class CopyConversationMessagesExecutor(CopyConversationMessages
|
||||
{
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
string conversationId = this.Evaluator.GetValue(Throw.IfNull(this.Model.ConversationId, $"{nameof(this.Model)}.{nameof(this.Model.ConversationId)}")).Value;
|
||||
Throw.IfNull(this.Model.ConversationId, $"{nameof(this.Model)}.{nameof(this.Model.ConversationId)}");
|
||||
await context.EnsureWorkflowConversationAsync(agentProvider, this.Model.ConversationId, cancellationToken).ConfigureAwait(false);
|
||||
string conversationId = this.Evaluator.GetValue(this.Model.ConversationId).Value;
|
||||
|
||||
DataValue? inputMessages = this.GetInputMessages();
|
||||
|
||||
if (inputMessages is not null)
|
||||
|
||||
+1
-7
@@ -11,7 +11,6 @@ using Microsoft.Bot.ObjectModel;
|
||||
using Microsoft.Bot.ObjectModel.Abstractions;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Microsoft.Extensions.AI.Agents;
|
||||
using Microsoft.PowerFx.Types;
|
||||
using Microsoft.Shared.Diagnostics;
|
||||
|
||||
namespace Microsoft.Agents.Workflows.Declarative.ObjectModel;
|
||||
@@ -79,12 +78,7 @@ internal sealed class InvokeAzureAgentExecutor(InvokeAzureAgent model, WorkflowA
|
||||
{
|
||||
conversationId = assignValue;
|
||||
|
||||
RecordValue conversation = (RecordValue)context.ReadState(SystemScope.Names.Conversation, VariableScopeNames.System);
|
||||
conversation.UpdateField("Id", FormulaValue.New(conversationId));
|
||||
await context.QueueSystemUpdateAsync(SystemScope.Names.Conversation, conversation).ConfigureAwait(false);
|
||||
await context.QueueSystemUpdateAsync(SystemScope.Names.ConversationId, FormulaValue.New(conversationId)).ConfigureAwait(false);
|
||||
|
||||
await context.AddEventAsync(new ConversationUpdateEvent(conversationId)).ConfigureAwait(false);
|
||||
await context.QueueConversationUpdateAsync(conversationId).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-1
@@ -16,7 +16,9 @@ internal sealed class RetrieveConversationMessageExecutor(RetrieveConversationMe
|
||||
{
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
string conversationId = this.Evaluator.GetValue(Throw.IfNull(this.Model.ConversationId, $"{nameof(this.Model)}.{nameof(this.Model.ConversationId)}")).Value;
|
||||
Throw.IfNull(this.Model.ConversationId, $"{nameof(this.Model)}.{nameof(this.Model.ConversationId)}");
|
||||
await context.EnsureWorkflowConversationAsync(agentProvider, this.Model.ConversationId, cancellationToken).ConfigureAwait(false);
|
||||
string conversationId = this.Evaluator.GetValue(this.Model.ConversationId).Value;
|
||||
string messageId = this.Evaluator.GetValue(Throw.IfNull(this.Model.MessageId, $"{nameof(this.Model)}.{nameof(this.Model.MessageId)}")).Value;
|
||||
|
||||
ChatMessage message = await agentProvider.GetMessageAsync(conversationId, messageId, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
+3
-1
@@ -18,7 +18,9 @@ internal sealed class RetrieveConversationMessagesExecutor(RetrieveConversationM
|
||||
{
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
string conversationId = this.Evaluator.GetValue(Throw.IfNull(this.Model.ConversationId, $"{nameof(this.Model)}.{nameof(this.Model.ConversationId)}")).Value;
|
||||
Throw.IfNull(this.Model.ConversationId, $"{nameof(this.Model)}.{nameof(this.Model.ConversationId)}");
|
||||
await context.EnsureWorkflowConversationAsync(agentProvider, this.Model.ConversationId, cancellationToken).ConfigureAwait(false);
|
||||
string conversationId = this.Evaluator.GetValue(this.Model.ConversationId).Value;
|
||||
|
||||
ChatMessage[] messages = await agentProvider.GetMessagesAsync(
|
||||
conversationId,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Collections.Frozen;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Agents.Workflows.Declarative.Extensions;
|
||||
@@ -14,7 +13,7 @@ using Microsoft.PowerFx.Types;
|
||||
|
||||
namespace Microsoft.Agents.Workflows.Declarative.PowerFx;
|
||||
|
||||
internal sealed record class WorkflowTypeInfo(FrozenSet<string> EnvironmentVariables, IEnumerable<VariableInformationDiagnostic> UserVariables);
|
||||
internal sealed record class WorkflowTypeInfo(ISet<string> EnvironmentVariables, IList<VariableInformationDiagnostic> UserVariables);
|
||||
|
||||
internal static class WorkflowDiagnostics
|
||||
{
|
||||
@@ -26,8 +25,8 @@ internal static class WorkflowDiagnostics
|
||||
|
||||
return
|
||||
new WorkflowTypeInfo(
|
||||
semanticModel.GetAllEnvironmentVariablesReferencedInTheBot().ToFrozenSet(),
|
||||
semanticModel.GetVariables(workflowElement.SchemaName.Value).Where(x => !x.IsSystemVariable).Select(v => v.ToDiagnostic()));
|
||||
semanticModel.GetAllEnvironmentVariablesReferencedInTheBot(),
|
||||
[.. semanticModel.GetVariables(workflowElement.SchemaName.Value).Where(x => !x.IsSystemVariable).Select(v => v.ToDiagnostic())]);
|
||||
}
|
||||
|
||||
public static void Initialize<TElement>(this WorkflowFormulaState scopes, TElement workflowElement, IConfiguration? configuration) where TElement : BotElement, IDialogBase
|
||||
|
||||
Reference in New Issue
Block a user