ai-agents-for-beginners

Hvordan designe gode AI-agenter

(Klikk på bildet ovenfor for å se videoen av denne leksjonen)

Verktøybruk Designmønster

Verktøy er interessante fordi de lar AI-agenter ha et bredere spekter av ferdigheter. I stedet for at agenten har et begrenset sett med handlinger den kan utføre, kan agenten nå utføre et bredt spekter av handlinger ved å legge til et verktøy. I dette kapitlet skal vi se på Verktøybruk Designmønster, som beskriver hvordan AI-agenter kan bruke spesifikke verktøy for å oppnå sine mål.

Introduksjon

I denne leksjonen ønsker vi å besvare følgende spørsmål:

Læringsmål

Etter å ha fullført denne leksjonen vil du kunne:

Hva er Verktøybruk Designmønster?

Verktøybruk Designmønster fokuserer på å gi LLM-er muligheten til å samhandle med eksterne verktøy for å oppnå spesifikke mål. Verktøy er kode som kan kjøres av en agent for å utføre handlinger. Et verktøy kan være en enkel funksjon som en kalkulator, eller et API-kall til en tredjepartstjeneste som aksjekursoppslag eller værmelding. I sammenheng med AI-agenter er verktøy designet for å bli utført av agenter som svar på modell-genererte funksjonskall.

Hvilke bruksområder kan det anvendes på?

AI-agenter kan utnytte verktøy for å fullføre komplekse oppgaver, hente informasjon eller ta beslutninger. Verktøybruk designmønster brukes ofte i scenarier som krever dynamisk interaksjon med eksterne systemer, som databaser, webtjenester eller kodefortolkere. Denne evnen er nyttig for flere ulike bruksområder, inkludert:

Hvilke elementer/byggeklosser trengs for å implementere verktøybruk designmønster?

Disse byggeklossene gjør det mulig for AI-agenten å utføre et bredt spekter av oppgaver. La oss se på de viktige elementene som trengs for å implementere Verktøybruk Designmønster:

Neste skal vi se nærmere på Funksjons-/Verktøypåcalling.

Funksjons-/Verktøypåcalling

Funksjonspåcalling er hovedmåten vi gjør det mulig for store språkmodeller (LLM) å samhandle med verktøy. Du vil ofte se «Funksjon» og «Verktøy» brukt om hverandre fordi «funksjoner» (blokker av gjenbrukbar kode) er de «verktøyene» agentene bruker for å utføre oppgaver. For at koden i en funksjon skal kunne påkalles, må en LLM sammenligne brukerens forespørsel med funksjonens beskrivelse. For å gjøre dette sendes et skjema som inneholder beskrivelsene av alle tilgjengelige funksjoner til LLM. LLM velger så den mest passende funksjonen for oppgaven og returnerer funksjonsnavnet og argumentene. Den valgte funksjonen påkalles, svaret sendes tilbake til LLM, som bruker informasjonen for å svare på brukerens forespørsel.

For utviklere som skal implementere funksjonspåcalling for agenter trenger du:

  1. En LLM-modell som støtter funksjonspåcalling
  2. Et skjema som inneholder funksjonsbeskrivelser
  3. Koden for hver funksjon som er beskrevet

