Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Ce tutoriel vous guide tout au long de l'utilisation de l'API Azure OpenAI embeddings pour effectuer document search où vous allez interroger une base de connaissances pour trouver le document le plus pertinent.
Dans ce tutoriel, vous allez apprendre à :
- Téléchargez un exemple de jeu de données et préparez-le pour l’analyse.
- Créez des variables d’environnement pour votre point de terminaison de ressources et votre clé API.
- Utilisez l’un des modèles suivants : text-embedding-ada-002 (version 2), text-embedding-3-large, text-embedding-3-small models.
- Utilisez la similarité cosinus pour classer les résultats de la recherche.
Conditions préalables
- Un abonnement Azure - Create one gratuitement
- Ressource Microsoft Foundry ou Azure OpenAI avec déploiement du modèle text-embedding-ada-002 (version 2). Ce modèle est actuellement disponible uniquement dans certaines régions.
- Python version 3.10 ou ultérieure
- Les bibliothèques Python suivantes :
openai,num2words,matplotlib,plotly,scipy,scikit-learn,pandas,tiktoken. - Jupyter Notebooks
Configurer
bibliothèques de Python
Si ce n’est déjà fait, vous devez installer les bibliothèques suivantes :
pip install openai num2words matplotlib plotly scipy scikit-learn pandas tiktoken
Télécharger le jeu de données BillSum
BillSum est un jeu de données comprenant des projets de loi du Congrès des États-Unis et de l'État de Californie. À des fins d’illustration, nous allons examiner uniquement les factures américaines. Le corpus se compose de projets de loi des sessions du 103e-115e (1993-2018) du Congrès. Les données ont été divisées en 18 949 factures de train et 3 269 factures de test. Le corpus BillSum se concentre sur la législation allant de 5 000 à 20 000 caractères. Pour plus d'informations sur le projet et le document universitaire d'origine à partir duquel ce jeu de données est dérivé, consultez le dépôt GitHub du projet BillSum
Ce tutoriel utilise le fichier bill_sum_data.csv qui peut être téléchargé à partir de notre exemple de données GitHub.
Vous pouvez également télécharger les exemples de données en exécutant la commande suivante sur votre ordinateur local :
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
Note
actuellement, l’authentification basée sur Microsoft Entra ID n’est pas prise en charge pour les incorporations avec l’API v1.
Récupérer la clé et le point de terminaison
Pour effectuer un appel sur Azure OpenAI, vous avez besoin d’un endpoint et d’une key.
| Nom de la variable | Valeur |
|---|---|
ENDPOINT |
Le point de terminaison de service se trouve dans le https://docs-test-001.openai.azure.com/. |
API-KEY |
Cette valeur se trouve dans la KEY1 ou KEY2. |
Accédez à votre ressource dans le portail Azure. La section Clés et point de terminaison se trouve dans la section Gestion des ressources . Copiez votre point de terminaison et votre clé d’accès, car vous aurez besoin des deux pour authentifier vos appels d’API. Vous pouvez utiliser l’un ou l’autre KEY1 ou KEY2. Toujours avoir deux clés vous permet de faire pivoter et de régénérer en toute sécurité les clés sans provoquer d’interruption de service.
Variables d’environnement
Créez et affectez des variables d’environnement persistantes pour votre clé API.
Important
Utilisez des clés API avec précaution. N’incluez pas la clé API directement dans votre code et ne la publiez jamais publiquement. Si vous utilisez une clé API, stockez-la en toute sécurité dans Azure Key Vault. Pour plus d’informations sur l’utilisation sécurisée des clés API dans vos applications, consultez les API avec Azure Key Vault.
Pour plus d’informations sur la sécurité des services d’INTELLIGENCE artificielle, consultez Demandes d’authentification à Azure AI services.
setx AZURE_OPENAI_API_KEY "REPLACE_WITH_YOUR_KEY_VALUE_HERE"
Après avoir défini les variables d’environnement, vous devrez peut-être fermer et rouvrir les notebooks Jupyter ou l’IDE que vous utilisez pour que les variables d’environnement soient accessibles. Bien que nous vous recommandions vivement d'utiliser Jupyter Notebooks, si, pour une raison quelconque, vous ne pouvez pas le faire, vous devrez modifier tout code qui retourne un dataframe pandas en utilisant print(dataframe_name) plutôt que d'appeler directement dataframe_name comme c'est souvent le cas à la fin d'un bloc de code.
Exécutez le code suivant dans votre IDE de Python préféré :
Importer des bibliothèques
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
Nous devons maintenant lire notre fichier csv et créer un DataFrame pandas. Une fois le DataFrame initial créé, nous pouvons afficher le contenu de la table en exécutant 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
Sortie:
La table initiale comporte plus de colonnes que nous avons besoin de créer un dataFrame plus petit appelé df_bills qui contiendra uniquement les colonnes pour text, summaryet title.
df_bills = df[['text', 'summary', 'title']]
df_bills
Sortie:
Ensuite, nous allons effectuer un nettoyage léger des données en supprimant les espaces blancs redondants et en supprimant la ponctuation pour préparer les données pour la tokenisation.
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))
Nous devons maintenant supprimer les factures trop longues pour la limite de jetons (8 192 jetons).
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
Note
Dans ce cas, toutes les factures sont sous la limite de jeton d’entrée du modèle d’incorporation, mais vous pouvez utiliser la technique ci-dessus pour supprimer les entrées qui entraîneraient l’échec de l’incorporation. En cas de problème avec le contenu qui dépasse la limite d’incorporation, vous pouvez également segmenter le contenu en morceaux plus petits, puis incorporer les blocs un par un.
Nous examinerons à nouveau df_bills.
df_bills
Sortie:
Pour comprendre la n_tokens colonne un peu plus ainsi que la façon dont le texte est finalement tokenisé, il peut être utile d’exécuter le code suivant :
sample_encode = tokenizer.encode(df_bills.text[0])
decode = tokenizer.decode_tokens_bytes(sample_encode)
decode
Pour nos documents, nous tronquons intentionnellement le résultat, mais l’exécution de cette commande dans votre environnement retournera le texte intégral depuis l’index zéro, tokenisé en blocs. Vous pouvez voir que dans certains cas, un mot entier est représenté avec un seul jeton, tandis que dans d’autres parties de mots sont fractionnés sur plusieurs jetons.
[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',
Si vous vérifiez ensuite la longueur de la decode variable, elle correspond au premier numéro de la colonne n_tokens.
len(decode)
1466
Maintenant que nous comprenons plus en détail le fonctionnement de la tokenisation, nous pouvons passer à l’incorporation. Il est important de noter que nous n’avons pas encore tokenisé les documents. La n_tokens colonne est simplement un moyen de s’assurer qu’aucune des données que nous transmettons au modèle pour la tokenisation et l’incorporation dépasse la limite de jeton d’entrée de 8 192. Lorsque nous transmettons les documents au modèle d’incorporation, il décompose les documents en jetons similaires (mais pas nécessairement identiques) aux exemples ci-dessus, puis convertissons les jetons en une série de nombres à virgule flottante qui seront accessibles via la recherche vectorielle. Ces incorporations peuvent être stockées localement ou dans une base de données Azure pour prendre en charge la recherche vectorielle. Par conséquent, chaque facture aura son propre vecteur d’incorporation correspondant dans la nouvelle ada_v2 colonne à droite du DataFrame.
Dans l’exemple ci-dessous, nous appelons le modèle d’incorporation une fois par élément que nous voulons incorporer. Lorsque vous travaillez sur des projets d’intégration volumineux, vous pouvez également fournir au modèle un tableau d’entrées à intégrer plutôt qu’une entrée unique à la fois. Lorsque vous passez au modèle un tableau d’entrées, le nombre maximal d’éléments d’entrée par appel au point de terminaison d'embedding est de 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
Sortie:
Lorsque nous exécutons le bloc de code de recherche ci-dessous, nous allons incorporer la requête de recherche « Puis-je obtenir des informations sur les revenus fiscaux de la société de câble ? » avec le même modèle text-embedding-ada-002 (version 2). Nous trouverons ensuite la facture la plus proche incorporée au texte nouvellement incorporé à partir de notre requête classée par similarité cosinus.
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)
Sortie :
Enfin, nous allons afficher le résultat principal de la recherche de documents en fonction de la requête utilisateur sur l’ensemble de la base de connaissances. Cela renvoie le meilleur résultat de la « Loi sur le droit d’affichage des contribuables de 1993 ». Ce document a un score de similarité par cosinus de 0,76 entre la requête et le document :
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."
À l’aide de cette approche, vous pouvez utiliser des incorporations comme mécanisme de recherche entre les documents d’une base de connaissances. L'utilisateur peut ensuite prendre le meilleur résultat de recherche et l'utiliser pour sa tâche en aval, qui a motivé sa requête initiale.
Dépannage
-
401/403 : Vérifiez
AZURE_OPENAI_API_KEYqu’il est défini et correspond à votre clé de ressource. -
404 : Vérifiez
AZURE_OPENAI_EMBEDDINGS_DEPLOYMENTqu’il correspond à votre nom de déploiement. -
URL non valide : vérifiez que
AZURE_OPENAI_ENDPOINTvotre point de terminaison de ressource, par exemplehttps://<resource-name>.openai.azure.com.
Nettoyer les ressources
Si vous avez créé une ressource OpenAI Azure uniquement pour suivre ce didacticiel et que vous souhaitez nettoyer et supprimer une ressource OpenAI Azure, vous devez supprimer vos modèles déployés, puis supprimer la ressource ou le groupe de ressources associé s'il est dédié à votre ressource de test. La suppression du groupe de ressources supprime également toutes les autres ressources associées.
Étapes suivantes
En savoir plus sur les modèles d'OpenAI Azure :
- Stockez vos incorporations et effectuez une recherche vectorielle (similarité) à l’aide de votre choix de service Azure :