Delen via


Functiehulpprogramma's gebruiken met een agent

In deze zelfstudie leert u hoe u functiehulpprogramma's gebruikt met een agent, waarbij de agent is gebouwd op de Azure OpenAI Chat Completion-service.

Belangrijk

Niet alle agenttypen ondersteunen functiehulpprogramma's. Sommige bieden mogelijk alleen ondersteuning voor aangepaste ingebouwde hulpprogramma's, zonder dat de beller zijn eigen functies kan bieden. In deze stap wordt een ChatClientAgent gebruikt, dat wel functiehulpprogramma's ondersteunt.

Vereiste voorwaarden

Zie de stap Een eenvoudige agent maken en uitvoeren in deze zelfstudie voor vereisten en het installeren van NuGet-pakketten.

De agent maken met functiehulpprogramma's

Functiehulpprogramma's zijn alleen aangepaste code die u wilt dat de agent kan aanroepen wanneer dat nodig is. U kunt elke C#-methode omzetten in een functiehulpprogramma door de AIFunctionFactory.Create methode te gebruiken om een AIFunction exemplaar van de methode te maken.

Als u aanvullende beschrijvingen wilt opgeven over de functie of de bijbehorende parameters voor de agent, zodat deze nauwkeuriger kan kiezen tussen verschillende functies, kunt u het System.ComponentModel.DescriptionAttribute kenmerk voor de methode en de bijbehorende parameters gebruiken.

Hier volgt een voorbeeld van een eenvoudig hulpmiddel voor functies dat doet alsof het het weer voor een bepaalde locatie ophaalt. Het is ingericht met beschrijvingskenmerken om aanvullende beschrijvingen over zichzelf en de locatieparameter aan de agent te bieden.

using System.ComponentModel;

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

Wanneer u de agent maakt, kunt u nu het functiehulpprogramma aan de agent doorgeven door een lijst met hulpprogramma's door te geven aan de AsAIAgent methode.

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

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

Waarschuwing

DefaultAzureCredential is handig voor ontwikkeling, maar vereist zorgvuldige overwegingen in de productieomgeving. Overweeg in productie een specifieke referentie te gebruiken (bijvoorbeeld ManagedIdentityCredential) om latentieproblemen, onbedoelde referentieprobing en potentiële beveiligingsrisico's van terugvalmechanismen te voorkomen.

Nu kunt u de agent gewoon als normaal uitvoeren en kan de agent het GetWeather functiehulpprogramma aanroepen wanneer dat nodig is.

Console.WriteLine(await agent.RunAsync("What is the weather like in Amsterdam?"));

Aanbeveling

Zie de .NET-voorbeelden voor volledige runnable voorbeelden.

Belangrijk

Niet alle agenttypen ondersteunen functiehulpprogramma's. Sommige bieden mogelijk alleen ondersteuning voor aangepaste ingebouwde hulpprogramma's, zonder dat de beller zijn eigen functies kan bieden. In deze stap worden agents gebruikt die zijn gemaakt via chatclients, die wel functiehulpprogramma's ondersteunen.

Vereiste voorwaarden

Zie de stap Een eenvoudige agent maken en uitvoeren in deze zelfstudie voor vereisten en het installeren van Python-pakketten.

De agent maken met functiehulpprogramma's

Functiehulpprogramma's zijn alleen aangepaste code die u wilt dat de agent kan aanroepen wanneer dat nodig is. U kunt elke Python-functie omzetten in een functie-instrument door deze door te geven aan de tools parameter van de agent bij het creëren van de agent.

Als u aanvullende beschrijvingen wilt opgeven over de functie of de bijbehorende parameters voor de agent, zodat deze nauwkeuriger kan kiezen tussen verschillende functies, kunt u de typeaantekeningen van Python gebruiken met Annotated en Pydantic's Field om beschrijvingen te bieden.

Hier volgt een voorbeeld van een eenvoudig hulpmiddel voor functies dat doet alsof het het weer voor een bepaalde locatie ophaalt. Er worden typeaantekeningen gebruikt om aanvullende beschrijvingen te geven over de functie en de locatieparameter voor de agent.

from typing import Annotated
from pydantic import Field

