Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Este tutorial orientará você usando a API Azure OpenAI embeddings API para executar document search em que você consultará uma base de dados de conhecimento para encontrar o documento mais relevante.
Neste tutorial, você aprenderá a:
- Baixe um conjunto de dados de exemplo e prepare-o para análise.
- Crie as variáveis de ambiente para o endpoint de recursos e a chave de API.
- Use um dos seguintes modelos: text-embedding-ada-002 (versão 2), text-embedding-3-large, text-embedding-3-small models.
- Utilize a similaridade de cosseno para classificar os resultados da pesquisa.
Pré-requisitos
- Uma assinatura Azure – Criar uma gratuitamente
- Um recurso Microsoft Foundry ou Azure OpenAI com o modelo text-embedding-ada-002 (versão 2) implantado. Atualmente, esse modelo só está disponível em determinadas regiões.
- Python versão 3.10 ou posterior
- As seguintes bibliotecas de Python:
openai,num2words,matplotlib,plotly,scipy,scikit-learn,pandas,tiktoken. - Jupyter Notebooks
Configurar
bibliotecas de Python
Caso ainda não tenha feito isso, você precisará instalar as seguintes bibliotecas:
pip install openai num2words matplotlib plotly scipy scikit-learn pandas tiktoken
Baixar o conjunto de dados BillSum
BillSum é um conjunto de dados de projetos de lei do Congresso dos Estados Unidos e do estado da Califórnia. Para fins ilustrativos, vamos olhar apenas para as contas dos EUA. O corpus consiste em projetos de lei das sessões 103-115 (1993-2018) do Congresso. Os dados foram divididos em 18.949 contas de trem e 3.269 contas de teste. O corpus BillSum concentra-se na legislação com comprimento médio de 5.000 a 20.000 caracteres. Mais informações sobre o projeto e o artigo acadêmico original do qual esse conjunto de dados é derivado podem ser encontradas no repositório GitHub do projeto BillSum
Este tutorial usa o arquivo bill_sum_data.csv que pode ser baixado de nossos dados de exemplo GitHub.
Você também pode baixar os dados de exemplo executando o seguinte comando em seu computador 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
Nota
no momento, não há suporte para autenticação baseada em Microsoft Entra ID para inserções com a API v1.
Recuperar chave e ponto de extremidade
Para fazer uma chamada com êxito contra Azure OpenAI, você precisa de um endpoint e um key.
| Nome da variável | Valor |
|---|---|
ENDPOINT |
O ponto de extremidade de serviço pode ser encontrado na seção https://docs-test-001.openai.azure.com/. |
API-KEY |
Esse valor pode ser encontrado na seção KEY1 ou KEY2. |
Acesse seu recurso no portal do Azure. A seção KEY1 ou KEY2. Sempre ter duas chaves permite girar e regenerar chaves com segurança sem causar uma interrupção de serviço.
Variáveis de ambiente
Crie e atribua variáveis de ambiente persistentes para sua chave de API.
Importante
Use chaves de API com cuidado. Não inclua a chave de API diretamente em seu código e nunca a publique publicamente. Se você usar uma chave de API, armazene-a com segurança em Azure Key Vault. Para obter mais informações sobre como usar chaves de API com segurança em seus aplicativos, consulte as chaves API com Azure Key Vault.
Para obter mais informações sobre a segurança dos serviços de IA, consulte Autenticar solicitações para Serviços de IA do Azure.
setx AZURE_OPENAI_API_KEY "REPLACE_WITH_YOUR_KEY_VALUE_HERE"
Depois de definir as variáveis de ambiente, talvez seja necessário fechar e reabrir notebooks Jupyter ou qualquer IDE que você esteja usando para que as variáveis de ambiente sejam acessíveis. Embora seja altamente recomendável usar o Jupyter Notebooks, se por algum motivo você não puder, precisará modificar qualquer código que esteja retornando um dataframe pandas usando print(dataframe_name) em vez de apenas chamar o dataframe_name diretamente, como geralmente é feito no final de um bloco de código.
Execute o seguinte código no IDE de Python preferencial:
Importar bibliotecas
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
Agora precisamos ler nosso arquivo csv e criar um pandas DataFrame. Depois que o DataFrame inicial é criado, podemos exibir o conteúdo da tabela executando 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
Saída:
A tabela inicial tem mais colunas do que precisamos, criaremos um DataFrame menor chamado df_bills que conterá apenas as colunas para text, summarye title.
df_bills = df[['text', 'summary', 'title']]
df_bills
Saída:
Em seguida, executaremos algumas limpezas de dados leves removendo o espaço em branco redundante e limpando a pontuação para preparar os dados para a tokenização.
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))
Agora, precisamos remover qualquer fatura que seja muito longa para o limite de tokens (8.192 tokens).
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
Nesse caso, todas as faturas estão abaixo do limite de tokens de entrada do modelo de incorporação, mas você pode usar a técnica acima para remover entradas que, de outra forma, causariam falha na incorporação. Diante do conteúdo que excede o limite de inserção, você também pode dividir o conteúdo em partes menores e, em seguida, inserir as partes uma de cada vez.
Examinaremos novamente df_bills.
df_bills
Saída:
Para entender o n_tokens coluna um pouco mais, bem como como o texto finalmente é tokenizado, pode ser útil executar o seguinte código:
sample_encode = tokenizer.encode(df_bills.text[0])
decode = tokenizer.decode_tokens_bytes(sample_encode)
decode
Para nossos documentos, estamos truncando intencionalmente a saída, mas executar esse comando em seu ambiente retornará o texto completo do índice zero tokenizado em partes. Você pode ver que, em alguns casos, uma palavra inteira é representada com um único token, enquanto em outras partes de palavras são divididas entre vários tokens.
[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 você verificar o comprimento da decode variável, ela corresponderá ao primeiro número na coluna n_tokens.
len(decode)
1466
Agora que entendemos mais sobre como a tokenização funciona, podemos passar para a inserção. É importante observar que ainda não tokenizamos os documentos. A n_tokens coluna é simplesmente uma maneira de garantir que nenhum dos dados que passamos para o modelo para tokenização e inserção exceda o limite de token de entrada de 8.192. Quando passarmos os documentos para o modelo de inserções, ele dividirá os documentos em tokens semelhantes (embora não necessariamente idênticos) aos exemplos acima e converterá os tokens em uma série de números de ponto flutuante que serão acessíveis por meio da pesquisa de vetor. Essas inserções podem ser armazenadas localmente ou em um banco de dados Azure para dar suporte à Pesquisa de Vetor. Como resultado, cada fatura terá seu próprio vetor de inserção correspondente na nova ada_v2 coluna no lado direito do DataFrame.
No exemplo abaixo, estamos chamando o modelo de inserção uma vez por cada item que desejamos inserir. Ao trabalhar com grandes projetos de inserção, você pode, como alternativa, passar ao modelo uma matriz de entradas para inserir em vez de uma entrada por vez. Quando você passa para o modelo uma matriz de entradas, o número máximo de itens de entrada por chamada para o endpoint de incorporação é 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
Saída:
Enquanto executamos o bloco de código de pesquisa abaixo, inseriremos a consulta de pesquisa "Posso obter informações sobre a receita fiscal da empresa de cabo?" com o mesmo modelo text-embedding-ada-002 (versão 2). Em seguida, encontraremos a inserção de fatura mais próxima ao texto recém-inserido de nossa consulta classificada pela similaridade cosseno.
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)
Saída:
Por fim, mostraremos o resultado principal da pesquisa de documentos com base na consulta do usuário em toda a base de dados de conhecimento. Isso retorna o resultado principal da "Lei do Direito do Contribuinte de Acesso de 1993". Este documento tem um índice de similaridade cosseno de 0,76 entre a consulta e o 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 essa abordagem, você pode usar inserções como um mecanismo de pesquisa em documentos em uma base de dados de conhecimento. Em seguida, o usuário pode obter o resultado da pesquisa superior e usá-lo para sua tarefa downstream, o que motivou sua consulta inicial.
Solucionando problemas
-
401/403: Verifique se
AZURE_OPENAI_API_KEYestá definido e corresponde à sua chave de recurso. -
404: Verifique se o
AZURE_OPENAI_EMBEDDINGS_DEPLOYMENTcorresponde ao nome da sua implantação. -
URL inválida: verifique se
AZURE_OPENAI_ENDPOINTé o ponto de extremidade do recurso, por exemplohttps://<resource-name>.openai.azure.com.
Limpar recursos
Se você criou um recurso Azure OpenAI apenas para concluir este tutorial e quiser limpar e remover um recurso Azure OpenAI, precisará excluir seus modelos implantados e excluir o recurso ou o grupo de recursos associado se ele for dedicado ao recurso de teste. Excluir o grupo de recursos também exclui outros recursos associados a ele.
Próximas etapas
Saiba mais sobre os modelos do Azure OpenAI:
- Armazene suas inserções e execute a pesquisa de vetor (similaridade) usando sua escolha de serviço de Azure: