(Clicca sull’immagine sopra per visualizzare il video di questa lezione)
Gli strumenti sono interessanti perché consentono agli agenti AI di avere una gamma più ampia di capacità. Invece di avere un set limitato di azioni che l’agente può eseguire, aggiungendo uno strumento, l’agente può ora eseguire una vasta gamma di azioni. In questo capitolo, esamineremo il modello di progettazione per l’uso degli strumenti, che descrive come gli agenti AI possono utilizzare strumenti specifici per raggiungere i loro obiettivi.
In questa lezione, cercheremo di rispondere alle seguenti domande:
Dopo aver completato questa lezione, sarai in grado di:
Il modello di progettazione per l’uso degli strumenti si concentra sul dare ai LLM la capacità di interagire con strumenti esterni per raggiungere obiettivi specifici. Gli strumenti sono codice che può essere eseguito da un agente per svolgere azioni. Uno strumento può essere una funzione semplice, come una calcolatrice, o una chiamata API a un servizio di terze parti, come la ricerca dei prezzi delle azioni o le previsioni meteo. Nel contesto degli agenti AI, gli strumenti sono progettati per essere eseguiti dagli agenti in risposta a chiamate di funzione generate dal modello.
Gli agenti AI possono sfruttare gli strumenti per completare compiti complessi, recuperare informazioni o prendere decisioni. Il modello di progettazione per l’uso degli strumenti è spesso utilizzato in scenari che richiedono interazioni dinamiche con sistemi esterni, come database, servizi web o interpreti di codice. Questa capacità è utile per una serie di casi d’uso, tra cui:
Questi blocchi costitutivi consentono all’agente AI di svolgere una vasta gamma di compiti. Esaminiamo gli elementi chiave necessari per implementare il modello di progettazione per l’uso degli strumenti:
Schemi di funzione/strumento: Definizioni dettagliate degli strumenti disponibili, inclusi nome della funzione, scopo, parametri richiesti e output attesi. Questi schemi permettono al LLM di comprendere quali strumenti sono disponibili e come costruire richieste valide.
Logica di esecuzione delle funzioni: Regola come e quando gli strumenti vengono invocati in base all’intento dell’utente e al contesto della conversazione. Questo può includere moduli di pianificazione, meccanismi di instradamento o flussi condizionali che determinano l’uso degli strumenti in modo dinamico.
Sistema di gestione dei messaggi: Componenti che gestiscono il flusso conversazionale tra input dell’utente, risposte del LLM, chiamate agli strumenti e output degli strumenti.
Framework di integrazione degli strumenti: Infrastruttura che collega l’agente a vari strumenti, siano essi funzioni semplici o servizi esterni complessi.
Gestione degli errori e validazione: Meccanismi per gestire i fallimenti nell’esecuzione degli strumenti, validare i parametri e gestire risposte inattese.
Gestione dello stato: Tiene traccia del contesto della conversazione, delle interazioni precedenti con gli strumenti e dei dati persistenti per garantire coerenza nelle interazioni multi-turno.
Passiamo ora a esaminare in dettaglio la chiamata di funzione/strumento.
La chiamata di funzione è il modo principale per consentire ai modelli di linguaggio di grandi dimensioni (LLM) di interagire con gli strumenti. Spesso vedrai i termini “Funzione” e “Strumento” usati in modo intercambiabile, poiché le “funzioni” (blocchi di codice riutilizzabile) sono gli “strumenti” che gli agenti utilizzano per svolgere compiti. Affinché il codice di una funzione venga invocato, un LLM deve confrontare la richiesta dell’utente con la descrizione della funzione. Per fare ciò, uno schema contenente le descrizioni di tutte le funzioni disponibili viene inviato al LLM. Il LLM seleziona quindi la funzione più appropriata per il compito e restituisce il suo nome e i suoi argomenti. La funzione selezionata viene invocata, la sua risposta viene inviata al LLM, che utilizza le informazioni per rispondere alla richiesta dell’utente.
Per implementare la chiamata di funzione per gli agenti, i sviluppatori avranno bisogno di:
Usiamo l’esempio di ottenere l’ora corrente in una città per illustrare:
Inizializzare un LLM che supporta la chiamata di funzione:
Non tutti i modelli supportano la chiamata di funzione, quindi è importante verificare che il LLM utilizzato lo faccia. Azure OpenAI supporta la chiamata di funzione. Possiamo iniziare avviando il client Azure OpenAI.
# 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"
)
Creare uno schema di funzione:
Successivamente, definiremo uno schema JSON che contiene il nome della funzione, la descrizione di ciò che la funzione fa e i nomi e le descrizioni dei parametri della funzione. Passeremo quindi questo schema al client creato in precedenza, insieme alla richiesta dell’utente di trovare l’ora a San Francisco. È importante notare che ciò che viene restituito è una chiamata allo strumento, non la risposta finale alla domanda. Come accennato in precedenza, il LLM restituisce il nome della funzione che ha selezionato per il compito e gli argomenti che verranno passati ad essa.
# 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')])
Il codice della funzione necessario per svolgere il compito:
Ora che il LLM ha scelto quale funzione deve essere eseguita, il codice che svolge il compito deve essere implementato ed eseguito. Possiamo implementare il codice per ottenere l’ora corrente in Python. Dovremo anche scrivere il codice per estrarre il nome e gli argomenti dal response_message per ottenere il risultato finale.
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.
La chiamata di funzione è al centro della maggior parte, se non di tutti, i progetti di utilizzo degli strumenti da parte degli agenti, tuttavia implementarla da zero può talvolta essere impegnativo. Come abbiamo appreso nella Lezione 2, i framework agentici ci forniscono blocchi pre-costruiti per implementare l’uso degli strumenti.
Ecco alcuni esempi di come puoi implementare il modello di progettazione per l’uso degli strumenti utilizzando diversi framework agentici:
Semantic Kernel è un framework AI open-source per sviluppatori .NET, Python e Java che lavorano con modelli di linguaggio di grandi dimensioni (LLM). Semplifica il processo di utilizzo della chiamata di funzione descrivendo automaticamente le tue funzioni e i loro parametri al modello attraverso un processo chiamato serializzazione. Gestisce anche la comunicazione tra il modello e il tuo codice. Un altro vantaggio dell’utilizzo di un framework agentico come Semantic Kernel è che ti consente di accedere a strumenti pre-costruiti come File Search e Code Interpreter.
Il seguente diagramma illustra il processo di chiamata di funzione con Semantic Kernel:
In Semantic Kernel le funzioni/strumenti sono chiamati Plugin. Possiamo convertire la funzione get_current_time
che abbiamo visto in precedenza in un plugin trasformandola in una classe con la funzione al suo interno. Possiamo anche importare il decoratore kernel_function
, che accetta la descrizione della funzione. Quando crei un kernel con il GetCurrentTimePlugin, il kernel serializzerà automaticamente la funzione e i suoi parametri, creando lo schema da inviare al LLM nel processo.
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 è un framework agentico più recente progettato per consentire agli sviluppatori di costruire, distribuire e scalare agenti AI di alta qualità ed estensibili in modo sicuro, senza dover gestire le risorse di calcolo e archiviazione sottostanti. È particolarmente utile per applicazioni aziendali poiché è un servizio completamente gestito con sicurezza di livello enterprise.
Rispetto allo sviluppo diretto con l’API LLM, Azure AI Agent Service offre alcuni vantaggi, tra cui:
Gli strumenti disponibili in Azure AI Agent Service possono essere suddivisi in due categorie:
Il servizio Agent consente di utilizzare questi strumenti insieme come un toolset
. Utilizza anche i thread
, che tengono traccia della cronologia dei messaggi di una particolare conversazione.
Immagina di essere un agente di vendita in un’azienda chiamata Contoso. Vuoi sviluppare un agente conversazionale che possa rispondere a domande sui tuoi dati di vendita.
La seguente immagine illustra come potresti utilizzare Azure AI Agent Service per analizzare i tuoi dati di vendita:
Per utilizzare uno di questi strumenti con il servizio, possiamo creare un client e definire uno strumento o un insieme di strumenti. Per implementarlo praticamente, possiamo utilizzare il seguente codice Python. Il LLM sarà in grado di esaminare il toolset e decidere se utilizzare la funzione creata dall’utente, fetch_sales_data_using_sqlite_query
, o il Code Interpreter predefinito a seconda della richiesta dell’utente.
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
)
Una preoccupazione comune con SQL generato dinamicamente dai LLM è la sicurezza, in particolare il rischio di SQL injection o azioni dannose, come l’eliminazione o la manomissione del database. Sebbene queste preoccupazioni siano valide, possono essere efficacemente mitigate configurando correttamente i permessi di accesso al database. Per la maggior parte dei database, ciò comporta la configurazione del database come di sola lettura. Per servizi di database come PostgreSQL o Azure SQL, all’app dovrebbe essere assegnato un ruolo di sola lettura (SELECT).
Eseguire l’app in un ambiente sicuro migliora ulteriormente la protezione. In scenari aziendali, i dati vengono tipicamente estratti e trasformati da sistemi operativi in un database di sola lettura o data warehouse con uno schema user-friendly. Questo approccio garantisce che i dati siano sicuri, ottimizzati per prestazioni e accessibilità, e che l’app abbia accesso limitato e di sola lettura.
Unisciti al Discord di Azure AI Foundry per incontrare altri studenti, partecipare agli orari di ricevimento e ottenere risposte alle tue domande sugli AI Agents.
Comprendere i modelli di design agentico
Disclaimer:
Questo documento è stato tradotto utilizzando il servizio di traduzione automatica Co-op Translator. Sebbene ci impegniamo per garantire l’accuratezza, si prega di notare che le traduzioni automatiche possono contenere errori o imprecisioni. Il documento originale nella sua lingua nativa dovrebbe essere considerato la fonte autorevole. Per informazioni critiche, si raccomanda una traduzione professionale eseguita da un traduttore umano. Non siamo responsabili per eventuali fraintendimenti o interpretazioni errate derivanti dall’uso di questa traduzione.