Udostępnij przez


Podstawowe pojęcia dotyczące przepływów pracy programu Microsoft Agent Framework — funkcje wykonawcze

Ten dokument zawiera szczegółowe omówienie składnika funkcji wykonawczej systemu przepływu pracy programu Microsoft Agent Framework.

Przegląd

Funkcje wykonawcze to podstawowe bloki konstrukcyjne, które przetwarzają komunikaty w przepływie pracy. Są to autonomiczne jednostki przetwarzania, które odbierają komunikaty typizowane, wykonują operacje i mogą generować komunikaty wyjściowe lub zdarzenia.

Funkcje wykonawcze dziedziczą z klasy bazowej Executor<TInput, TOutput> . Każdy funkcja wykonawcza ma unikatowy identyfikator i może obsługiwać określone typy komunikatów.

Podstawowa struktura funkcji wykonawczej

using Microsoft.Agents.AI.Workflows;
using Microsoft.Agents.AI.Workflows.Reflection;

internal sealed class UppercaseExecutor() : Executor<string, string>("UppercaseExecutor")
{
    public async ValueTask<string> HandleAsync(string message, IWorkflowContext context)
    {
        string result = message.ToUpperInvariant();
        return result; // Return value is automatically sent to connected executors
    }
}

Istnieje możliwość ręcznego wysyłania komunikatów bez zwracania wartości:

internal sealed class UppercaseExecutor() : Executor<string>("UppercaseExecutor")
{
    public async ValueTask HandleAsync(string message, IWorkflowContext context)
    {
        string result = message.ToUpperInvariant();
        await context.SendMessageAsync(result); // Manually send messages to connected executors
    }
}

Istnieje również możliwość obsługi wielu typów danych wejściowych przez zastąpienie ConfigureRoutes metody :

internal sealed class SampleExecutor() : Executor("SampleExecutor")
{
    protected override RouteBuilder ConfigureRoutes(RouteBuilder routeBuilder)
    {
        return routeBuilder
            .AddHandler<string>(this.HandleStringAsync)
            .AddHandler<int>(this.HandleIntAsync);
    }

    /// <summary>
    /// Converts input string to uppercase
    /// </summary>
    public async ValueTask<string> HandleStringAsync(string message, IWorkflowContext context)
    {
        string result = message.ToUpperInvariant();
        return result;
    }

    /// <summary>
    /// Doubles the input integer
    /// </summary>
    public async ValueTask<int> HandleIntAsync(int message, IWorkflowContext context)
    {
        int result = message * 2;
        return result;
    }
}

Istnieje również możliwość utworzenia funkcji wykonawczej na podstawie funkcji przy użyciu BindExecutor metody rozszerzenia:

Func<string, string> uppercaseFunc = s => s.ToUpperInvariant();
var uppercase = uppercaseFunc.BindExecutor("UppercaseExecutor");

Funkcje wykonawcze dziedziczą z klasy bazowej Executor . Każdy wykonawca ma unikatowy identyfikator i może obsługiwać określone typy komunikatów przy użyciu metod ozdobionych dekoratorem @handler . Programy obsługi muszą mieć odpowiednią adnotację, aby określić typ komunikatów, które mogą przetwarzać.

Podstawowa struktura funkcji wykonawczej

from agent_framework import (
    Executor,
    WorkflowContext,
    handler,
)

class UpperCase(Executor):

    @handler
    async def to_upper_case(self, text: str, ctx: WorkflowContext[str]) -> None:
        """Convert the input to uppercase and forward it to the next node.

        Note: The WorkflowContext is parameterized with the type this handler will
        emit. Here WorkflowContext[str] means downstream nodes should expect str.
        """
        await ctx.send_message(text.upper())

Można utworzyć wykonawcę z funkcji za pomocą dekoratora @executor.

from agent_framework import (
    WorkflowContext,
    executor,
)

@executor(id="upper_case_executor")
async def upper_case(text: str, ctx: WorkflowContext[str]) -> None:
    """Convert the input to uppercase and forward it to the next node.

    Note: The WorkflowContext is parameterized with the type this handler will
    emit. Here WorkflowContext[str] means downstream nodes should expect str.
    """
    await ctx.send_message(text.upper())

Istnieje również możliwość obsługi wielu typów danych wejściowych przez zdefiniowanie wielu programów obsługi:

class SampleExecutor(Executor):

    @handler
    async def to_upper_case(self, text: str, ctx: WorkflowContext[str]) -> None:
        """Convert the input to uppercase and forward it to the next node.

        Note: The WorkflowContext is parameterized with the type this handler will
        emit. Here WorkflowContext[str] means downstream nodes should expect str.
        """
        await ctx.send_message(text.upper())

    @handler
    async def double_integer(self, number: int, ctx: WorkflowContext[int]) -> None:
        """Double the input integer and forward it to the next node.

        Note: The WorkflowContext is parameterized with the type this handler will
        emit. Here WorkflowContext[int] means downstream nodes should expect int.
        """
        await ctx.send_message(number * 2)

WorkflowContext obiekt

Obiekt WorkflowContext udostępnia metody umożliwiające handlerowi interakcję z przepływem pracy podczas wykonywania. Parametr WorkflowContext jest sparametryzowany z typem komunikatów, które program obsługi będzie emitować i typ danych wyjściowych, które może uzyskać.

Najczęściej używaną metodą jest send_message, która umożliwia programowi obsługi wysyłanie komunikatów do połączonych funkcji wykonawczych.

from agent_framework import WorkflowContext

class SomeHandler(Executor):

    @handler
    async def some_handler(message: str, ctx: WorkflowContext[str]) -> None:
        await ctx.send_message("Hello, World!")

Procedura obsługi może użyć yield_output do generowania rezultatów, które będą traktowane jako outputy przepływu pracy i zostaną zwrócone lub przesyłane strumieniowo do obiektu wywołującego jako zdarzenie wyjściowe:

from agent_framework import WorkflowContext

class SomeHandler(Executor):

    @handler
    async def some_handler(message: str, ctx: WorkflowContext[Never, str]) -> None:
        await ctx.yield_output("Hello, World!")

Jeśli program obsługi ani nie wysyła komunikatów, ani nie zwraca danych wyjściowych, żaden parametr typu nie jest wymagany dla polecenia WorkflowContext:

from agent_framework import WorkflowContext

class SomeHandler(Executor):

    @handler
    async def some_handler(message: str, ctx: WorkflowContext) -> None:
        print("Doing some work...")

Następny krok