Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Questa esercitazione illustra come usare l'API Azure OpenAI embededdings per eseguire document search in cui eseguire una query su una Knowledge Base per trovare il documento più pertinente.
In questa esercitazione si apprenderà come:
- Scaricare un set di dati di esempio e prepararlo per l'analisi.
- Creare variabili di ambiente per l'endpoint delle risorse e la chiave API.
- Usare uno dei modelli seguenti: text-embedding-ada-002 (versione 2), text-embedding-3-large, text-embedding-3-small models.
- Usare la somiglianza del coseno per classificare i risultati della ricerca.
Prerequisiti
- Una sottoscrizione Azure - Crearne una gratuitamente
- Una risorsa Microsoft Foundry o Azure OpenAI con il modello text-embedding-ada-002 (versione 2) implementato. Questo modello è attualmente disponibile solo in determinate aree.
- Python versione 3.10 o successiva
- Le librerie di Python seguenti:
openai,num2words,matplotlib,plotly,scipy,scikit-learn,pandas,tiktoken. - Notebook di Jupyter
Configurare
librerie Python
Se non è già stato fatto, è necessario installare le librerie seguenti:
pip install openai num2words matplotlib plotly scipy scikit-learn pandas tiktoken
Scaricare il set di dati BillSum
BillSum è un dataset di progetti di legge del Congresso degli Stati Uniti e dello stato della California. A scopo illustrativo, verranno esaminate solo le fatture degli Stati Uniti. Il corpus è costituito da fatture delle sessioni del Congresso del 103-115 (1993-2018). I dati sono stati suddivisi in 18.949 fatture dei treni e 3.269 fatture di test. Il corpus BillSum è incentrato sulla legislazione di media lunghezza da 5.000 a 20.000 caratteri di lunghezza. Altre informazioni sul progetto e sul documento accademico originale da cui deriva questo set di dati sono disponibili nel repository GitHub del progetto BillSum
Questo tutorial utilizza il file bill_sum_data.csv che può essere scaricato dai nostri dati di esempio GitHub.
È anche possibile scaricare i dati di esempio eseguendo il comando seguente nel computer locale:
curl "https://raw.githubusercontent.com/Azure-Samples/Azure-OpenAI-Docs-Samples/main/Samples/Tutorials/Embeddings/data/bill_sum_data.csv" --output bill_sum_data.csv
Nota
Autenticazione basata su Microsoft Entra ID non è attualmente supportata per gli embedding con l'API v1.
Recuperare la chiave e l'endpoint
Per effettuare correttamente una chiamata a Azure OpenAI, è necessario un endpoint e un key.
| Nome variabile | Valore |
|---|---|
ENDPOINT |
L'endpoint del servizio è disponibile nella sezione Keys e Endpoint quando si esamina la risorsa dal Portale di Azure. In alternativa, è possibile trovare l'endpoint tramite la pagina Deployments nel portale di Microsoft Foundry. Un endpoint di esempio è: https://docs-test-001.openai.azure.com/. |
API-KEY |
Questo valore è disponibile nella Keys e Endpoint quando esamini la risorsa dal portale di Azure. È possibile usare KEY1 o KEY2. |
Passare alla risorsa nel portale di Azure. La sezione Chiavi ed endpoint è disponibile nella sezione Gestione risorse . Copiare l'endpoint e la chiave di accesso perché saranno necessari entrambi per l'autenticazione delle chiamate API. È possibile usare KEY1 o KEY2. Avere sempre due chiavi consente di ruotare e rigenerare le chiavi in modo sicuro senza causare un'interruzione del servizio.
Variabili di ambiente
Creare e assegnare variabili di ambiente persistenti per la chiave API.
Importante
Usare le chiavi API con cautela. Non includere la chiave API direttamente nel codice e non pubblicarla mai pubblicamente. Se si usa una chiave API, archiviarla in modo sicuro in Azure Key Vault. Per altre informazioni sull'uso sicuro delle chiavi API nelle app, vedere ChiaviAPI con Azure Key Vault.
Per altre informazioni sulla sicurezza dei servizi di intelligenza artificiale, vedere Autorizzazione delle richieste a Servizi di Azure AI.
setx AZURE_OPENAI_API_KEY "REPLACE_WITH_YOUR_KEY_VALUE_HERE"
Dopo aver impostato le variabili di ambiente, potrebbe essere necessario chiudere e riaprire i notebook di Jupyter o qualsiasi IDE in uso per consentire l'accessibilità delle variabili di ambiente. Sebbene sia fortemente consigliato usare Jupyter Notebook, se per qualche motivo non puoi, avrai bisogno di modificare il codice che restituisce un dataframe di pandas usando print(dataframe_name) anziché semplicemente chiamare dataframe_name direttamente, come spesso avviene alla fine di un blocco di codice.
Eseguire il codice seguente nell'IDE di Python preferito:
Importare librerie
import os
import re
import requests
import sys
from num2words import num2words
import os
import pandas as pd
import numpy as np
import tiktoken
from openai import OpenAI
A questo momento è necessario leggere il file CSV e creare un dataframe pandas. Dopo aver creato il dataframe iniziale, è possibile visualizzare il contenuto della tabella eseguendo df.
df=pd.read_csv(os.path.join(os.getcwd(),'bill_sum_data.csv')) # This assumes that you have placed the bill_sum_data.csv in the same directory you are running Jupyter Notebooks
df
Output:
La tabella iniziale include più colonne di quelle necessarie per creare un nuovo dataframe più piccolo denominato df_bills che conterrà solo le colonne per text, summarye title.
df_bills = df[['text', 'summary', 'title']]
df_bills
Output:
Successivamente si eseguirà una pulizia dei dati leggeri rimuovendo gli spazi vuoti ridondanti e pulendo la punteggiatura per preparare i dati per la tokenizzazione.
pd.options.mode.chained_assignment = None #https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#evaluation-order-matters
# s is input text
def normalize_text(s, sep_token = " \n "):
s = re.sub(r'\s+', ' ', s).strip()
s = re.sub(r"\. ,","",s)
# remove all instances of multiple spaces
s = s.replace("..",".")
s = s.replace(". .",".")
s = s.replace("\n", "")
s = s.strip()
return s
df_bills['text']= df_bills["text"].apply(lambda x : normalize_text(x))
È ora necessario rimuovere le fatture troppo lunghe per il limite di token (8.192 token).
tokenizer = tiktoken.get_encoding("cl100k_base")
df_bills['n_tokens'] = df_bills["text"].apply(lambda x: len(tokenizer.encode(x)))
df_bills = df_bills[df_bills.n_tokens<8192]
len(df_bills)
20
Nota
In questo caso, tutte le fatture si trovano al di sotto del limite di token di input del modello di incorporamento, ma è possibile usare la tecnica precedente per rimuovere le voci che altrimenti causano un errore di incorporamento. Quando il contenuto supera il limite di incorporamento, è anche possibile suddividere il contenuto in parti più piccole e quindi incorporare i blocchi uno alla volta.
Esamineremo di nuovo df_bills.
df_bills
Output:
Per comprendere la colonna n_tokens un po' più bene come viene tokenizzato il testo, può essere utile eseguire il codice seguente:
sample_encode = tokenizer.encode(df_bills.text[0])
decode = tokenizer.decode_tokens_bytes(sample_encode)
decode
Per la nostra documentazione, stiamo intenzionalmente troncando l'output, ma eseguendo questo comando nel tuo ambiente verrà restituito il testo completo dall'indice zero suddiviso in blocchi. È possibile notare che in alcuni casi un'intera parola è rappresentata con un singolo token, mentre in altre parti di parole vengono suddivisi tra più token.
[b'SECTION',
b' ',
b'1',
b'.',
b' SHORT',
b' TITLE',
b'.',
b' This',
b' Act',
b' may',
b' be',
b' cited',
b' as',
b' the',
b' ``',
b'National',
b' Science',
b' Education',
b' Tax',
b' In',
b'cent',
b'ive',
b' for',
b' Businesses',
b' Act',
b' of',
b' ',
b'200',
b'7',
b"''.",
b' SEC',
b'.',
b' ',
b'2',
b'.',
b' C',
b'RED',
b'ITS',
b' FOR',
b' CERT',
b'AIN',
b' CONTRIBUT',
b'IONS',
b' BEN',
b'EF',
b'IT',
b'ING',
b' SC',
Se quindi si controlla la lunghezza della decode variabile, si troverà che corrisponda al primo numero nella colonna n_tokens.
len(decode)
1466
Ora che si comprende di più sul funzionamento della tokenizzazione, è possibile passare all'incorporamento. È importante notare che i documenti non sono ancora stati tokenizzati. La n_tokens colonna è semplicemente un modo per assicurarsi che nessuno dei dati passati al modello per la tokenizzazione e l'incorporamento superi il limite di token di input di 8.192. Quando si passano i documenti al modello di incorporamento, i documenti verranno suddivisi in token simili (anche se non necessariamente identici) agli esempi precedenti e quindi convertiranno i token in una serie di numeri a virgola mobile che saranno accessibili tramite la ricerca vettoriale. Questi incorporamenti possono essere archiviati in locale o in un database Azure per supportare La ricerca vettoriale. Di conseguenza, ogni fattura avrà il proprio vettore di incorporamento corrispondente nella nuova ada_v2 colonna a destra del dataframe.
Nell'esempio seguente viene chiamato il modello di incorporamento una volta per ogni elemento da incorporare. Quando si lavora con progetti di incorporamento di grandi dimensioni, in alternativa è possibile passare al modello una matrice di input da incorporare anziché un input alla volta. Quando si passa il modello a una matrice di input, il numero massimo di elementi di input per chiamata all'endpoint di incorporamento è 2048.
client = OpenAI(
api_key = os.getenv("AZURE_OPENAI_API_KEY"),
base_url="https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/"
)
def generate_embeddings(text, model="text-embedding-ada-002"): # model = "deployment_name"
return client.embeddings.create(input = [text], model=model).data[0].embedding
df_bills['ada_v2'] = df_bills["text"].apply(lambda x : generate_embeddings (x, model = 'text-embedding-ada-002')) # model should be set to the deployment name you chose when you deployed the text-embedding-ada-002 (Version 2) model
df_bills
Output:
Quando eseguiamo il blocco di codice di ricerca riportato di seguito, incorporeremo la query di ricerca "È possibile ottenere informazioni sui ricavi fiscali delle società via cavo?" con lo stesso modello text-embedding-ada-002 (Versione 2). A questo punto è possibile trovare l'incorporamento della fattura più vicino al testo appena incorporato della query classificato in base alla somiglianza del coseno.
def cosine_similarity(a, b):
return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
def get_embedding(text, model="text-embedding-ada-002"): # model = "deployment_name"
return client.embeddings.create(input = [text], model=model).data[0].embedding
def search_docs(df, user_query, top_n=4, to_print=True):
embedding = get_embedding(
user_query,
model="text-embedding-ada-002" # model should be set to the deployment name you chose when you deployed the text-embedding-ada-002 (Version 2) model
)
df["similarities"] = df.ada_v2.apply(lambda x: cosine_similarity(x, embedding))
res = (
df.sort_values("similarities", ascending=False)
.head(top_n)
)
if to_print:
display(res)
return res
res = search_docs(df_bills, "Can I get information on cable company tax revenue?", top_n=4)
Output:
Infine, verrà visualizzato il risultato principale della ricerca di documenti in base alla query dell'utente sull'intera knowledge base. Questo restituisce il miglior risultato della "Legge sul Diritto del Contribuente di Visionare del 1993". Questo documento ha un punteggio di somiglianza coseno pari a 0,76 tra la query e il documento:
res["summary"][9]
"Taxpayer's Right to View Act of 1993 - Amends the Communications Act of 1934 to prohibit a cable operator from assessing separate charges for any video programming of a sporting, theatrical, or other entertainment event if that event is performed at a facility constructed, renovated, or maintained with tax revenues or by an organization that receives public financial support. Authorizes the Federal Communications Commission and local franchising authorities to make determinations concerning the applicability of such prohibition. Sets forth conditions under which a facility is considered to have been constructed, maintained, or renovated with tax revenues. Considers events performed by nonprofit or public organizations that receive tax subsidies to be subject to this Act if the event is sponsored by, or includes the participation of a team that is part of, a tax exempt organization."
Usando questo approccio, è possibile usare gli incorporamenti come meccanismo di ricerca tra documenti in una Knowledge Base. L'utente può quindi prendere il primo risultato della ricerca e usarlo per l'attività successiva, che ha originato la loro query iniziale.
Risoluzione dei problemi
-
401/403: Verificare
AZURE_OPENAI_API_KEYche sia impostata e corrisponda alla chiave della risorsa. -
404: Verificare
AZURE_OPENAI_EMBEDDINGS_DEPLOYMENTche corrisponda al nome della distribuzione. -
URL non valido: verificare
AZURE_OPENAI_ENDPOINTche sia l'endpoint della risorsa, ad esempiohttps://<resource-name>.openai.azure.com.
Pulire le risorse
Se è stata creata una risorsa OpenAI Azure esclusivamente per completare questa esercitazione e si vuole pulire e rimuovere una risorsa OpenAI Azure, è necessario eliminare i modelli distribuiti e quindi eliminare la risorsa o il gruppo di risorse associato se è dedicato alla risorsa di test. L'eliminazione del gruppo di risorse elimina anche tutte le altre risorse associate.
Passaggi successivi
Altre informazioni sui modelli Azure OpenAI:
- Archiviare gli incorporamenti ed eseguire una ricerca vettoriale (somiglianza) usando la scelta del servizio Azure: