Compartilhar via


Como criar e consumir um índice usando um código

Importante

Alguns dos recursos descritos nesse artigo podem estar disponíveis apenas na versão prévia. Essa versão prévia é fornecida sem um contrato de nível de serviço e não recomendamos isso para cargas de trabalho de produção. Alguns recursos podem não ter suporte ou podem ter restrição de recursos. Para obter mais informações, consulte Termos de Uso Complementares de Versões Prévias do Microsoft Azure.

Neste artigo, você aprenderá a criar um índice e consumi-lo a partir do código. Para criar um índice localmente, usamos o pacote promptflow-rag. Para criar um índice remoto na nuvem, usamos o pacote azure-ai-ml. Nós consumimos os índices usando langchain.

Pré-requisitos

Você deve ter:

  • Um hub do Estúdio de IA e um projeto.

  • Uma conexão de serviço de Pesquisa de IA do Azure para indexar os dados de produto e do cliente de exemplo. Se você não tiver um serviço da Pesquisa de IA do Azure, poderá criar um no portal do Azure ou ver as instruções aqui.

  • Modelos para inserção:

    • Você pode usar um modelo de inserção ada-002 do OpenAI do Azure. As instruções para implantação podem ser encontradas aqui.
    • OU você pode usar qualquer outro modelo de inserção implantado em seu projeto do Estúdio de IA. Neste exemplo, usamos a inserção multilíngue do Cohere. As instruções para implantação deste modelo podem ser encontradas aqui.

Criar e consumir um índice localmente

Nós podemos criar e consumir um índice localmente.

Pacotes necessários para operações de índice local

Instale os pacotes a seguir, necessários para a criação do índice local.

pip install promptflow-rag langchain langchain-openai

Configurar a Pesquisa de IA para uso local

Nós usamos a Pesquisa de IA do Azure como o repositório de índices. Para começar, podemos configurar o serviço Pesquisa de IA do Azure usando o seguinte código:

import os
# set credentials to your Azure AI Search instance
os.environ["AZURE_AI_SEARCH_KEY"] = "<your-ai-search-key>"
os.environ["AZURE_AI_SEARCH_ENDPOINT"] = "https://<your-ai-search-service>.search.windows.net"

Criar um índice localmente usando inserções do OpenAI do Azure

Para criar um índice que usa inserções do OpenAI do Azure, nós configuramos variáveis de ambiente para se conectar ao modelo.

import os
# set credentials to your Azure OpenAI instance
os.environ["OPENAI_API_VERSION"] = "2023-07-01-preview"
os.environ["AZURE_OPENAI_API_KEY"] = "<your-azure-openai-api-key>"
os.environ["AZURE_OPENAI_ENDPOINT"] = "https://<your-azure-openai-service>.openai.azure.com/"

Agora, vamos criar o índice usando a função build_index.

from promptflow.rag.config import LocalSource, AzureAISearchConfig, EmbeddingsModelConfig
from promptflow.rag import build_index

local_index_aoai=build_index(
    name="<your-index-name>" + "aoai",  # name of your index
    vector_store="azure_ai_search",  # the type of vector store
    embeddings_model_config=EmbeddingsModelConfig(
        model_name="text-embedding-ada-002",
        deployment_name="text-embedding-ada-002", # verify if your deployment name is same as model name
    ),
    input_source=LocalSource(input_data="<path-to-your-local-files>"),  # the location of your file/folders
    index_config=AzureAISearchConfig(
        ai_search_index_name="<your-index-name>" + "-aoai-store", # the name of the index store inside the azure ai search service
    ),
    tokens_per_chunk = 800, # Optional field - Maximum number of tokens per chunk
    token_overlap_across_chunks = 0, # Optional field - Number of tokens to overlap between chunks
)

O código acima cria um índice localmente. Ele usa variáveis de ambiente para obter o serviço de Pesquisa de IA e para se conectar ao modelo de inserção do OpenAI do Azure.

