Compartir a través de


Temas Avanzados de Orquestación del Agente del Kernel Semántico

Importante

Las características de orquestación del agente en Agent Framework se encuentran en la fase experimental. Están en desarrollo activo y pueden cambiar significativamente antes de avanzar a la fase de versión preliminar o candidata para lanzamiento.

Tiempo de ejecución

El entorno de ejecución es el componente fundamental que administra el ciclo de vida, la comunicación y la ejecución de agentes y orquestaciones. Actúa como bus de mensajes y entorno de ejecución para todos los actores del sistema (agentes y actores específicos para la orquestación).

Rol del tiempo de ejecución

  • Enrutamiento de mensajes: El entorno de ejecución es responsable de la entrega de mensajes entre agentes y actores de orquestación, utilizando un modelo de mensajería directa o de publicación-suscripción, según el patrón de orquestación.
  • Administración del ciclo de vida del actor: Crea, registra y administra el ciclo de vida de todos los actores implicados en una orquestación, lo que garantiza el aislamiento y la administración adecuada de los recursos.
  • Contexto de ejecución: El tiempo de ejecución proporciona el contexto de ejecución para las orquestaciones, lo que permite que varias orquestaciones (y sus invocaciones) se ejecuten de forma independiente y simultánea.

Relación entre tiempo de ejecución y orquestaciones

Piense en una orquestación como un gráfico que define cómo interactúan los agentes entre sí. El tiempo de ejecución es el motor que ejecuta este grafo, administrando el flujo de mensajes y el ciclo de vida de los agentes. Los desarrolladores pueden ejecutar este grafo varias veces con entradas diferentes en la misma instancia en tiempo de ejecución y el tiempo de ejecución garantizará que cada ejecución esté aislada e independiente.

Tiempos de expiración

Cuando se invoca una orquestación, esta devuelve inmediatamente un controlador que se puede usar para obtener el resultado más adelante. Este patrón asincrónico permite un diseño más flexible y dinámico, especialmente en escenarios en los que la orquestación puede tardar mucho tiempo en completarse.

Importante

Si se produce un tiempo de espera, no se cancelará la invocación de la orquestación. La orquestación continuará ejecutándose en segundo plano hasta que finalice. Los desarrolladores todavía pueden recuperar el resultado más adelante.

Los desarrolladores pueden obtener el resultado de una invocación de orquestación más adelante llamando al GetValueAsync método en el objeto de resultado. Cuando la aplicación está lista para procesar el resultado, es posible que la invocación se haya completado o no. Por lo tanto, los desarrolladores pueden especificar opcionalmente un tiempo de espera para el GetValueAsync método . Si la orquestación no se completa dentro del tiempo de espera especificado, se producirá una excepción de tiempo de espera.

string output = await result.GetValueAsync(TimeSpan.FromSeconds(60));

Si la orquestación no se completa dentro del tiempo de espera especificado, se producirá una excepción de tiempo de espera.

Los desarrolladores pueden obtener el resultado de una invocación de orquestación más adelante llamando al get método en el objeto de resultado. Cuando la aplicación está lista para procesar el resultado, es posible que la invocación se haya completado o no. Por lo tanto, los desarrolladores pueden especificar opcionalmente un tiempo de espera para el get método . Si la orquestación no se completa dentro del tiempo de espera especificado, se producirá una excepción de tiempo de espera.

value = await orchestration_result.get(timeout=60)

Si la orquestación no se completa dentro del tiempo de espera especificado, se generará una excepción de tiempo de espera.

Nota:

La orquestación del agente aún no está disponible en el SDK de Java.

Participación humana en el bucle

Respuesta de devolución de llamada del agente

Para ver las respuestas del agente dentro de una invocación, los desarrolladores pueden proporcionar un ResponseCallback a la orquestación. Esto permite a los desarrolladores observar las respuestas de cada agente durante el proceso de orquestación. Los desarrolladores pueden usar esta devolución de llamada para las actualizaciones de la interfaz de usuario, el registro de actividad u otros fines.

public ValueTask ResponseCallback(ChatMessageContent response)
{
    Console.WriteLine($"# {response.AuthorName}\n{response.Content}");
    return ValueTask.CompletedTask;
}

SequentialOrchestration orchestration = new SequentialOrchestration(
    analystAgent, writerAgent, editorAgent)
{
    ResponseCallback = ResponseCallback,
};

Para ver las respuestas del agente dentro de una invocación, los desarrolladores pueden proporcionar un agent_response_callback a la orquestación. Esto permite a los desarrolladores observar las respuestas de cada agente durante el proceso de orquestación. Los desarrolladores pueden usar esta devolución de llamada para las actualizaciones de la interfaz de usuario, el registro de actividad u otros fines.

def agent_response_callback(message: ChatMessageContent) -> None:
    print(f"# {message.name}\n{message.content}")

sequential_orchestration = SequentialOrchestration(
    members=agents,
    agent_response_callback=agent_response_callback,
)

Nota:

La orquestación del agente aún no está disponible en el SDK de Java.

