Compartir vía


Procedimiento para crear y consumir un índice mediante código

Importante

Los elementos marcados (versión preliminar) en este artículo se encuentran actualmente en versión preliminar pública. Esta versión preliminar se ofrece sin acuerdo de nivel de servicio y no se recomienda para las cargas de trabajo de producción. Es posible que algunas características no sean compatibles o que tengan sus funcionalidades limitadas. Para más información, consulte Términos de uso complementarios de las Versiones Preliminares de Microsoft Azure.

En este artículo, aprenderá a crear un índice y a consumirlo a partir del código. Para crear un índice localmente, usamos el paquete promptflow-rag. Para crear un índice remoto en la nube, usamos el paquete azure-ai-ml. Consumimos los índices mediante langchain.

Requisitos previos

Debe disponer de lo siguiente:

  • Un centro de conectividad y proyecto de AI Studio.

  • Una conexión del servicio de Búsqueda de Azure AI para indizar los datos del producto y del cliente de ejemplo. Si no tiene un servicio de Búsqueda de Azure AI, puede crear uno desde Azure Portal o ver las instrucciones aquí.

  • Modelos para insertar:

    • Puede usar un modelo de inserción ada-002 de Azure OpenAI. Las instrucciones para implementar se pueden encontrar aquí.
    • O bien, puede usar cualquier otro modelo de inserción implementado en el proyecto de AI Studio. En este ejemplo se usa la inserción multilingüe de Cohere. Las instrucciones para implementar este modelo se pueden encontrar aquí.

Compilación y consumo local de un índice

Podemos compilar y consumir un índice localmente.

Paquetes necesarios para las operaciones de índice local

Instale los siguientes paquetes necesarios para la creación de índices locales.

pip install promptflow-rag langchain langchain-openai

Configuración de la búsqueda de IA para uso local

Usamos Búsqueda de Azure AI como almacén de índices. Para empezar, podemos configurar el servicio Búsqueda de Azure AI mediante el código siguiente:

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"

Creación de un índice local mediante inserciones de Azure OpenAI

Para crear un índice que use inserciones de Azure OpenAI, se configuran variables de entorno para conectarse al 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/"

Ahora compilemos el índice mediante la función 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
)

El código anterior crea un índice localmente. Usa variables de entorno para obtener el servicio de AI Search y también para conectarse al modelo de inserción de Azure OpenAI.

Compilación de un índice localmente mediante otros modelos de inserción implementados en el proyecto de AI Studio

Para crear un índice que use un modelo de inserción implementado en el proyecto de AI Studio, configuramos la conexión al modelo mediante un ConnectionConfig como se muestra a continuación. El subscription, resource_group y workspace hace referencia al proyecto donde está instalado el modelo de inserción. El connection_name hace referencia al nombre de conexión del modelo, que se puede encontrar en la página de configuración del proyecto de Inteligencia artificial de Studio.

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>"
    )

Ahora crearemos el índice mediante la función 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
)

El código anterior crea un índice localmente. Usa variables de entorno para obtener el servicio Búsqueda de Azure AI y la configuración de conexión para conectarse al modelo de inserción.

Consumo de un índice local

El índice local creado se puede usar como un recuperador de langchain para consumirlo para las consultas de búsqueda.

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>")

Registro del índice en el proyecto de AI Studio (opcional)

Opcionalmente, puede registrar el índice en el proyecto de AI Studio para que usted u otros usuarios que tengan acceso al proyecto puedan usarlo desde la nube. Antes de continuar, instale los paquetes necesarios para las operaciones remotas.

Conexión al proyecto

# 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>"
    )

Los objetos subscription, resource_group y workspace del código anterior hacen referencia al proyecto al que quiere conectarse.

Registro del í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")
          )

Nota:

Las variables de entorno están diseñadas para su comodidad en un entorno local. Sin embargo, si registra un índice local creado mediante variables de entorno, es posible que el índice no funcione según lo previsto porque los secretos de las variables de entorno no se transferirán al índice de nube. Para solucionar este problema, puede usar un ConnectionConfig o connection_id para crear un índice local antes de registrarse.

Creación de un índice (de forma remota) en el proyecto de AI Studio

Creamos un índice en la nube en el proyecto de AI Studio.

Paquetes necesarios para las operaciones de índice remoto

Instale los siguientes paquetes necesarios para la creación remota de índices.

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

Conexión al proyecto de AI Studio

Para empezar, nos conectamos al proyecto. Los objetos subscription, resource_group y workspace del siguiente código hacen referencia al proyecto al que quiere conectarse.

# 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>"
    )

Obtención de la conexión del servicio Búsqueda de Azure AI

Este proyecto debe tener una conexión con el servicio Búsqueda de Azure AI. Recuperamos los detalles del proyecto.

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

Conexión a los modelos de inserción

Puede conectarse a Azure OpenAI mediante conexiones de Microsoft Entra ID o conexiones basadas en claves 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")

Puede conectarse al modelo de inserción implementado en el proyecto de AI Studio (modelos que no son de Azure OpenAI) mediante la conexión sin 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)

Selección de datos de entrada para compilar el índice

Puede compilar el índice a partir de los siguientes tipos de entradas:

  • Archivos y carpetas locales
  • Repositorios de GitHub
  • Azure Storage

Podemos usar el ejemplo de código siguiente para emplear cualquiera de estos orígenes y configurar nuestro 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}"

Compilación del índice en la nube

Ahora podemos compilar el índice mediante ai_search_connection, embeddings_model_config y input_source. Usamos la función build_index. Si usa una dirección URL de Azure Storage como origen de entrada, también debe proporcionar un 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
)

En función del tamaño de los datos de origen de entrada, los pasos anteriores pueden tardar algún tiempo en completarse. Una vez completado el trabajo, puede recuperar el objeto de índice.

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

Consumo de un índice registrado del proyecto

Para consumir un índice registrado del proyecto, debe conectarse al proyecto y recuperar el índice. El índice recuperado se puede usar como un recuperador de langchain para su consumo. Puede conectarse al proyecto con un elemento client como se muestra aquí.

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>")

Función de pregunta y respuesta para usar el índice

Hemos visto cómo se crea un índice localmente o en la nube. Con este índice, creamos una función de QnA que acepta una pregunta de usuario y proporciona una respuesta de los datos del índice. En primer lugar, vamos a obtener el índice como elemento langchain_retriever como se muestra aquí. Ahora usamos este retriever en nuestra función. Esta función usa el LLM tal como se define en el constructor AzureChatOpenAI. Usa el índice como langchain_retriever para consultar los datos. Creamos una plantilla de aviso que acepta un contexto y una pregunta. Usamos el RetrievalQA.from_chain_type de langchain para reunir todos estos elementos y obtener las respuestas.

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"]]),
    }

Formulemos una pregunta para asegurarnos de que obtenemos una respuesta.

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