Criar um índice localmente usando outros modelos de inserção implantados no seu projeto de estúdio de IA

Para criar um índice que usa um modelo de inserção implantado no seu projeto de estúdio de IA, nós configuramos a conexão com o modelo usando um ConnectionConfig, conforme mostrado abaixo. Os subscription, resource_group e workspace referem-se ao projeto em que o modelo de inserção está instalado. connection_name refere-se ao nome da conexão do modelo, que pode ser encontrado na página de configurações do projeto do de Estúdio de IA.

from promptflow.rag.config import ConnectionConfig

my_connection_config=ConnectionConfig(
    subscription_id="<subscription_id>",
    resource_group_name="<resource_group_name>",
    workspace_name="<ai_studio_project_name>",
    connection_name="<serverless_connection_name>"
    )

Agora, vamos criar o índice usando a função build_index.

from promptflow.rag.config import LocalSource, AzureAISearchConfig, EmbeddingsModelConfig
from promptflow.rag import build_index

local_index_cohere=build_index(
    name="<your-index-name>" + "cohere",  # name of your index
    vector_store="azure_ai_search",  # the type of vector store
    embeddings_model_config=EmbeddingsModelConfig(
        model_name="cohere-embed-v3-multilingual", # in this example we use cohere multi lingual embedding
        connection_config=my_connection_config # created in previous step
    ),
    input_source=LocalSource(input_data="<path-to-your-local-files>"),  # the location of your file/folders
    index_config=AzureAISearchConfig(
        ai_search_index_name="<your-index-name>" + "cohere-store", # the name of the index store inside the azure ai search service
    ),
    tokens_per_chunk = 800, # Optional field - Maximum number of tokens per chunk
    token_overlap_across_chunks = 0, # Optional field - Number of tokens to overlap between chunks
)

O código acima cria um índice localmente. Ele usa variáveis de ambiente para obter o serviço de Pesquisa de IA e a configuração de conexão para se conectar ao modelo de inserção.

Como consumir um índice local

O índice local criado pode ser usado como um recuperador de langchain para consumi-lo em consultas de pesquisa.

from promptflow.rag import get_langchain_retriever_from_index

# Get the OpenAI embedded Index
retriever=get_langchain_retriever_from_index(local_index_aoai)
retriever.get_relevant_documents("<your search query>")

# Get the Cohere embedded Index
retriever=get_langchain_retriever_from_index(local_index_cohere)
retriever.get_relevant_documents("<your search query>")

Como registrar o índice em seu projeto do Estúdio de IA (opcional)

Como opção, você pode registrar o índice em seu projeto do Estúdio de IA para que você ou outras pessoas que tenham acesso ao projeto possam usá-lo na nuvem. Antes de continuar, instale os pacotes necessários para operações remotas.

Conectar-se ao projeto

# connect to the AI Studio project
from azure.identity import DefaultAzureCredential
from azure.ai.ml import MLClient

client=MLClient(
    DefaultAzureCredential(), 
    subscription_id="<subscription_id>",
    resource_group_name="<resource_group_name>",
    workspace_name="<ai_studio_project_name>"
    )

Os subscription, resource_group e workspace no código acima referem-se ao projeto ao qual você deseja se conectar.

Registrar o índice

from azure.ai.ml.entities import Index

# register the index with Azure OpenAI embeddings
client.indexes.create_or_update(
    Index(name="<your-index-name>" + "aoai", 
          path=local_index_aoai, 
          version="1")
          )

# register the index with cohere embeddings
client.indexes.create_or_update(
    Index(name="<your-index-name>" + "cohere", 
          path=local_index_cohere, 
          version="1")
          )

Observação

As variáveis de ambiente são destinadas à conveniência em um ambiente local. No entanto, se você registrar um índice local criado usando variáveis de ambiente, o índice poderá não funcionar conforme o esperado porque os segredos das variáveis de ambiente não’serão transferidos para o índice de nuvem. Para resolver esse problema, você pode usar um ConnectionConfig ou connection_id para criar um índice local antes de registrar.

