次の方法で共有


人間の介入を含む承認プロセスで関数ツールを使用する

このチュートリアルの手順では、エージェントに対する人間の承認を必要とする関数ツールを使用する方法について説明します。エージェントは Azure OpenAI チャット補完サービス上に構築されています。

エージェントがユーザー入力を必要とする場合 (関数呼び出しの承認など)、これは人間のループ内パターンと呼ばれます。 ユーザー入力を必要とするエージェントの実行は、最終的な回答ではなく、ユーザーから必要な入力を示す応答で完了します。 エージェントの呼び出し元は、ユーザーから必要な入力を取得し、新しいエージェントの実行の一環としてエージェントに渡す役割を担います。

[前提条件]

前提条件と NuGet パッケージのインストールについては、このチュートリアルの 「エージェントの作成と実行 」の手順を参照してください。

関数ツールを使用してエージェントを作成する

関数を使用する場合は、実行前に人間の承認が必要かどうかを関数ごとに指定できます。 これを行うには、 AIFunction インスタンスを ApprovalRequiredAIFunction インスタンスにラップします。

特定の場所の天気を偽装する単純な関数ツールの例を次に示します。

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.";

AIFunctionを作成し、それをApprovalRequiredAIFunctionでラップするには、次の操作を行います。

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

エージェントを作成するときに、 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]);

承認が必要な関数が作成されたので、エージェントは、関数を直接実行して結果を返すのではなく、承認の要求で応答する可能性があります。 FunctionApprovalRequestContent インスタンスの応答コンテンツを確認できます。これは、エージェントが関数のユーザー承認を必要としていることを示します。

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

関数の承認要求がある場合、名前と引数を含む関数呼び出しの詳細は、FunctionCall インスタンスの FunctionApprovalRequestContent プロパティにあります。 これをユーザーに表示して、関数呼び出しを承認するか拒否するかを決定できます。 この例では、1 つの要求があるとします。

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

ユーザーが入力を入力したら、FunctionApprovalResponseContentCreateResponse メソッドを使用してFunctionApprovalRequestContent インスタンスを作成できます。 関数呼び出しを承認する true を渡すか、拒否する false します。

その後、応答コンテンツを新しい UserChatMessageでエージェントに渡し、同じスレッド オブジェクトと共にエージェントから結果を取得できます。

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

ループ承認で人間と共に関数ツールを使用する場合は常に、すべての関数呼び出しが承認または拒否されるまで、各エージェントの実行後に、応答内の FunctionApprovalRequestContent インスタンスを確認することを忘れないでください。

このチュートリアルの手順では、エージェントに対する人間の承認を必要とする関数ツールを使用する方法について説明します。

エージェントがユーザー入力を必要とする場合 (関数呼び出しの承認など)、これは人間のループ内パターンと呼ばれます。 ユーザー入力を必要とするエージェントの実行は、最終的な回答ではなく、ユーザーから必要な入力を示す応答で完了します。 エージェントの呼び出し元は、ユーザーから必要な入力を取得し、新しいエージェントの実行の一環としてエージェントに渡す役割を担います。

[前提条件]

前提条件と Python パッケージのインストールについては、このチュートリアルの 「エージェントの作成と実行 」の手順を参照してください。

承認が必要な関数ツールを使用してエージェントを作成する

関数を使用する場合は、実行前に人間の承認が必要かどうかを関数ごとに指定できます。 これを行うには、approval_mode デコレーターを使用するときに、"always_require" パラメーターを@ai_functionに設定します。

特定の場所の天気を偽装する単純な関数ツールの例を次に示します。

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."

承認を必要とする関数を作成するには、 approval_mode パラメーターを使用します。

@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%."

エージェントを作成するときに、 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

承認が必要な関数が作成されたので、エージェントは、関数を直接実行して結果を返すのではなく、承認の要求で応答する可能性があります。 ユーザー入力要求の応答を確認できます。これは、エージェントが関数のユーザー承認を必要としていることを示します。

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

関数の承認要求がある場合、名前と引数を含む関数呼び出しの詳細は、ユーザー入力要求の function_call プロパティにあります。 これをユーザーに表示して、関数呼び出しを承認するか拒否するかを決定できます。

ユーザーが入力を入力したら、ユーザー入力要求で create_response メソッドを使用して応答を作成できます。 関数呼び出しを承認する True を渡すか、拒否する False します。

その後、応答を新しい ChatMessageでエージェントに渡して、エージェントから結果を取得できます。

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)

ループでの承認の処理

承認を必要とする複数の関数呼び出しを操作する場合は、すべての関数が承認または拒否されるまで、ループ内で承認を処理することが必要になる場合があります。

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)

ループ承認で人間と共に関数ツールを使用する場合は、すべての関数呼び出しが承認または拒否されるまで、各エージェントの実行後に、応答でユーザー入力要求を確認することを忘れないでください。

次のステップ