(Klik op de afbeelding hierboven om de video van deze les te bekijken)
Tools zijn interessant omdat ze AI-agenten in staat stellen een breder scala aan mogelijkheden te hebben. In plaats van dat de agent een beperkte set acties kan uitvoeren, kan de agent met een tool nu een breed scala aan acties uitvoeren. In dit hoofdstuk bekijken we het Tool Use Design Pattern, dat beschrijft hoe AI-agenten specifieke tools kunnen gebruiken om hun doelen te bereiken.
In deze les proberen we de volgende vragen te beantwoorden:
Na het voltooien van deze les kun je:
Het Tool Use Design Pattern richt zich op het geven van LLMs de mogelijkheid om te communiceren met externe tools om specifieke doelen te bereiken. Tools zijn code die door een agent kan worden uitgevoerd om acties uit te voeren. Een tool kan een eenvoudige functie zijn, zoals een rekenmachine, of een API-aanroep naar een externe service, zoals het opzoeken van aandelenkoersen of weersvoorspellingen. In de context van AI-agenten zijn tools ontworpen om door agenten te worden uitgevoerd als reactie op modelgegenereerde functieaanroepen.
AI-agenten kunnen tools gebruiken om complexe taken uit te voeren, informatie op te halen of beslissingen te nemen. Het Tool Use Design Pattern wordt vaak gebruikt in scenario’s die dynamische interactie met externe systemen vereisen, zoals databases, webservices of code-interpreters. Deze mogelijkheid is nuttig voor verschillende toepassingen, waaronder:
Deze bouwstenen stellen de AI-agent in staat een breed scala aan taken uit te voeren. Laten we de belangrijkste elementen bekijken die nodig zijn om het Tool Use Design Pattern te implementeren:
Functie-/Toolschema’s: Gedetailleerde definities van beschikbare tools, inclusief functienaam, doel, vereiste parameters en verwachte outputs. Deze schema’s stellen de LLM in staat te begrijpen welke tools beschikbaar zijn en hoe geldige verzoeken te construeren.
Functie-uitvoeringslogica: Regelt hoe en wanneer tools worden aangeroepen op basis van de intentie van de gebruiker en de context van het gesprek. Dit kan plannermodules, routeringsmechanismen of conditionele stromen omvatten die dynamisch het gebruik van tools bepalen.
Berichtenafhandelingssysteem: Componenten die de conversatiestroom beheren tussen gebruikersinvoer, LLM-reacties, toolaanroepen en tooloutputs.
Toolintegratiekader: Infrastructuur die de agent verbindt met verschillende tools, of het nu eenvoudige functies of complexe externe services zijn.
Foutafhandeling en validatie: Mechanismen om fouten in tooluitvoering af te handelen, parameters te valideren en onverwachte reacties te beheren.
Staatbeheer: Houdt de context van het gesprek, eerdere toolinteracties en persistente gegevens bij om consistentie te waarborgen bij interacties met meerdere beurten.
Laten we nu Function/Tool Calling in meer detail bekijken.
Functieaanroepen zijn de primaire manier waarop we Large Language Models (LLMs) in staat stellen om met tools te communiceren. Je zult vaak ‘Function’ en ‘Tool’ door elkaar zien gebruikt, omdat ‘functies’ (blokken herbruikbare code) de ‘tools’ zijn die agenten gebruiken om taken uit te voeren. Om de code van een functie aan te roepen, moet een LLM het verzoek van de gebruiker vergelijken met de beschrijving van de functie. Hiervoor wordt een schema met de beschrijvingen van alle beschikbare functies naar de LLM gestuurd. De LLM selecteert vervolgens de meest geschikte functie voor de taak en retourneert de naam en argumenten. De geselecteerde functie wordt aangeroepen, de reactie wordt teruggestuurd naar de LLM, die de informatie gebruikt om te reageren op het verzoek van de gebruiker.
Om functieaanroepen voor agenten te implementeren, heb je nodig:
Laten we het voorbeeld gebruiken van het verkrijgen van de huidige tijd in een stad om dit te illustreren:
Initialiseer een LLM die functieaanroepen ondersteunt:
Niet alle modellen ondersteunen functieaanroepen, dus het is belangrijk om te controleren of het LLM dat je gebruikt dit doet. Azure OpenAI ondersteunt functieaanroepen. We kunnen beginnen met het initiëren van de Azure OpenAI-client.
# Initialize the Azure OpenAI client
client = AzureOpenAI(
azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT"),
api_key=os.getenv("AZURE_OPENAI_API_KEY"),
api_version="2024-05-01-preview"
)
Maak een Functieschema:
Vervolgens definiëren we een JSON-schema dat de functienaam, beschrijving van wat de functie doet, en de namen en beschrijvingen van de functieparameters bevat. We nemen dit schema en geven het door aan de eerder gemaakte client, samen met het verzoek van de gebruiker om de tijd in San Francisco te vinden. Wat belangrijk is om op te merken, is dat een toolaanroep wordt geretourneerd, niet het definitieve antwoord op de vraag. Zoals eerder vermeld, retourneert de LLM de naam van de functie die is geselecteerd voor de taak en de argumenten die eraan worden doorgegeven.
# Function description for the model to read
tools = [
{
"type": "function",
"function": {
"name": "get_current_time",
"description": "Get the current time in a given location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city name, e.g. San Francisco",
},
},
"required": ["location"],
},
}
}
]
# Initial user message
messages = [{"role": "user", "content": "What's the current time in San Francisco"}]
# First API call: Ask the model to use the function
response = client.chat.completions.create(
model=deployment_name,
messages=messages,
tools=tools,
tool_choice="auto",
)
# Process the model's response
response_message = response.choices[0].message
messages.append(response_message)
print("Model's response:")
print(response_message)
Model's response:
ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_pOsKdUlqvdyttYB67MOj434b', function=Function(arguments='{"location":"San Francisco"}', name='get_current_time'), type='function')])
De functiecode die nodig is om de taak uit te voeren:
Nu de LLM heeft gekozen welke functie moet worden uitgevoerd, moet de code die de taak uitvoert worden geïmplementeerd en uitgevoerd. We kunnen de code implementeren om de huidige tijd in Python te verkrijgen. We moeten ook de code schrijven om de naam en argumenten uit het response_message te halen om het definitieve resultaat te krijgen.
def get_current_time(location):
"""Get the current time for a given location"""
print(f"get_current_time called with location: {location}")
location_lower = location.lower()
for key, timezone in TIMEZONE_DATA.items():
if key in location_lower:
print(f"Timezone found for {key}")
current_time = datetime.now(ZoneInfo(timezone)).strftime("%I:%M %p")
return json.dumps({
"location": location,
"current_time": current_time
})
print(f"No timezone data found for {location_lower}")
return json.dumps({"location": location, "current_time": "unknown"})
# Handle function calls
if response_message.tool_calls:
for tool_call in response_message.tool_calls:
if tool_call.function.name == "get_current_time":
function_args = json.loads(tool_call.function.arguments)
time_response = get_current_time(
location=function_args.get("location")
)
messages.append({
"tool_call_id": tool_call.id,
"role": "tool",
"name": "get_current_time",
"content": time_response,
})
else:
print("No tool calls were made by the model.")
# Second API call: Get the final response from the model
final_response = client.chat.completions.create(
model=deployment_name,
messages=messages,
)
return final_response.choices[0].message.content
get_current_time called with location: San Francisco
Timezone found for san francisco
The current time in San Francisco is 09:24 AM.
Functieaanroepen vormen de kern van de meeste, zo niet alle ontwerpen voor toolgebruik door agenten, maar het implementeren ervan vanaf nul kan soms uitdagend zijn. Zoals we hebben geleerd in Les 2 bieden agentic frameworks ons vooraf gebouwde bouwstenen om toolgebruik te implementeren.
Hier zijn enkele voorbeelden van hoe je het Tool Use Design Pattern kunt implementeren met verschillende agentic frameworks:
Semantic Kernel is een open-source AI-framework voor .NET-, Python- en Java-ontwikkelaars die werken met Large Language Models (LLMs). Het vereenvoudigt het proces van functieaanroepen door automatisch je functies en hun parameters te beschrijven aan het model via een proces genaamd serializing. Het beheert ook de communicatie tussen het model en je code. Een ander voordeel van het gebruik van een agentic framework zoals Semantic Kernel is dat het je toegang geeft tot vooraf gebouwde tools zoals File Search en Code Interpreter.
Het volgende diagram illustreert het proces van functieaanroepen met Semantic Kernel:
In Semantic Kernel worden functies/tools Plugins genoemd. We kunnen de get_current_time
-functie die we eerder zagen omzetten in een plugin door deze om te zetten in een klasse met de functie erin. We kunnen ook de kernel_function
-decorator importeren, die de beschrijving van de functie accepteert. Wanneer je vervolgens een kernel maakt met de GetCurrentTimePlugin, serialiseert de kernel automatisch de functie en haar parameters, waardoor het schema wordt gemaakt dat naar de LLM wordt gestuurd.
from semantic_kernel.functions import kernel_function
class GetCurrentTimePlugin:
async def __init__(self, location):
self.location = location
@kernel_function(
description="Get the current time for a given location"
)
def get_current_time(location: str = ""):
...
from semantic_kernel import Kernel
# Create the kernel
kernel = Kernel()
# Create the plugin
get_current_time_plugin = GetCurrentTimePlugin(location)
# Add the plugin to the kernel
kernel.add_plugin(get_current_time_plugin)
Azure AI Agent Service is een nieuwer agentic framework dat is ontworpen om ontwikkelaars in staat te stellen veilig hoogwaardige en uitbreidbare AI-agenten te bouwen, implementeren en schalen zonder dat ze de onderliggende compute- en opslagbronnen hoeven te beheren. Het is vooral nuttig voor zakelijke toepassingen, omdat het een volledig beheerde service is met beveiliging van ondernemingsklasse.
In vergelijking met ontwikkelen met de LLM API rechtstreeks biedt Azure AI Agent Service enkele voordelen, waaronder:
De tools die beschikbaar zijn in Azure AI Agent Service kunnen worden onderverdeeld in twee categorieën:
De Agent Service stelt ons in staat om deze tools samen te gebruiken als een toolset
. Het maakt ook gebruik van threads
die de geschiedenis van berichten van een bepaalde conversatie bijhouden.
Stel je voor dat je een verkoopagent bent bij een bedrijf genaamd Contoso. Je wilt een conversatieagent ontwikkelen die vragen over je verkoopgegevens kan beantwoorden.
De volgende afbeelding illustreert hoe je Azure AI Agent Service kunt gebruiken om je verkoopgegevens te analyseren:
Om een van deze tools met de service te gebruiken, kunnen we een client maken en een tool of toolset definiëren. Om dit praktisch te implementeren, kunnen we de volgende Python-code gebruiken. De LLM kan naar de toolset kijken en beslissen of de door de gebruiker gemaakte functie, fetch_sales_data_using_sqlite_query
, of de vooraf gebouwde Code Interpreter wordt gebruikt, afhankelijk van het verzoek van de gebruiker.
import os
from azure.ai.projects import AIProjectClient
from azure.identity import DefaultAzureCredential
from fetch_sales_data_functions import fetch_sales_data_using_sqlite_query # fetch_sales_data_using_sqlite_query function which can be found in a fetch_sales_data_functions.py file.
from azure.ai.projects.models import ToolSet, FunctionTool, CodeInterpreterTool
project_client = AIProjectClient.from_connection_string(
credential=DefaultAzureCredential(),
conn_str=os.environ["PROJECT_CONNECTION_STRING"],
)
# Initialize function calling agent with the fetch_sales_data_using_sqlite_query function and adding it to the toolset
fetch_data_function = FunctionTool(fetch_sales_data_using_sqlite_query)
toolset = ToolSet()
toolset.add(fetch_data_function)
# Initialize Code Interpreter tool and adding it to the toolset.
code_interpreter = code_interpreter = CodeInterpreterTool()
toolset = ToolSet()
toolset.add(code_interpreter)
agent = project_client.agents.create_agent(
model="gpt-4o-mini", name="my-agent", instructions="You are helpful agent",
toolset=toolset
)
Een veelvoorkomende zorg bij SQL die dynamisch wordt gegenereerd door LLMs is beveiliging, met name het risico van SQL-injectie of kwaadaardige acties, zoals het verwijderen of manipuleren van de database. Hoewel deze zorgen geldig zijn, kunnen ze effectief worden gemitigeerd door de toegangsrechten van de database correct te configureren. Voor de meeste databases houdt dit in dat de database wordt geconfigureerd als alleen-lezen. Voor databaseservices zoals PostgreSQL of Azure SQL moet de app een alleen-lezen (SELECT) rol krijgen.
Het draaien van de app in een veilige omgeving biedt extra bescherming. In zakelijke scenario’s worden gegevens meestal geëxtraheerd en getransformeerd van operationele systemen naar een alleen-lezen database of datawarehouse met een gebruiksvriendelijke schema. Deze aanpak zorgt ervoor dat de gegevens veilig zijn, geoptimaliseerd voor prestaties en toegankelijkheid, en dat de app beperkte, alleen-lezen toegang heeft.
Word lid van de Azure AI Foundry Discord om andere leerlingen te ontmoeten, spreekuren bij te wonen en je vragen over AI Agents beantwoord te krijgen.
Begrip van Agentic Design Patterns
Disclaimer:
Dit document is vertaald met behulp van de AI-vertalingsservice Co-op Translator. Hoewel we streven naar nauwkeurigheid, dient u zich ervan bewust te zijn dat geautomatiseerde vertalingen fouten of onnauwkeurigheden kunnen bevatten. Het originele document in de oorspronkelijke taal moet worden beschouwd als de gezaghebbende bron. Voor cruciale informatie wordt professionele menselijke vertaling aanbevolen. Wij zijn niet aansprakelijk voor eventuele misverstanden of verkeerde interpretaties die voortvloeien uit het gebruik van deze vertaling.