Delen via


Basisconcepten van Microsoft Agent Framework-werkstromen - Uitvoerders

Dit document biedt een uitgebreid overzicht van het onderdeel Executors van het Microsoft Agent Framework Workflow-systeem.

Overzicht

Uitvoerders zijn de fundamentele bouwstenen waarmee berichten in een werkstroom worden verwerkt. Het zijn autonome verwerkingseenheden die getypte berichten ontvangen, bewerkingen uitvoeren en uitvoerberichten of gebeurtenissen kunnen produceren.

Uitvoerders nemen over van de Executor<TInput, TOutput> basisklasse. Elke uitvoerder heeft een unieke id en kan specifieke berichttypen verwerken.

Basisuitvoeringsstructuur

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
    }
}

Het is mogelijk om berichten handmatig te verzenden zonder een waarde te retourneren:

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
    }
}

Het is ook mogelijk om meerdere invoertypen te verwerken door de ConfigureRoutes methode te overschrijven:

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;
    }
}

Het is ook mogelijk om een uitvoerder van een functie te maken met behulp van de BindExecutor extensiemethode:

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

Uitvoerders nemen over van de Executor basisklasse. Elke uitvoerder heeft een unieke id en kan specifieke berichttypen verwerken met behulp van methoden die zijn ingericht met de @handler decorator. Handlers moeten over de juiste aantekening beschikken om het type berichten op te geven dat ze kunnen verwerken.

Basisuitvoeringsstructuur

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())

Het is mogelijk om een uitvoerder van een functie te maken met behulp van de @executor decorator:

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())

Het is ook mogelijk om meerdere invoertypen te verwerken door meerdere handlers te definiƫren:

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)

Het WorkflowContext object

Het WorkflowContext object biedt methoden voor de handler om tijdens de uitvoering met de werkstroom te communiceren. De WorkflowContext parameter wordt geparameteriseerd met het type berichten dat de handler verzendt en het type uitvoer dat het kan opleveren.

De meest gebruikte methode is send_message, waarmee de handler berichten naar verbonden uitvoerders kan verzenden.

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!")

Een handler kan gebruiken yield_output om uitvoer te produceren die als werkstroomuitvoer wordt beschouwd en als uitvoergebeurtenis naar de aanroeper wordt geretourneerd/gestreamd:

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!")

Als een handler geen berichten verzendt of uitvoer oplevert, is er geen typeparameter nodig voor WorkflowContext:

from agent_framework import WorkflowContext

class SomeHandler(Executor):

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

Volgende stap