def get_weather(
    location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
    """Get the weather for a given location."""
    return f"The weather in {location} is cloudy with a high of 15°C."

U kunt de @tool decorator ook gebruiken om expliciet de naam en beschrijving van de functie op te geven:

from typing import Annotated
from pydantic import Field
from agent_framework import tool

@tool(name="weather_tool", description="Retrieves weather information for any location")
def get_weather(
    location: Annotated[str, Field(description="The location to get the weather for.")],
) -> str:
    return f"The weather in {location} is cloudy with a high of 15°C."

Indien u de name en description parameters niet specificeert in de @tool-decorator, gebruikt het framework automatisch de naam en de docstring van de functie als terugvalopties.

Expliciete schema's gebruiken met @tool

Wanneer u volledige controle nodig hebt over het schema dat beschikbaar is voor het model, geeft u de schema parameter door aan @tool. U kunt een Pydantic-model of een onbewerkte JSON-schemawoordenlijst opgeven.

# Load environment variables from .env file
load_dotenv()


# Approach 1: Pydantic model as explicit schema
class WeatherInput(BaseModel):
    """Input schema for the weather tool."""

    location: Annotated[str, Field(description="The city name to get weather for")]
    unit: Annotated[str, Field(description="Temperature unit: celsius or fahrenheit")] = "celsius"


@tool(
    name="get_weather",
    description="Get the current weather for a given location.",
    schema=WeatherInput,
    approval_mode="never_require",
    """Get the current weather for a location."""
    return f"The weather in {location} is 22 degrees {unit}."


# Approach 2: JSON schema dictionary as explicit schema
get_current_time_schema = {
    "type": "object",
    "properties": {
        "timezone": {"type": "string", "description": "The timezone to get the current time for", "default": "UTC"},
    },
}


@tool(
    name="get_current_time",
    description="Get the current time in a given timezone.",

Alleen runtime-context doorgeven aan een hulpprogramma

Gebruik normale functieparameters voor waarden die het model moet leveren. Gebruiken FunctionInvocationContext voor alleen runtime-waarden, zoals function_invocation_kwargs of de huidige sessie. De geïnjecteerde contextparameter is verborgen in het schema dat beschikbaar is voor het model.

import asyncio
from typing import Annotated

from agent_framework import Agent, FunctionInvocationContext, tool
from agent_framework.openai import OpenAIResponsesClient
from dotenv import load_dotenv
from pydantic import Field
# Define the function tool with explicit invocation context.
# The context parameter can also be declared as an untyped ``ctx`` parameter.
@tool(approval_mode="never_require")
def get_weather(
    location: Annotated[str, Field(description="The location to get the weather for.")],
    ctx: FunctionInvocationContext,
) -> str:
    """Get the weather for a given location."""
    # Extract the injected argument from the explicit context
    user_id = ctx.kwargs.get("user_id", "unknown")

    # Simulate using the user_id for logging or personalization
    print(f"Getting weather for user: {user_id}")

    return f"The weather in {location} is cloudy with a high of 15°C."


async def main() -> None:
    agent = Agent(
        client=OpenAIResponsesClient(),
        name="WeatherAgent",
        instructions="You are a helpful weather assistant.",
        tools=[get_weather],
    )

    # Pass the runtime context explicitly when running the agent.
    response = await agent.run(
        "What is the weather like in Amsterdam?",
        function_invocation_kwargs={"user_id": "user_123"},

Zie Runtime Context voor meer informatie over ctx.kwargs, ctx.session, en functionmiddleware.

Hulpprogramma's voor alleen declaratie maken

Als een hulpprogramma buiten het framework wordt geïmplementeerd (bijvoorbeeld clientzijde in een gebruikersinterface), kunt u dit declareren zonder een implementatie.FunctionTool(..., func=None) Het model kan nog steeds reden hebben om het hulpprogramma aan te roepen en uw toepassing kan het resultaat later opgeven.


# Load environment variables from .env file
load_dotenv()

# A declaration-only tool: the schema is sent to the LLM, but the framework
# has no implementation to execute. The caller must supply the result.
get_user_location = FunctionTool(
    name="get_user_location",
    func=None,
    description="Get the user's current city. Only the client application can resolve this.",
    input_model={
        "type": "object",
        "properties": {
            "reason": {"type": "string", "description": "Why the location is needed"},

Wanneer u de agent maakt, kunt u nu het functiehulpprogramma aan de agent opgeven door deze door te geven aan de tools parameter.

import asyncio
import os
from agent_framework.openai import OpenAIChatCompletionClient
from azure.identity import AzureCliCredential

agent = OpenAIChatCompletionClient(
    model=os.environ["AZURE_OPENAI_DEPLOYMENT_NAME"],
    azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT"],
    api_version=os.getenv("AZURE_OPENAI_API_VERSION"),
    credential=AzureCliCredential(),
).as_agent(
    instructions="You are a helpful assistant",
    tools=get_weather
)

Nu kunt u de agent gewoon als normaal uitvoeren en kan de agent het get_weather functiehulpprogramma aanroepen wanneer dat nodig is.

async def main():
    result = await agent.run("What is the weather like in Amsterdam?")
    print(result.text)

asyncio.run(main())

Een klasse maken met meerdere functiehulpprogramma's

Wanneer verschillende hulpprogramma's afhankelijkheden of de onveranderbare status delen, verpakt u deze in een klasse en geeft u afhankelijke methoden door aan de agent. Gebruik klassekenmerken voor waarden die het model niet mag bieden, zoals serviceclients, functievlagmen of status in de cache.

import asyncio
from typing import Annotated

from agent_framework import Agent, tool
from agent_framework.openai import OpenAIResponsesClient
from dotenv import load_dotenv
class MyFunctionClass:
    def __init__(self, safe: bool = False) -> None:
        """Simple class with two tools: divide and add.

        The safe parameter controls whether divide raises on division by zero or returns `infinity` for divide by zero.
        """
        self.safe = safe

    def divide(
        self,
        a: Annotated[int, "Numerator"],
        b: Annotated[int, "Denominator"],
    ) -> str:
        """Divide two numbers, safe to use also with 0 as denominator."""
        result = "∞" if b == 0 and self.safe else a / b
        return f"{a} / {b} = {result}"

    def add(
        self,
        x: Annotated[int, "First number"],
        y: Annotated[int, "Second number"],
    ) -> str:
        return f"{x} + {y} = {x + y}"


async def main():
    # Creating my function class with safe division enabled
    tools = MyFunctionClass(safe=True)
    # Applying the tool decorator to one of the methods of the class
    add_function = tool(description="Add two numbers.")(tools.add)

    agent = Agent(
        client=OpenAIResponsesClient(),
        name="ToolAgent",
        instructions="Use the provided tools.",
    )
    print("=" * 60)
    print("Step 1: Call divide(10, 0) - tool returns infinity")
    query = "Divide 10 by 0"
    response = await agent.run(
        query,
        tools=[add_function, tools.divide],
    )
    print(f"Response: {response.text}")
    print("=" * 60)
    print("Step 2: Call set safe to False and call again")
    # Disabling safe mode to allow exceptions
    tools.safe = False

Dit patroon is geschikt voor een langdurige toestand van een hulpmiddel. Gebruik FunctionInvocationContext in plaats daarvan wanneer de waarde per aanroep verandert.

Volgende stappen