Compartilhar via


Usando ferramentas funcionais com aprovações humanas no circuito

Esta etapa do tutorial mostra como usar ferramentas de funcionalidade que exigem aprovação humana com um agente, onde o agente é criado no Serviço de Conclusão de Bate-papo do Azure OpenAI.

Quando os agentes exigem qualquer entrada do usuário, por exemplo, para aprovar uma chamada de função, isso é conhecido como um padrão humano no loop. Uma execução de agente que requer entrada do usuário será concluída com uma resposta que indica qual entrada é necessária do usuário, em vez de concluir com uma resposta final. O chamador do agente é então responsável por obter a entrada necessária do usuário e passá-la de volta para o agente como parte de uma nova execução do agente.

Pré-requisitos

Para pré-requisitos e instalação de pacotes NuGet, consulte a etapa Criar e executar um agente simples neste tutorial.

Criar o agente com ferramentas funcionais

Ao usar funções, é possível indicar para cada função se ela requer aprovação humana antes de ser executada. Isso é feito encapsulando a AIFunction instância em uma ApprovalRequiredAIFunction instância.

Aqui está um exemplo de uma ferramenta de função simples que falsifica a obtenção do clima para um determinado local.

using System;
using System.ComponentModel;
using System.Linq;
using Azure.AI.OpenAI;
using Azure.Identity;
using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;
using OpenAI;

[Description("Get the weather for a given location.")]
static string GetWeather([Description("The location to get the weather for.")] string location)
    => $"The weather in {location} is cloudy with a high of 15°C.";

Para criar um AIFunction e, em seguida, embrulhá-lo em um ApprovalRequiredAIFunction, você pode fazer o seguinte:

AIFunction weatherFunction = AIFunctionFactory.Create(GetWeather);
AIFunction approvalRequiredWeatherFunction = new ApprovalRequiredAIFunction(weatherFunction);

Ao criar o agente, agora você pode fornecer ao agente a ferramenta de função que exige aprovação, passando uma lista de ferramentas para o método CreateAIAgent.

AIAgent agent = new AzureOpenAIClient(
    new Uri("https://<myresource>.openai.azure.com"),
    new AzureCliCredential())
     .GetChatClient("gpt-4o-mini")
     .CreateAIAgent(instructions: "You are a helpful assistant", tools: [approvalRequiredWeatherFunction]);

Como agora você tem uma função que requer aprovação, o agente pode responder com uma solicitação de aprovação, em vez de executar a função diretamente e retornar o resultado. Você pode verificar o conteúdo da resposta para qualquer FunctionApprovalRequestContent instância, o que indica que o agente requer aprovação do usuário para uma função.

AgentThread thread = agent.GetNewThread();
AgentRunResponse response = await agent.RunAsync("What is the weather like in Amsterdam?", thread);

var functionApprovalRequests = response.Messages
    .SelectMany(x => x.Contents)
    .OfType<FunctionApprovalRequestContent>()
    .ToList();

Se houver solicitações de aprovação de função, os detalhes da chamada de função, incluindo nome e argumentos, poderão ser encontrados na FunctionCall propriedade na FunctionApprovalRequestContent instância. Isso pode ser mostrado ao usuário, para que ele possa decidir se aprova ou rejeita a chamada de função. Para este exemplo, suponha que haja uma solicitação.

FunctionApprovalRequestContent requestContent = functionApprovalRequests.First();
Console.WriteLine($"We require approval to execute '{requestContent.FunctionCall.Name}'");

Depois que o usuário tiver fornecido sua entrada, você poderá criar uma FunctionApprovalResponseContent instância usando o CreateResponse método no FunctionApprovalRequestContent. Passe true para aprovar a chamada de função ou false rejeitá-la.

Em seguida, o conteúdo da resposta pode ser passado para o agente em um novo UserChatMessage, juntamente com o mesmo objeto de thread para obter o resultado de volta do agente.

var approvalMessage = new ChatMessage(ChatRole.User, [requestContent.CreateResponse(true)]);
Console.WriteLine(await agent.RunAsync(approvalMessage, thread));

Sempre que você estiver usando ferramentas de função com aprovações humanas no loop, lembre-se de verificar se há FunctionApprovalRequestContent instâncias na resposta, após cada execução do agente, até que todas as chamadas de função tenham sido aprovadas ou rejeitadas.

Esta etapa do tutorial mostra como usar ferramentas de função que exigem aprovação humana com um agente.

Quando os agentes exigem qualquer entrada do usuário, por exemplo, para aprovar uma chamada de função, isso é conhecido como um padrão humano no loop. Uma execução de agente que requer entrada do usuário será concluída com uma resposta que indica qual entrada é necessária do usuário, em vez de concluir com uma resposta final. O chamador do agente é então responsável por obter a entrada necessária do usuário e passá-la de volta para o agente como parte de uma nova execução do agente.

Pré-requisitos

Para pré-requisitos e instalação de pacotes do Python, consulte a etapa Criar e executar um agente simples neste tutorial.

Criar o agente com ferramentas funcionais que exigem aprovação

Ao usar funções, é possível indicar para cada função se ela requer aprovação humana antes de ser executada. Isso é feito definindo o parâmetro approval_mode para "always_require", ao usar o decorador @ai_function.

Aqui está um exemplo de uma ferramenta de função simples que falsifica a obtenção do clima para um determinado local.

from typing import Annotated
from agent_framework import ai_function

@ai_function
def get_weather(location: Annotated[str, "The city and state, e.g. San Francisco, CA"]) -> str:
    """Get the current weather for a given location."""
    return f"The weather in {location} is cloudy with a high of 15°C."

Para criar uma função que requer aprovação, você pode usar o approval_mode parâmetro:

@ai_function(approval_mode="always_require")
def get_weather_detail(location: Annotated[str, "The city and state, e.g. San Francisco, CA"]) -> str:
    """Get detailed weather information for a given location."""
    return f"The weather in {location} is cloudy with a high of 15°C, humidity 88%."

Ao criar o agente, agora você pode fornecer a ferramenta de função que requer aprovação para o agente, passando uma lista de ferramentas para o construtor ChatAgent.

from agent_framework import ChatAgent
from agent_framework.openai import OpenAIResponsesClient

async with ChatAgent(
    chat_client=OpenAIResponsesClient(),
    name="WeatherAgent",
    instructions="You are a helpful weather assistant.",
    tools=[get_weather, get_weather_detail],
) as agent:
    # Agent is ready to use

Como agora você tem uma função que requer aprovação, o agente pode responder com uma solicitação de aprovação, em vez de executar a função diretamente e retornar o resultado. Você pode verificar a resposta de solicitações de entrada do usuário, o que indica que o agente requer aprovação do usuário para uma função.

result = await agent.run("What is the detailed weather like in Amsterdam?")

if result.user_input_requests:
    for user_input_needed in result.user_input_requests:
        print(f"Function: {user_input_needed.function_call.name}")
        print(f"Arguments: {user_input_needed.function_call.arguments}")

Se houver solicitações de aprovação de função, os detalhes da chamada de função, incluindo nome e argumentos, poderão ser encontrados na function_call propriedade na solicitação de entrada do usuário. Isso pode ser mostrado ao usuário, para que ele possa decidir se aprova ou rejeita a chamada de função.

Depois que o usuário tiver fornecido sua entrada, você poderá criar uma resposta usando o create_response método na solicitação de entrada do usuário. Passe True para aprovar a chamada de função ou False rejeitá-la.

Em seguida, a resposta pode ser passada em um novo ChatMessage para o agente, a fim de obter o resultado de volta.

from agent_framework import ChatMessage, Role

# Get user approval (in a real application, this would be interactive)
user_approval = True  # or False to reject

# Create the approval response
approval_message = ChatMessage(
    role=Role.USER, 
    contents=[user_input_needed.create_response(user_approval)]
)

# Continue the conversation with the approval
final_result = await agent.run([
    "What is the detailed weather like in Amsterdam?",
    ChatMessage(role=Role.ASSISTANT, contents=[user_input_needed]),
    approval_message
])
print(final_result.text)

Manipulando aprovações em um loop

Ao trabalhar com várias chamadas de função que exigem aprovação, talvez seja necessário lidar com aprovações em um loop até que todas as funções sejam aprovadas ou rejeitadas:

async def handle_approvals(query: str, agent) -> str:
    """Handle function call approvals in a loop."""
    current_input = query

    while True:
        result = await agent.run(current_input)

        if not result.user_input_requests:
            # No more approvals needed, return the final result
            return result.text

        # Build new input with all context
        new_inputs = [query]

        for user_input_needed in result.user_input_requests:
            print(f"Approval needed for: {user_input_needed.function_call.name}")
            print(f"Arguments: {user_input_needed.function_call.arguments}")

            # Add the assistant message with the approval request
            new_inputs.append(ChatMessage(role=Role.ASSISTANT, contents=[user_input_needed]))

            # Get user approval (in practice, this would be interactive)
            user_approval = True  # Replace with actual user input

            # Add the user's approval response
            new_inputs.append(
                ChatMessage(role=Role.USER, contents=[user_input_needed.create_response(user_approval)])
            )

        # Continue with all the context
        current_input = new_inputs

# Usage
result_text = await handle_approvals("Get detailed weather for Seattle and Portland", agent)
print(result_text)

Sempre que você estiver usando ferramentas de função com aprovações humanas no loop, lembre-se de verificar se há solicitações de entrada do usuário na resposta, após cada execução do agente, até que todas as chamadas de função tenham sido aprovadas ou rejeitadas.

Próximas etapas