Función de respuesta humana

En el caso de las orquestaciones que admiten la interacción del usuario (por ejemplo, transferencia y chat de grupo), proporcione un InteractiveCallback que devuelva un ChatMessageContent proporcionado por el usuario. Al utilizar esta devolución de llamada, los desarrolladores pueden implementar lógica personalizada para recopilar datos del usuario, como mostrar un aviso en la interfaz de usuario o integrarse con otros sistemas.

HandoffOrchestration orchestration = new(...)
{
    InteractiveCallback = () =>
    {
        Console.Write("User: ");
        string input = Console.ReadLine();
        return new ChatMessageContent(AuthorRole.User, input);
    }
};

En el caso de las orquestaciones que admiten la interacción del usuario (por ejemplo, transferencia y chat de grupo), proporcione un human_response_function que devuelva un ChatMessageContent proporcionado por el usuario. Al utilizar esta devolución de llamada, los desarrolladores pueden implementar lógica personalizada para recopilar datos del usuario, como mostrar un aviso en la interfaz de usuario o integrarse con otros sistemas.

def human_response_function() -> ChatMessageContent:
    user_input = input("User: ")
    return ChatMessageContent(role=AuthorRole.USER, content=user_input)

handoff_orchestration = HandoffOrchestration(
    ...,
    agent_response_callback=agent_response_callback,
)

Nota:

La orquestación del agente aún no está disponible en el SDK de Java.

Datos estructurados

Creemos que los datos estructurados son una parte clave de la creación de flujos de trabajo agente. Mediante el uso de datos estructurados, los desarrolladores pueden crear orquestaciones más reutilizables y se mejora la experiencia de desarrollo. El SDK de kernel semántico proporciona una manera de pasar datos estructurados como entrada a orquestaciones y devolver datos estructurados como salida.

Importante

Internamente, las orquestaciones siguen procesando los datos como ChatMessageContent.

Entradas estructuradas

Los desarrolladores pueden pasar datos estructurados como entrada a orquestaciones mediante una clase de entrada fuertemente tipada y especificarlos como parámetro genérico para la orquestación. Esto permite la seguridad de tipos y más flexibilidad para que las orquestaciones gestionen estructuras de datos complejas. Por ejemplo, para evaluar los problemas de GitHub, defina una clase para la entrada estructurada:

public sealed class GithubIssue
{
    public string Id { get; set; } = string.Empty;
    public string Title { get; set; } = string.Empty;
    public string Body { get; set; } = string.Empty;
    public string[] Labels { get; set; } = [];
}

A continuación, los desarrolladores pueden usar este tipo como entrada para una orquestación al proporcionarlo como parámetro genérico:

HandoffOrchestration<GithubIssue, string> orchestration =
    new(...);

GithubIssue input = new GithubIssue { ... };
var result = await orchestration.InvokeAsync(input, runtime);

Transformaciones de entrada personalizadas

De forma predeterminada, la orquestación usará la transformación de entrada integrada, que serializa el objeto en JSON y lo envuelve en un ChatMessageContent. Si desea personalizar cómo se convierte la entrada estructurada en el tipo de mensaje subyacente, puede proporcionar su propia función de transformación de entrada a través de la InputTransform propiedad :

HandoffOrchestration<GithubIssue, string> orchestration =
    new(...)
    {
        InputTransform = (issue, cancellationToken) =>
        {
            // For example, create a chat message with a custom format
            var message = new ChatMessageContent(AuthorRole.User, $"[{issue.Id}] {issue.Title}\n{issue.Body}");
            return ValueTask.FromResult<IEnumerable<ChatMessageContent>>([message]);
        },
    };

Esto le permite controlar exactamente cómo se presenta la entrada tipada a los agentes, lo que permite escenarios avanzados, como formato personalizado, selección de campos o entrada de varios mensajes.

Sugerencia

Consulte el ejemplo completo en Step04a_HandoffWithStructuredInput.cs

Los desarrolladores pueden pasar datos estructurados como entrada a orquestaciones especificando un modelo Pydantic (o cualquier clase personalizada) como parámetro genérico para la orquestación. Esto permite la seguridad de tipos y permite que las orquestaciones controle estructuras de datos complejas.

Por ejemplo, para evaluar los problemas de GitHub, defina un modelo Pydantic para la entrada estructurada:

from pydantic import BaseModel

class GithubIssue(BaseModel):
    id: str
    title: str
    body: str
    labels: list[str] = []

A continuación, puede usar este tipo como entrada para la orquestación si lo proporciona como parámetro genérico:

from semantic_kernel.agents import HandoffOrchestration

def custom_input_transform(input_message: GithubIssue) -> ChatMessageContent:
    return ChatMessageContent(role=AuthorRole.USER, content=f"[{input_message.id}] {input_message.title}\n{input_message.body}")


handoff_orchestration = HandoffOrchestration[GithubIssue, ChatMessageContent](
    ...,
    input_transform=custom_input_transform,
)

GithubIssueSample = GithubIssue(
    id="12345",
    title="Bug: ...",
    body="Describe the bug...",
    labels=[],
)

orchestration_result = await handoff_orchestration.invoke(
    task=GithubIssueSample,
    runtime=runtime,
)

Sugerencia

Consulte el ejemplo completo en step4a_handoff_structured_inputs.py

Nota:

La orquestación del agente aún no está disponible en el SDK de Java.

Salidas estructuradas

Los agentes y las orquestaciones pueden devolver salidas estructuradas especificando una clase de salida fuertemente tipificada como un parámetro genérico de la orquestación. Esto le permite trabajar con resultados enriquecidos y estructurados en la aplicación, en lugar de simplemente texto sin formato.

Por ejemplo, supongamos que desea analizar un artículo y extraer temas, opiniones y entidades. Defina una clase para la salida estructurada:

public sealed class Analysis
{
    public IList<string> Themes { get; set; } = [];
    public IList<string> Sentiments { get; set; } = [];
    public IList<string> Entities { get; set; } = [];
}

A continuación, puede usar este tipo como salida para la orquestación si lo proporciona como parámetro genérico:

ConcurrentOrchestration<string, Analysis> orchestration =
    new(agent1, agent2, agent3)
    {
        ResultTransform = outputTransform.TransformAsync, // see below
    };

// ...
OrchestrationResult<Analysis> result = await orchestration.InvokeAsync(input, runtime);
Analysis output = await result.GetValueAsync(TimeSpan.FromSeconds(60));

Transformaciones de salida personalizadas

De forma predeterminada, la orquestación usará la transformación de salida integrada, que intenta deserializar el contenido de respuesta del agente en el tipo de salida. Para escenarios más avanzados, puede proporcionar una transformación de salida personalizada (por ejemplo, con la salida estructurada por algunos modelos).

StructuredOutputTransform<Analysis> outputTransform =
    new(chatCompletionService, new OpenAIPromptExecutionSettings { ResponseFormat = typeof(Analysis) });

ConcurrentOrchestration<string, Analysis> orchestration =
    new(agent1, agent2, agent3)
    {
        ResultTransform = outputTransform.TransformAsync,
    };

Este enfoque permite recibir y procesar datos estructurados directamente desde la orquestación, lo que facilita la creación de flujos de trabajo e integraciones avanzados.

Sugerencia

Consulte el ejemplo completo en Step01a_ConcurrentWithStructuredOutput.cs

Los agentes y orquestaciones pueden devolver salidas estructuradas especificando un modelo Pydantic (o cualquier clase personalizada) como tipo de salida genérico para la orquestación. Esto le permite trabajar con resultados enriquecidos y estructurados en la aplicación, en lugar de simplemente texto sin formato.

Por ejemplo, supongamos que desea analizar un artículo y extraer temas, opiniones y entidades. Defina un modelo Pydantic para la salida estructurada:

from pydantic import BaseModel

class ArticleAnalysis(BaseModel):
    themes: list[str]
    sentiments: list[str]
    entities: list[str]

A continuación, puede usar este tipo como salida para la orquestación si lo proporciona como parámetro genérico y especifica una transformación de salida:

from semantic_kernel.agents import ConcurrentOrchestration
from semantic_kernel.agents.orchestration.tools import structured_outputs_transform
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion

# `structured_outputs_transform` is a built-in transform that uses the structured output

concurrent_orchestration = ConcurrentOrchestration[str, ArticleAnalysis](
    members=agents,
    output_transform=structured_outputs_transform(ArticleAnalysis, AzureChatCompletion()),
)

...

orchestration_result = await concurrent_orchestration.invoke(
    task="article text",
    runtime=runtime,
)

value = await orchestration_result.get(timeout=20)

# `value` is now an instance of ArticleAnalysis

Este enfoque permite recibir y procesar datos estructurados directamente desde la orquestación, lo que facilita la creación de flujos de trabajo e integraciones avanzados.

Sugerencia

Consulte el ejemplo completo en step1a_concurrent_structured_outputs.py

Nota:

La orquestación del agente aún no está disponible en el SDK de Java.

Cancelación

Importante

La cancelación impedirá que los agentes procesen más mensajes, pero no detendrán los agentes que ya están procesando mensajes.

Importante

La cancelación no detendrá el tiempo de ejecución.

Puede cancelar una orquestación llamando al Cancel método en el controlador de resultados. Esto detendrá la orquestación propagando la señal a todos los agentes y dejará de procesar los mensajes adicionales.

var resultTask = orchestration.InvokeAsync(input, runtime);
resultTask.Cancel();

Los desarrolladores pueden cancelar una orquestación llamando al cancel método en el controlador de resultados. Esto detendrá la orquestación propagando la señal a todos los agentes y dejará de procesar los mensajes adicionales.

orchestration_result = await orchestration.invoke(task=task, runtime=runtime)
orchestration_result.cancel()

Nota:

La orquestación del agente aún no está disponible en el SDK de Java.

Pasos siguientes

Nota:

La orquestación del agente aún no está disponible en el SDK de Java.