Criar um índice (remotamente) em seu projeto do Estúdio de IA

Criamos um índice na nuvem em seu projeto do Estúdio de IA.

Pacotes necessários para operações de índice remoto

Instale os pacotes a seguir, que são necessários para a criação do índice remoto.

pip install azure-ai-ml promptflow-rag langchain langchain-openai

Conectar-se ao projeto do Estúdio de IA

Para começar, nós nos conectamos ao projeto. Os subscription, resource_group e workspace no código abaixo referem-se ao projeto ao qual você deseja se conectar.

# connect to the AI Studio project
from azure.identity import DefaultAzureCredential
from azure.ai.ml import MLClient

client=MLClient(
    DefaultAzureCredential(), 
    subscription_id="<subscription_id>",
    resource_group_name="<resource_group_name>",
    workspace_name="<ai_studio_project_name>"
    )

Obter a conexão do serviço de Pesquisa de IA

Esse projeto deve ter uma conexão com o serviço de Pesquisa de IA. Recuperamos os detalhes do projeto.

ai_search_connection = client.connections.get("<ai_search_connection>")

Conectar-se aos modelos de inserção

Você pode se conectar ao OpenAI do Azure usando conexões do Microsoft Entra ID ou conexões baseadas na chave de API.

from azure.ai.ml.entities import IndexModelConfiguration
## aoai connections - entra id
aoai_connection = client.connections.get("<your_aoai_entra_id_connection>")
embeddings_model_config = IndexModelConfiguration.from_connection(
    aoai_connection, 
    model_name="text-embedding-ada-002",
    deployment_name="text-embedding-ada-002") # verify if your deployment name is same as model name

## OR you can connect using API Key based connections 
from azure.ai.ml.entities import IndexModelConfiguration
## aoai connections - API Key
aoai_connection = client.connections.get("<your_aoai_connection>", populate_secrets=True)
embeddings_model_config = IndexModelConfiguration.from_connection(
    aoai_connection, 
    model_name="text-embedding-ada-002",
    deployment_name="text-embedding-ada-002")

Você pode se conectar ao modelo de inserção implantado no seu projeto do estúdio de IA (modelos que não são OpenAI do Azure) usando a conexão sem servidor.

from azure.ai.ml.entities import IndexModelConfiguration
serverless_connection = client.connections.get("<my_embedding_model_severless_connection_name>")
embeddings_model_config = IndexModelConfiguration.from_connection(cohere_serverless_connection)

Selecionar dados de entrada para criar o índice

Você pode criar o índice com base nos seguintes tipos de entradas:

  • Pastas e arquivos locais
  • Repositórios GitHub
  • Armazenamento do Azure

Podemos usar o exemplo de código a seguir para usar qualquer uma dessas fontes e configurar nosso input_source:

# Local source
from azure.ai.ml.entities import LocalSource

input_source=LocalSource(input_data="<path-to-your-local-files>")

# Github repository
from azure.ai.ml.entities import GitSource

input_source=GitSource(
    git_url="https://github.com/rust-lang/book.git", # connecting to the RUST repo as an example
    git_branch_name="main", 
    git_connection_id="")

# Azure Storage
input_source_subscription = "<subscription>"
input_source_resource_group = "<resource_group>"
input_source_workspace = "<workspace>"
input_source_datastore = "<datastore_name>"
input_source_path = "path"

input_source = f"azureml://subscriptions/{input_source_subscription}/resourcegroups/{input_source_resource_group}/workspaces/{input_source_workspace}/datastores/{input_source_datastore}/paths/{input_source_path}"

Criar o índice na nuvem

Agora, podemos criar o índice usando ai_search_connection, embeddings_model_config e input_source. Nós usamos a função build_index. Se você estiver usando uma URL de Armazenamento do Microsoft Azure como fonte de entrada, também precisará fornecer um UserIdentityConfiguration.

