Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Este tutorial irá guiá-lo através da utilização da API embeddings da Azure OpenAI para realizar pesquisa de documentos, onde consultará uma base de conhecimento para encontrar o documento mais relevante.
Neste tutorial, aprende como:
- Descarregue um conjunto de dados de exemplo e prepare-o para análise.
- Cria variáveis de ambiente para o endpoint dos seus recursos e a chave de API.
- Use um dos seguintes modelos: "text-embedding-ada-002" (Versão 2), "text-embedding-3-grande", "text-embedding-3-pequeno".
- Utilize a semelhança do cosseno para classificar os resultados de pesquisa.
Pré-requisitos
- Uma subscrição Azure - Crie uma gratuitamente
- Um recurso Microsoft Foundry ou Azure OpenAI com o modelo text-embedding-ada-002 (Versão 2) implementado. Este modelo está atualmente disponível apenas em certas regiões.
- Python versão 3.10 ou posterior
- As seguintes bibliotecas Python:
openai,num2words,matplotlib,plotly,scipy,scikit-learn,pandas,tiktoken. - Cadernos Jupyter
Configuração
Bibliotecas Python
Se ainda não o fez, precisa de instalar as seguintes bibliotecas:
pip install openai num2words matplotlib plotly scipy scikit-learn pandas tiktoken
Descarregue o conjunto de dados BillSum
BillSum é um conjunto de dados de projetos de lei do Congresso dos Estados Unidos e dos estados da Califórnia. Para fins ilustrativos, vamos olhar apenas para as notas dos EUA. O corpus consiste em projetos de lei das 103.ª-115.ª sessões (1993-2018) do Congresso. Os dados foram divididos em 18.949 projetos de comboio e 3.269 projetos de teste. O corpus BillSum foca-se em legislação de comprimento médio entre 5.000 e 20.000 caracteres. Mais informações sobre o projeto e o artigo académico original de onde este conjunto de dados deriva podem ser encontradas no repositório de GitHub do projeto BillSum
Este tutorial utiliza o ficheiro bill_sum_data.csv que pode ser descarregado do nosso repositório de dados de amostra GitHub.
Também pode descarregar os dados de exemplo executando o seguinte comando na sua máquina 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
A autenticação baseada no Microsoft Entra ID atualmente não é suportada para embeddings com a API v1.
Recuperar chave e endpoint
Para fazer uma chamada com sucesso na Azure OpenAI, precisa de um endpoint e de uma chave.
| Nome da variável | Valor |
|---|---|
ENDPOINT |
O endpoint do serviço pode ser encontrado na seção https://docs-test-001.openai.azure.com/. |
API-KEY |
Este valor pode ser encontrado na secção Keys e Endpoint ao examinar o seu recurso no portal do Azure. Pode usar tanto KEY1 como KEY2. |
Aceda ao seu recurso no portal Azure. A secção Chaves e Endpoints pode ser encontrada na secção de Gestão de Recursos . Copie o seu endpoint e a chave de acesso, pois vai precisar de ambos para autenticar as suas chamadas API. Pode usar tanto KEY1 como KEY2. Ter sempre duas chaves permite-lhe alternar e regenerar chaves de forma segura, sem causar interrupções no serviço.
Variáveis ambientais
Cria e atribui variáveis persistentes de ambiente para a tua chave API.
Importante
Use as chaves API com cautela. Não incluas a chave API diretamente no teu código e nunca a publiques publicamente. Se usares uma chave API, guarda-a de forma segura no Azure Key Vault. Para obter mais informações sobre o uso seguro das chaves API nas suas aplicações, consulte chaves API com Azure Key Vault.
Para mais informações sobre a segurança dos serviços de IA, consulte Autenticar pedidos 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, pode ser necessário fechar e reabrir os notebooks Jupyter ou qualquer IDE que esteja a usar para que as variáveis de ambiente sejam acessíveis. Embora recomendemos fortemente o uso do Jupyter Notebooks, se por algum motivo não o puder fazer, terá de modificar qualquer código que esteja a retornar um dataframe do pandas usando print(dataframe_name) em vez de chamar o dataframe_name diretamente, como é frequentemente feito no final de um bloco de código.
Execute o seguinte código no seu IDE Python preferido:
Bibliotecas de importação
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 o nosso ficheiro csv e criar um pandas DataFrame. Depois de criado o DataFrame inicial, podemos visualizar 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 vamos criar um novo DataFrame mais pequeno chamado df_bills que conterá apenas as colunas para text, summary, e title.
df_bills = df[['text', 'summary', 'title']]
df_bills
Saída:
De seguida, vamos fazer uma limpeza leve dos dados, removendo espaços em branco redundantes e limpando a pontuação para preparar os dados para 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 quaisquer faturas que sejam demasiado longas 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
Neste caso, todas as faturas estão abaixo do limite de token de entrada do modelo de incorporação, mas pode usar a técnica acima para remover entradas que, de outra forma, fariam com que a incorporação falhasse. Quando confrontado com conteúdo que ultrapassa o limite de embedding, também pode dividir o conteúdo em pedaços mais pequenos e depois incorporar os blocos um de cada vez.
Vamos examinar df_bills novamente.
df_bills
Saída:
Para compreender um pouco melhor a coluna n_tokens e como o texto é, em última análise, 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 a nossa documentação, estamos a truncar intencionalmente a saída, mas ao executar este comando no seu ambiente, o texto completo do índice zero será tokenizado em blocos. Pode ver que, em alguns casos, uma palavra inteira é representada com um único token, enquanto noutros partes das palavras são divididas por 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 depois verificar o comprimento da decode variável, verá que corresponde ao primeiro número na coluna n_tokens.
len(decode)
1466
Agora que compreendemos melhor como funciona a tokenização, podemos avançar para o embedding. É importante notar que ainda não tokenizámos os documentos. A n_tokens coluna é simplesmente uma forma de garantir que nenhum dos dados que passamos para o modelo para tokenização e embedding ultrapassa o limite de tokens de entrada de 8.192. Quando passamos os documentos para o modelo de embeddings, ele divide os documentos em tokens semelhantes (embora não necessariamente idênticos) aos exemplos acima e depois converte os tokens numa série de números de ponto flutuante que serão acessíveis via pesquisa vetorial. Estas incorporações podem ser armazenadas localmente ou numa base de dados Azure para suportar Pesquisa Vetorial. Como resultado, cada fatura terá o seu próprio vetor de incorporação correspondente na nova ada_v2 coluna do lado direito do DataFrame.
No exemplo abaixo, estamos a chamar o modelo de embedding uma vez por cada item que queremos incorporar. Ao trabalhar com grandes projetos de incorporação, pode-se passar ao modelo uma matriz de entradas para incorporar, em vez de enviar uma entrada de cada vez. Quando passa um array de entradas para o modelo, o número máximo de itens de entrada por chamada para o endpoint de embedding é 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:
À medida que executamos o bloco de código de pesquisa abaixo, vamos incorporar a consulta de pesquisa "Posso obter informações sobre receitas fiscais das empresas de cabo?" com o mesmo modelo text-embedding-ada-002 (Versão 2 ). A seguir, vamos encontrar a incorporação de fatura que se aproxima mais do texto recém-incorporado da nossa consulta, classificada por 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:
Finalmente, vamos mostrar o resultado principal da pesquisa de documentos com base na consulta do utilizador contra toda a base de conhecimento. Este é o resultado principal do "Taxpayer's Right to View Act de 1993". Este documento tem uma pontuação de similaridade de 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 esta abordagem, pode usar embeddings como mecanismo de pesquisa entre documentos numa base de conhecimento. O utilizador pode então utilizar o melhor resultado da pesquisa e usá-lo para a sua tarefa subsequente, que motivou a sua consulta inicial.
Resolução de problemas
-
401/403: Verificar se
AZURE_OPENAI_API_KEYestá definido e corresponde à sua chave de recursos. -
404: Verifique se
AZURE_OPENAI_EMBEDDINGS_DEPLOYMENTcorresponde ao nome da sua implementação. -
URL inválida: Verifique se
AZURE_OPENAI_ENDPOINTé o endpoint do seu recurso, por exemplohttps://<resource-name>.openai.azure.com.
Recursos de limpeza
Se criou um recurso Azure OpenAI apenas para completar este tutorial e quiser limpar e remover um recurso Azure OpenAI, terá de eliminar os seus modelos implementados e depois eliminar o recurso ou grupo de recursos associado se for dedicado ao seu recurso de teste. Eliminar o grupo de recursos também elimina quaisquer outros recursos associados a ele.
Próximos passos
Saiba mais sobre os modelos do Azure OpenAI:
- Armazene os seus embeddings e realize pesquisa vetorial (similaridade) usando o serviço Azure à sua escolha: