Ai învățat destul de multe până acum în lecțiile anterioare. Totuși, putem îmbunătăți și mai mult. Unele aspecte pe care le putem aborda sunt cum să obținem un format de răspuns mai consistent pentru a facilita utilizarea răspunsului în etapele ulterioare. De asemenea, s-ar putea să dorim să adăugăm date din alte surse pentru a îmbogăți aplicația noastră.
Problemele menționate mai sus sunt cele pe care acest capitol își propune să le abordeze.
Această lecție va acoperi:
- Explicarea conceptului de apelare a funcțiilor și a cazurilor sale de utilizare.
- Crearea unui apel de funcție folosind Azure OpenAI.
- Cum să integrezi un apel de funcție într-o aplicație.
Până la sfârșitul acestei lecții, vei putea:
- Explica scopul utilizării apelării funcțiilor.
- Configura Apelul Funcției folosind Serviciul Azure OpenAI.
- Proiecta apeluri de funcții eficiente pentru cazul de utilizare al aplicației tale.
Pentru această lecție, dorim să construim o funcționalitate pentru startup-ul nostru educațional care să permită utilizatorilor să folosească un chatbot pentru a găsi cursuri tehnice. Vom recomanda cursuri care se potrivesc nivelului lor de competență, rolului actual și tehnologiei de interes.
Pentru a finaliza acest scenariu, vom folosi o combinație de:
Azure OpenAIpentru a crea o experiență de chat pentru utilizator.Microsoft Learn Catalog APIpentru a ajuta utilizatorii să găsească cursuri pe baza cererii lor.Apelarea Funcțiilorpentru a prelua interogarea utilizatorului și a o trimite unei funcții pentru a face cererea API.
Pentru a începe, să vedem de ce am dori să folosim apelarea funcțiilor în primul rând:
Înainte de apelarea funcțiilor, răspunsurile de la un LLM erau nestructurate și inconsistente. Dezvoltatorii erau nevoiți să scrie coduri complexe de validare pentru a se asigura că pot gestiona fiecare variație a unui răspuns. Utilizatorii nu puteau obține răspunsuri precum "Care este vremea actuală în Stockholm?". Acest lucru se întâmpla deoarece modelele erau limitate la perioada în care datele au fost antrenate.
Apelarea funcțiilor este o caracteristică a Serviciului Azure OpenAI care depășește următoarele limitări:
- Format de răspuns consistent. Dacă putem controla mai bine formatul răspunsului, putem integra mai ușor răspunsul în alte sisteme.
- Date externe. Capacitatea de a utiliza date din alte surse ale unei aplicații într-un context de chat.
Vă recomandăm să folosiți notebook-ul inclus dacă doriți să rulați scenariul de mai jos. De asemenea, puteți doar să citiți mai departe, deoarece încercăm să ilustrăm o problemă unde funcțiile pot ajuta la rezolvarea acesteia.
Să analizăm exemplul care ilustrează problema formatului răspunsului:
Să presupunem că dorim să creăm o bază de date cu datele studenților pentru a le sugera cursurile potrivite. Mai jos avem două descrieri ale studenților care sunt foarte similare în datele pe care le conțin.
-
Crearea unei conexiuni la resursa noastră Azure OpenAI:
import os import json from openai import AzureOpenAI from dotenv import load_dotenv load_dotenv() client = AzureOpenAI( api_key=os.environ['AZURE_OPENAI_API_KEY'], # this is also the default, it can be omitted api_version = "2023-07-01-preview" ) deployment=os.environ['AZURE_OPENAI_DEPLOYMENT']
Mai jos este un cod Python pentru configurarea conexiunii noastre la Azure OpenAI unde setăm
api_type,api_base,api_versionșiapi_key. -
Crearea a două descrieri ale studenților folosind variabilele
student_1_descriptionșistudent_2_description.student_1_description="Emily Johnson is a sophomore majoring in computer science at Duke University. She has a 3.7 GPA. Emily is an active member of the university's Chess Club and Debate Team. She hopes to pursue a career in software engineering after graduating." student_2_description = "Michael Lee is a sophomore majoring in computer science at Stanford University. He has a 3.8 GPA. Michael is known for his programming skills and is an active member of the university's Robotics Club. He hopes to pursue a career in artificial intelligence after finishing his studies."
Dorim să trimitem descrierile studenților de mai sus către un LLM pentru a analiza datele. Aceste date pot fi utilizate ulterior în aplicația noastră și pot fi trimise către un API sau stocate într-o bază de date.
-
Să creăm două prompturi identice în care instruim LLM-ul despre informațiile care ne interesează:
prompt1 = f''' Please extract the following information from the given text and return it as a JSON object: name major school grades club This is the body of text to extract the information from: {student_1_description} ''' prompt2 = f''' Please extract the following information from the given text and return it as a JSON object: name major school grades club This is the body of text to extract the information from: {student_2_description} '''
Prompturile de mai sus instruiesc LLM-ul să extragă informații și să returneze răspunsul în format JSON.
-
După configurarea prompturilor și a conexiunii la Azure OpenAI, vom trimite acum prompturile către LLM folosind
openai.ChatCompletion. Stocăm promptul în variabilamessagesși atribuim roluluser. Acest lucru este pentru a imita un mesaj de la un utilizator scris unui chatbot.# response from prompt one openai_response1 = client.chat.completions.create( model=deployment, messages = [{'role': 'user', 'content': prompt1}] ) openai_response1.choices[0].message.content # response from prompt two openai_response2 = client.chat.completions.create( model=deployment, messages = [{'role': 'user', 'content': prompt2}] ) openai_response2.choices[0].message.content
Acum putem trimite ambele cereri către LLM și examina răspunsul pe care îl primim găsindu-l astfel: openai_response1['choices'][0]['message']['content'].
-
În cele din urmă, putem converti răspunsul în format JSON apelând
json.loads:# Loading the response as a JSON object json_response1 = json.loads(openai_response1.choices[0].message.content) json_response1
Răspuns 1:
{ "name": "Emily Johnson", "major": "computer science", "school": "Duke University", "grades": "3.7", "club": "Chess Club" }Răspuns 2:
{ "name": "Michael Lee", "major": "computer science", "school": "Stanford University", "grades": "3.8 GPA", "club": "Robotics Club" }Chiar dacă prompturile sunt aceleași și descrierile sunt similare, vedem valorile proprietății
Gradesformatate diferit, deoarece uneori putem obține formatul3.7sau3.7 GPA, de exemplu.Acest rezultat se datorează faptului că LLM-ul preia date nestructurate sub forma promptului scris și returnează, de asemenea, date nestructurate. Trebuie să avem un format structurat astfel încât să știm la ce să ne așteptăm atunci când stocăm sau utilizăm aceste date.
Deci, cum rezolvăm problema formatării? Prin utilizarea apelării funcțiilor, putem asigura că primim date structurate înapoi. Când folosim apelarea funcțiilor, LLM-ul nu apelează sau rulează de fapt nicio funcție. În schimb, creăm o structură pe care LLM-ul să o urmeze pentru răspunsurile sale. Apoi folosim aceste răspunsuri structurate pentru a ști ce funcție să rulăm în aplicațiile noastre.
Putem apoi să luăm ceea ce este returnat de funcție și să trimitem acest lucru înapoi către LLM. LLM-ul va răspunde apoi folosind limbaj natural pentru a răspunde la interogarea utilizatorului.
Există multe cazuri de utilizare diferite în care apelarea funcțiilor poate îmbunătăți aplicația ta, cum ar fi:
-
Apelarea instrumentelor externe. Chatbot-urile sunt excelente pentru a oferi răspunsuri la întrebările utilizatorilor. Prin utilizarea apelării funcțiilor, chatbot-urile pot folosi mesajele de la utilizatori pentru a îndeplini anumite sarcini. De exemplu, un student poate cere chatbot-ului să "Trimită un e-mail instructorului meu spunând că am nevoie de mai mult ajutor la acest subiect". Acest lucru poate face un apel de funcție la
send_email(to: string, body: string). -
Crearea de interogări API sau baze de date. Utilizatorii pot găsi informații folosind limbaj natural care este convertit într-o interogare formatată sau cerere API. Un exemplu ar putea fi un profesor care solicită "Cine sunt studenții care au finalizat ultima temă", ceea ce ar putea apela o funcție numită
get_completed(student_name: string, assignment: int, current_status: string). -
Crearea de date structurate. Utilizatorii pot lua un bloc de text sau CSV și pot folosi LLM-ul pentru a extrage informații importante din acesta. De exemplu, un student poate converti un articol Wikipedia despre acorduri de pace pentru a crea fișe de învățare AI. Acest lucru poate fi realizat prin utilizarea unei funcții numite
get_important_facts(agreement_name: string, date_signed: string, parties_involved: list).
Procesul de creare a unui apel de funcție include 3 pași principali:
- Apelarea API-ului Chat Completions cu o listă de funcții și un mesaj de la utilizator.
- Citirea răspunsului modelului pentru a efectua o acțiune, adică executarea unei funcții sau a unui apel API.
- Realizarea unui alt apel către API-ul Chat Completions cu răspunsul de la funcția ta pentru a folosi acea informație pentru a crea un răspuns pentru utilizator.
Primul pas este să creezi un mesaj de utilizator. Acesta poate fi atribuit dinamic prin preluarea valorii unui câmp de text sau poți atribui o valoare aici. Dacă este prima dată când lucrezi cu API-ul Chat Completions, trebuie să definești role și content al mesajului.
Rolul role poate fi fie system (crearea regulilor), assistant (modelul) sau user (utilizatorul final). Pentru apelarea funcțiilor, îl vom atribui ca user și vom folosi o întrebare exemplu.
messages= [ {"role": "user", "content": "Find me a good course for a beginner student to learn Azure."} ]Prin atribuirea diferitelor roluri, este clar pentru LLM dacă este sistemul care spune ceva sau utilizatorul, ceea ce ajută la construirea unui istoric de conversație pe care LLM-ul îl poate folosi.
Următorul pas este să definim o funcție și parametrii acelei funcții. Vom folosi doar o funcție aici numită search_courses, dar poți crea mai multe funcții.
Important: Funcțiile sunt incluse în mesajul sistemului către LLM și vor fi incluse în numărul de tokeni disponibili pe care îi ai.
Mai jos, creăm funcțiile ca un array de elemente. Fiecare element este o funcție și are proprietăți name, description și parameters:
functions = [
{
"name":"search_courses",
"description":"Retrieves courses from the search index based on the parameters provided",
"parameters":{
"type":"object",
"properties":{
"role":{
"type":"string",
"description":"The role of the learner (i.e. developer, data scientist, student, etc.)"
},
"product":{
"type":"string",
"description":"The product that the lesson is covering (i.e. Azure, Power BI, etc.)"
},
"level":{
"type":"string",
"description":"The level of experience the learner has prior to taking the course (i.e. beginner, intermediate, advanced)"
}
},
"required":[
"role"
]
}
}
]Să descriem fiecare instanță a funcției mai detaliat mai jos:
name- Numele funcției pe care dorim să o apelăm.description- Aceasta este descrierea modului în care funcția funcționează. Aici este important să fii specific și clar.parameters- O listă de valori și format pe care dorim ca modelul să le producă în răspunsul său. Array-ul de parametri constă în elemente unde elementele au următoarele proprietăți:type- Tipul de date în care vor fi stocate proprietățile.properties- Lista valorilor specifice pe care modelul le va folosi pentru răspunsul său formatat.name- Cheia este numele proprietății pe care modelul o va folosi în răspunsul său formatat, de exemplu,product.type- Tipul de date al acestei proprietăți, de exemplu,string.description- Descrierea proprietății specifice.
Există, de asemenea, o proprietate opțională required - proprietatea necesară pentru ca apelul funcției să fie complet.
După definirea unei funcții, acum trebuie să o includem în apelul către API-ul Chat Completion. Facem acest lucru adăugând functions la cerere. În acest caz, functions=functions.
Există, de asemenea, o opțiune de a seta function_call la auto. Acest lucru înseamnă că vom lăsa LLM-ul să decidă ce funcție ar trebui să fie apelată pe baza mesajului utilizatorului, mai degrabă decât să o atribuim noi înșine.
Iată un cod mai jos unde apelăm ChatCompletion.create, observă cum setăm functions=functions și function_call="auto" și astfel oferim LLM-ului opțiunea de a decide când să apeleze funcțiile pe care i le oferim:
response = client.chat.completions.create(model=deployment,
messages=messages,
functions=functions,
function_call="auto")
print(response.choices[0].message)Răspunsul care vine înapoi arată astfel:
{
"role": "assistant",
"function_call": {
"name": "search_courses",
"arguments": "{\n \"role\": \"student\",\n \"product\": \"Azure\",\n \"level\": \"beginner\"\n}"
}
}Aici putem vedea cum funcția search_courses a fost apelată și cu ce argumente, așa cum sunt listate în proprietatea arguments din răspunsul JSON.
Concluzia este că LLM-ul a fost capabil să găsească datele pentru a se potrivi argumentelor funcției, deoarece le-a extras din valoarea furnizată parametrului messages în apelul de completare a chatului. Mai jos este o reamintire a valorii messages:
messages= [ {"role": "user", "content": "Find me a good course for a beginner student to learn Azure."} ]După cum poți vedea, student, Azure și beginner au fost extrase din messages și setate ca intrare pentru funcție. Utilizarea funcțiilor în acest mod este o modalitate excelentă de a extrage informații dintr-un prompt, dar și de a oferi structură LLM-ului și de a avea funcționalități reutilizabile.
Următorul pas este să vedem cum putem folosi acest lucru în aplicația noastră.
După ce am testat răspunsul formatat de la LLM, putem acum să integrăm acest lucru într-o aplicație.
Pentru a integra acest lucru în aplicația noastră, să urmăm pașii următori:
-
Mai întâi, să facem apelul către serviciile OpenAI și să stocăm mesajul într-o variabilă numită
response_message.response_message = response.choices[0].message
-
Acum vom defini funcția care va apela API-ul Microsoft Learn pentru a obține o listă de cursuri:
import requests def search_courses(role, product, level): url = "https://learn.microsoft.com/api/catalog/" params = { "role": role, "product": product, "level": level } response = requests.get(url, params=params) modules = response.json()["modules"] results = [] for module in modules[:5]: title = module["title"] url = module["url"] results.append({"title": title, "url": url}) return str(results)
Observă cum acum creăm o funcție Python reală care se potrivește cu numele funcțiilor introduse în variabila
functions. De asemenea, facem apeluri API externe reale pentru a obține datele de care avem nevoie. În acest caz, mergem către API-ul Microsoft Learn pentru a căuta module de instruire.
Ok, deci am creat variabilele functions și o funcție Python corespunzătoare, cum spunem LLM-ului cum să le mapăm astfel încât funcția Python să fie apelată?
-
Pentru a vedea dacă trebuie să apelăm o funcție Python, trebuie să analizăm răspunsul LLM și să vedem dacă
function_callface parte din acesta și să apelăm funcția indicată. Iată cum poți face verificarea menționată mai jos:# Check if the model wants to call a function if response_message.function_call.name: print("Recommended Function call:") print(response_message.function_call.name) print() # Call the function. function_name = response_message.function_call.name available_functions = { "search_courses": search_courses, } function_to_call = available_functions[function_name] function_args = json.loads(response_message.function_call.arguments) function_response = function_to_call(**function_args) print("Output of function call:") print(function_response) print(type(function_response)) # Add the assistant response and function response to the messages messages.append( # adding assistant response to messages { "role": response_message.role, "function_call": { "name": function_name, "arguments": response_message.function_call.arguments, }, "content": None } ) messages.append( # adding function response to messages { "role": "function", "name": function_name, "content":function_response, } )
Aceste trei linii asigură că extragem numele funcției, argumentele și facem apelul:
function_to_call = available_functions[function_name] function_args = json.loads(response_message.function_call.arguments) function_response = function_to_call(**function_args)
Mai jos este rezultatul rulării codului nostru:
Rezultat
{ "name": "search_courses", "arguments": "{\n \"role\": \"student\",\n \"product\": \"Azure\",\n \"level\": \"beginner\"\n}" } Output of function call: [{'title': 'Describe concepts of cryptography', 'url': 'https://learn.microsoft.com/training/modules/describe-concepts-of-cryptography/? WT.mc_id=api_CatalogApi'}, {'title': 'Introduction to audio classification with TensorFlow', 'url': 'https://learn.microsoft.com/en- us/training/modules/intro-audio-classification-tensorflow/?WT.mc_id=api_CatalogApi'}, {'title': 'Design a Performant Data Model in Azure SQL Database with Azure Data Studio', 'url': 'https://learn.microsoft.com/training/modules/design-a-data-model-with-ads/? WT.mc_id=api_CatalogApi'}, {'title': 'Getting started with the Microsoft Cloud Adoption Framework for Azure', 'url': 'https://learn.microsoft.com/training/modules/cloud-adoption-framework-getting-started/?WT.mc_id=api_CatalogApi'}, {'title': 'Set up the Rust development environment', 'url': 'https://learn.microsoft.com/training/modules/rust-set-up-environment/?WT.mc_id=api_CatalogApi'}] <class 'str'> -
Acum vom trimite mesajul actualizat,
messages, către LLM astfel încât să putem primi un răspuns în limbaj natural în loc de un răspuns formatat JSON API.print("Messages in next request:") print(messages) print() second_response = client.chat.completions.create( messages=messages, model=deployment, function_call="auto", functions=functions, temperature=0 ) # get a new response from GPT where it can see the function response print(second_response.choices[0].message)
Rezultat
{ "role": "assistant", "content": "I found some good courses for beginner students to learn Azure:\n\n1. [Describe concepts of cryptography] (https://learn.microsoft.com/training/modules/describe-concepts-of-cryptography/?WT.mc_id=api_CatalogApi)\n2. [Introduction to audio classification with TensorFlow](https://learn.microsoft.com/training/modules/intro-audio-classification-tensorflow/?WT.mc_id=api_CatalogApi)\n3. [Design a Performant Data Model in Azure SQL Database with Azure Data Studio](https://learn.microsoft.com/training/modules/design-a-data-model-with-ads/?WT.mc_id=api_CatalogApi)\n4. [Getting started with the Microsoft Cloud Adoption Framework for Azure](https://learn.microsoft.com/training/modules/cloud-adoption-framework-getting-started/?WT.mc_id=api_CatalogApi)\n5. [Set up the Rust development environment](https://learn.microsoft.com/training/modules/rust-set-up-environment/?WT.mc_id=api_CatalogApi)\n\nYou can click on the links to access the courses." }
Pentru a continua învățarea despre Apelarea Funcțiilor Azure OpenAI, poți construi:
- Mai mulți parametri ai funcției care ar putea ajuta cursanții să găsească mai multe cursuri.
- Creează un alt apel de funcție care să preia mai multe informații de la cursant, cum ar fi limba lor maternă.
- Creează gestionarea erorilor atunci când apelul funcției și/sau apelul API nu returnează niciun curs potrivit
Sugestie: Urmează pagina Learn API reference documentation pentru a vedea cum și unde sunt disponibile aceste date.
După ce finalizezi această lecție, verifică colecția noastră Generative AI Learning collection pentru a continua să îți dezvolți cunoștințele despre Generative AI!
Mergi la Lecția 12, unde vom analiza cum să proiectăm UX pentru aplicații AI!
Declinare de responsabilitate:
Acest document a fost tradus folosind serviciul de traducere AI Co-op Translator. Deși ne străduim să asigurăm acuratețea, vă rugăm să fiți conștienți că traducerile automate pot conține erori sau inexactități. Documentul original în limba sa maternă ar trebui considerat sursa autoritară. Pentru informații critice, se recomandă traducerea profesională realizată de oameni. Nu ne asumăm responsabilitatea pentru neînțelegerile sau interpretările greșite care pot apărea din utilizarea acestei traduceri.