# from azure.ai.ml.entities.credentials import UserIdentityConfiguration # user specified identity used to access the data. Required when using an azure storage URL
from azure.ai.ml.entities import AzureAISearchConfig

client.indexes.build_index(
    name="<index_name>", # name of your index
    embeddings_model_config=embeddings_model_config, 
    input_source=input_source, 
    # input_source_credential=UserIdentityConfiguration(), # user specified identity used to access the data. Required when using an azure storage URL
    index_config=AzureAISearchConfig(
        ai_search_index_name="<index_name>",  # the name of the index store in AI search service
        ai_search_connection_id=ai_search_connection.id, 
    ),
    tokens_per_chunk = 800, # Optional field - Maximum number of tokens per chunk
    token_overlap_across_chunks = 0, # Optional field - Number of tokens to overlap between chunks
)

Dependendo do tamanho dos dados de origem de entrada, as etapas acima podem demorar um pouco para serem concluídas. Depois que o trabalho for concluído, você poderá recuperar o objeto do índice.

my_index=client.indexes.get(name="<index_name>", label="latest")

Como consumir um índice registrado do seu projeto

Para consumir um índice registrado do seu projeto, você precisa se conectar ao projeto e recuperar o índice. O índice recuperado pode ser usado como um recuperador langhcain para consumi-lo. Você pode se conectar ao projeto com um client, conforme mostrado aqui.

from promptflow.rag import get_langchain_retriever_from_index

my_index=client.indexes.get(
    name="<registered_index_name>", 
    label="latest")

index_langchain_retriever=get_langchain_retriever_from_index(my_index.path)
index_langchain_retriever.get_relevant_documents("<your search query>")

Uma função de perguntas e respostas para usar o índice

Nós vimos como criar um índice localmente ou na nuvem. Usando esse índice, criamos uma função QnA que aceita uma pergunta do usuário e fornece uma resposta dos dados do índice. Primeiro, vamos obter o índice como um langchain_retriever, conforme mostrado aqui. Agora, usamos retriever em nossa função. Essa função usa o LLM conforme definido no construtor AzureChatOpenAI. Ela usa o índice como um langchain_retriever para consultar os dados. Criamos um modelo de prompt que aceita um contexto e uma pergunta. Usamos o RetrievalQA.from_chain_type do langchains para juntar tudo isso e obter as respostas.

def qna(question: str, temperature: float = 0.0, prompt_template: object = None) -> str:
    from langchain import PromptTemplate
    from langchain.chains import RetrievalQA
    from langchain_openai import AzureChatOpenAI

    llm = AzureChatOpenAI(
        openai_api_version="2023-06-01-preview",
        api_key="<your-azure-openai-api-key>",
        azure_endpoint="https://<your-azure-openai-service>.openai.azure.com/",
        azure_deployment="<your-chat-model-deployment>", # verify the model name and deployment name
        temperature=temperature,
    )

    template = """
    System:
    You are an AI assistant helping users answer questions given a specific context.
    Use the following pieces of context to answer the questions as completely, 
    correctly, and concisely as possible.
    Your answer should only come from the context. Don't try to make up an answer.
    Do not add documentation reference in the response.

    {context}

    ---

    Question: {question}

    Answer:"
    """
    prompt_template = PromptTemplate(template=template, input_variables=["context", "question"])

    qa = RetrievalQA.from_chain_type(
        llm=llm,
        chain_type="stuff",
        retriever=index_langchain_retriever,
        return_source_documents=True,
        chain_type_kwargs={
            "prompt": prompt_template,
        },
    )

    response = qa(question)

    return {
        "question": response["query"],
        "answer": response["result"],
        "context": "\n\n".join([doc.page_content for doc in response["source_documents"]]),
    }

Vamos fazer uma pergunta para garantir que tenhamos uma resposta.

result = qna("<your question>")
print(result["answer"])