La oss bruke eksempelet med å hente nåværende tid i en by for å illustrere:

  1. Initialiser en LLM som støtter funksjonspåcalling:

    Ikke alle modeller støtter funksjonspåcalling, så det er viktig å sjekke at LLM-en du bruker gjør det. Azure OpenAI støtter funksjonspåcalling. Vi kan starte med å initiere Azure OpenAI-klienten.

     # Initialiser Azure OpenAI-klienten
     client = AzureOpenAI(
         azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT"), 
         api_key=os.getenv("AZURE_OPENAI_API_KEY"),  
         api_version="2024-05-01-preview"
     )
    
  2. Opprett et funksjonsskjema:

    Deretter definerer vi et JSON-skjema som inneholder funksjonsnavn, beskrivelse av hva funksjonen gjør, og navn og beskrivelser av funksjonsparametrene. Vi tar så dette skjemaet og sender det til klienten vi opprettet tidligere, sammen med brukerens forespørsel om å finne tiden i San Francisco. Det viktige å merke seg er at et verktøypårop returneres, ikke det endelige svaret på spørsmålet. Som nevnt tidligere, returnerer LLM navnet på funksjonen den valgte for oppgaven, og argumentene som skal sendes til den.

     # Funksjonsbeskrivelse for modellen å lese
     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"],
                 },
             }
         }
     ]
    
      
     # Første brukerbeskjed
     messages = [{"role": "user", "content": "What's the current time in San Francisco"}] 
      
     # Første API-kall: Be modellen bruke funksjonen
       response = client.chat.completions.create(
           model=deployment_name,
           messages=messages,
           tools=tools,
           tool_choice="auto",
       )
      
       # Behandle modellens svar
       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')])
    
  3. Funksjonskoden som kreves for å utføre oppgaven:

    Nå som LLM har valgt hvilken funksjon som må kjøres, må koden som utfører oppgaven implementeres og kjøres. Vi kan implementere koden for å hente nåværende tid i Python. Vi må også skrive kode for å hente ut navnet og argumentene fra response_message for å få det endelige resultatet.

       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"})
    
      # Håndter funksjonskall
       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.")  
      
       # Andre API-kall: Hent den endelige responsen fra modellen
       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.
    

Funksjonspåcalling er kjernen i de fleste, om ikke alle, agenters verktøybruk design, men å implementere det fra bunnen av kan noen ganger være utfordrende. Som vi lærte i Leksjon 2 gir agentiske rammeverk oss ferdigbygde byggeklosser for å implementere verktøybruk.

Verktøybruk Eksempler med Agentiske Rammeverk

Her er noen eksempler på hvordan du kan implementere Verktøybruk Designmønster ved hjelp av ulike agentiske rammeverk:

Semantic Kernel

Semantic Kernel er et åpen-kildekode AI-rammeverk for .NET, Python og Java-utviklere som jobber med store språkmodeller (LLM). Det forenkler prosessen med å bruke funksjonspåcalling ved automatisk å beskrive funksjonene dine og parametrene deres for modellen gjennom en prosess kalt serialisering. Det håndterer også kommunikasjonen frem og tilbake mellom modellen og koden din. En annen fordel med å bruke et agentisk rammeverk som Semantic Kernel, er at det gir tilgang til ferdigbygde verktøy som Fil-søk og Kodefortolker.

Følgende diagram illustrerer prosessen med funksjonspåcalling med Semantic Kernel:

function calling

I Semantic Kernel kalles funksjoner/verktøy Plug-ins. Vi kan konvertere get_current_time-funksjonen vi så tidligere til en plug-in ved å gjøre den om til en klasse med funksjonen i seg. Vi kan også importere kernel_function-dekoratøren, som tar inn beskrivelsen av funksjonen. Når du oppretter en kernel med GetCurrentTimePlugin, vil kjernen automatisk serialisere funksjonen og parameterne, og lage skjemaet som sendes til LLM i prosessen.

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

# Opprett kjernen
kernel = Kernel()

# Opprett pluginen
get_current_time_plugin = GetCurrentTimePlugin(location)

# Legg pluginen til kjernen
kernel.add_plugin(get_current_time_plugin)

Azure AI Agent Service

Azure AI Agent Service er et nyere agentisk rammeverk designet for å gjøre det mulig for utviklere å sikkert bygge, distribuere og skalere høykvalitets og utvidbare AI-agenter uten å måtte håndtere underliggende databehandling og lagringsressurser. Det er særlig nyttig for bedriftsapplikasjoner siden det er en fullt administrert tjeneste med sikkerhet på bedriftsnivå.

Sammenlignet med å utvikle direkte med LLM-API, gir Azure AI Agent Service noen fordeler, inkludert:

Verktøyene som er tilgjengelige i Azure AI Agent Service kan deles inn i to kategorier:

  1. Kunnskapsverktøy:
  2. Handlingsverktøy:

Agenttjenesten gjør det mulig å bruke disse verktøyene sammen som et toolset. Den benytter også threads som holder orden på meldingshistorikk fra en spesifikk samtale.

Forestill deg at du er salgskonsulent i et selskap som heter Contoso. Du ønsker å utvikle en samtaleagent som kan svare på spørsmål om salgsdataene dine.

Følgende bilde illustrerer hvordan du kan bruke Azure AI Agent Service til å analysere salgsdataene dine:

Agentic Service In Action

For å bruke noen av disse verktøyene med tjenesten kan vi opprette en klient og definere et verktøy eller verktøysett. For å implementere dette praktisk kan vi bruke følgende Python-kode. LLM vil kunne se på verktøysettet og avgjøre om den skal bruke den brukerlagde funksjonen fetch_sales_data_using_sqlite_query eller den forhåndsbygde kodefortolkeren avhengig av brukerens forespørsel.

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-funksjon som finnes i en fetch_sales_data_functions.py-fil.
from azure.ai.projects.models import ToolSet, FunctionTool, CodeInterpreterTool

project_client = AIProjectClient.from_connection_string(
    credential=DefaultAzureCredential(),
    conn_str=os.environ["PROJECT_CONNECTION_STRING"],
)

# Initialiser verktøysett
toolset = ToolSet()

# Initialiser funksjonskallagent med fetch_sales_data_using_sqlite_query-funksjonen og legg den til i verktøysettet
fetch_data_function = FunctionTool(fetch_sales_data_using_sqlite_query)
toolset.add(fetch_data_function)

# Initialiser Code Interpreter-verktøyet og legg det til i verktøysettet.
code_interpreter = code_interpreter = CodeInterpreterTool()
toolset.add(code_interpreter)

agent = project_client.agents.create_agent(
    model="gpt-4o-mini", name="my-agent", instructions="You are helpful agent", 
    toolset=toolset
)

Hvilke spesielle hensyn må tas for å bruke Verktøybruk Designmønster for å bygge tillitsverdige AI-agenter?

En vanlig bekymring med SQL som genereres dynamisk av LLM-er er sikkerhet, spesielt risikoen for SQL-injeksjon eller ondsinnede handlinger, som å slette eller tukle med databasen. Selv om disse bekymringene er gyldige, kan de effektivt dempes ved riktig konfigurasjon av database-tilgangstillatelser. For de fleste databaser innebærer dette å konfigurere databasen som skrivebeskyttet. For databaser som PostgreSQL eller Azure SQL bør appen tildeles en lese- (SELECT) rolle. Å kjøre appen i et sikkert miljø øker beskyttelsen ytterligere. I bedrifts-scenarier blir data typisk hentet ut og transformert fra operative systemer til en skrivebeskyttet database eller datalager med et brukervennlig skjema. Denne tilnærmingen sikrer at dataene er sikre, optimalisert for ytelse og tilgjengelighet, og at appen har begrenset, skrivebeskyttet tilgang.

Sample Codes

Got More Questions about the Tool Use Design Patterns?

Join the Azure AI Foundry Discord to meet with other learners, attend office hours and get your AI Agents questions answered.

Additional Resources

Previous Lesson

Understanding Agentic Design Patterns

Next Lesson

Agentic RAG


Ansvarsfraskrivelse: Dette dokumentet er oversatt ved bruk av AI-oversettelsestjenesten Co-op Translator. Selv om vi tilstreber nøyaktighet, vennligst vær oppmerksom på at automatiske oversettelser kan inneholde feil eller unøyaktigheter. Det opprinnelige dokumentet på sitt opprinnelige språk bør betraktes som den autoritative kilden. For kritisk informasjon anbefales profesjonell menneskelig oversettelse. Vi er ikke ansvarlige for misforståelser eller feiltolkninger som følge av bruk av denne oversettelsen.