Поделиться через


Руководство. Создание конвейера индексирования для RAG в поиске ИИ Azure

Узнайте, как создать конвейер автоматического индексирования для решения RAG в службе "Поиск ИИ Azure". Автоматизация индексирования — это индексатор, который управляет индексированием и выполнением набора навыков, предоставляя интегрированные блоки данных и векторизацию на однократной или повторяющейся основе для добавочных обновлений.

Изучив это руководство, вы:

  • Укажите схему индекса из предыдущего руководства
  • Создание подключения к источнику данных
  • Создать индексатор
  • Создание набора навыков, который блокирует, векторизирует и распознает сущности
  • Запуск индексатора и проверки результатов

Если у вас нет подписки Azure, создайте бесплатную учетную запись, прежде чем приступить к работе.

Совет

Мастер импорта и векторизации данных можно использовать для создания конвейера. Ознакомьтесь с некоторыми краткими руководствами: поиск изображений и векторный поиск.

Необходимые компоненты

  • Visual Studio Code с расширением Python и пакетом Jupyter. Дополнительные сведения см. в статье Python в Visual Studio Code.

  • служба хранилища Azure учетной записи общего назначения. Это упражнение отправляет PDF-файлы в хранилище BLOB-объектов для автоматического индексирования.

  • Поиск ИИ Azure, уровень "Базовый" или выше для управляемого удостоверения и семантического ранжирования. Выберите регион, которым предоставлен общий доступ к Azure OpenAI и Службам искусственного интеллекта Azure.

  • Azure OpenAI с развертыванием текстового внедрения-3 в том же регионе, что и поиск по искусственному интеллекту Azure. Дополнительные сведения о внедрении моделей, используемых в решениях RAG, см. в статье "Выбор моделей внедрения для RAG" в службе "Поиск ИИ Azure".

  • Учетная запись службы искусственного интеллекта Azure в том же регионе, что и служба поиска ИИ Azure. Этот ресурс используется для навыка распознавания сущностей, который обнаруживает расположения в содержимом.

Скачивание примера приложения

Скачайте записную книжку Jupyter из GitHub, чтобы отправить запросы в поиск ИИ Azure. Дополнительные сведения см. в статье "Скачивание файлов с GitHub".

Укажите схему индекса

Откройте или создайте записную книжку Jupyter (.ipynb) в Visual Studio Code, чтобы содержать скрипты, составляющие конвейер. Начальные шаги по установке пакетов и сбор переменных для подключений. После выполнения действий по настройке вы будете готовы начать работу с компонентами конвейера индексирования.

Начнем с схемы индекса из предыдущего руководства. Он организован вокруг векторизованных и невекторизованных блоков. Он содержит поле, в которое хранится содержимое locations , созданное СИ, созданное набором навыков.

from azure.identity import DefaultAzureCredential
from azure.identity import get_bearer_token_provider
from azure.search.documents.indexes import SearchIndexClient
from azure.search.documents.indexes.models import (
    SearchField,
    SearchFieldDataType,
    VectorSearch,
    HnswAlgorithmConfiguration,
    VectorSearchProfile,
    AzureOpenAIVectorizer,
    AzureOpenAIVectorizerParameters,
    SearchIndex
)

credential = DefaultAzureCredential()

# Create a search index  
index_name = "py-rag-tutorial-idx"
index_client = SearchIndexClient(endpoint=AZURE_SEARCH_SERVICE, credential=credential)  
fields = [
    SearchField(name="parent_id", type=SearchFieldDataType.String),  
    SearchField(name="title", type=SearchFieldDataType.String),
    SearchField(name="locations", type=SearchFieldDataType.Collection(SearchFieldDataType.String), filterable=True),
    SearchField(name="chunk_id", type=SearchFieldDataType.String, key=True, sortable=True, filterable=True, facetable=True, analyzer_name="keyword"),  
    SearchField(name="chunk", type=SearchFieldDataType.String, sortable=False, filterable=False, facetable=False),  
    SearchField(name="text_vector", type=SearchFieldDataType.Collection(SearchFieldDataType.Single), vector_search_dimensions=1024, vector_search_profile_name="myHnswProfile")
    ]  
  
# Configure the vector search configuration  
vector_search = VectorSearch(  
    algorithms=[  
        HnswAlgorithmConfiguration(name="myHnsw"),
    ],  
    profiles=[  
        VectorSearchProfile(  
            name="myHnswProfile",  
            algorithm_configuration_name="myHnsw",  
            vectorizer_name="myOpenAI",  
        )
    ],  
    vectorizers=[  
        AzureOpenAIVectorizer(  
            vectorizer_name="myOpenAI",  
            kind="azureOpenAI",  
            parameters=AzureOpenAIVectorizerParameters(  
                resource_url=AZURE_OPENAI_ACCOUNT,  
                deployment_name="text-embedding-3-large",
                model_name="text-embedding-3-large"
            ),
        ),  
    ], 
)  
  
# Create the search index
index = SearchIndex(name=index_name, fields=fields, vector_search=vector_search)  
result = index_client.create_or_update_index(index)  
print(f"{result.name} created")  

Создание подключения к источнику данных

На этом шаге настройте образец данных и подключение к Хранилище BLOB-объектов Azure. Индексатор извлекает PDF-файлы из контейнера. Вы создаете контейнер и отправляете файлы на этом шаге.

Исходная электронная книга имеет большой размер, более 100 страниц и 35 МБ. Мы разбили его на небольшие PDF-файлы, по одному на страницу текста, чтобы оставаться под ограничением документа для индексаторов размером 16 МБ на вызов API, а также ограничения данных обогащения ИИ. Для простоты мы опустим векторизацию изображений для этого упражнения.

  1. Войдите в портал Azure и найдите учетную запись служба хранилища Azure.

  2. Создайте контейнер и отправьте PDF-файлы из earth_book_2019_text_pages.

  3. Убедитесь, что служба поиска ИИ Azure имеет разрешения чтения данных BLOB-объектов хранилища для ресурса.

  4. Затем в Visual Studio Code определите источник данных индексатора, предоставляющий сведения о подключении во время индексирования.

    from azure.search.documents.indexes import SearchIndexerClient
    from azure.search.documents.indexes.models import (
        SearchIndexerDataContainer,
        SearchIndexerDataSourceConnection
    )
    
    # Create a data source 
    indexer_client = SearchIndexerClient(endpoint=AZURE_SEARCH_SERVICE, credential=credential)
    container = SearchIndexerDataContainer(name="nasa-ebooks-pdfs-all")
    data_source_connection = SearchIndexerDataSourceConnection(
        name="py-rag-tutorial-ds",
        type="azureblob",
        connection_string=AZURE_STORAGE_CONNECTION,
        container=container
    )
    data_source = indexer_client.create_or_update_data_source_connection(data_source_connection)
    
    print(f"Data source '{data_source.name}' created or updated")
    

Если вы настроили управляемое удостоверение для поиска ИИ Azure для подключения, строка подключения включает ResourceId= суффикс. Он должен выглядеть примерно так: "ResourceId=/subscriptions/FAKE-SUBCRIPTION=ID/resourceGroups/FAKE-RESOURCE-GROUP/providers/Microsoft.Storage/storageAccounts/FAKE-ACCOUNT;"

Создание набора навыков

Навыки являются основой для интеграции блокирования и векторизации данных. Как минимум, необходимо, чтобы навык разделения текста блокировал содержимое и навык внедрения, который создает векторные представления фрагментированного содержимого.

В этом наборе навыков дополнительный навык используется для создания структурированных данных в индексе. Навык распознавания сущностей используется для определения расположений, которые могут варьироваться от соответствующих имен до универсальных ссылок, таких как "океан" или "гора". Структурированные данные предоставляют дополнительные возможности для создания интересных запросов и повышения релевантности.

Требуется AZURE_AI_MULTISERVICE_KEY, даже если вы используете управление доступом на основе ролей. Поиск по искусственному интеллекту Azure использует ключ для выставления счетов и требуется, если ваши рабочие нагрузки не остаются в пределах бесплатного ограничения. Вы также можете подключиться без ключа, если вы используете самый последний api предварительной версии или бета-версии пакетов. Дополнительные сведения см. в статье "Присоединение ресурса с несколькими службами ИИ Azure к набору навыков".

from azure.search.documents.indexes.models import (
    SplitSkill,
    InputFieldMappingEntry,
    OutputFieldMappingEntry,
    AzureOpenAIEmbeddingSkill,
    EntityRecognitionSkill,
    SearchIndexerIndexProjection,
    SearchIndexerIndexProjectionSelector,
    SearchIndexerIndexProjectionsParameters,
    IndexProjectionMode,
    SearchIndexerSkillset,
    CognitiveServicesAccountKey
)

# Create a skillset  
skillset_name = "py-rag-tutorial-ss"

split_skill = SplitSkill(  
    description="Split skill to chunk documents",  
    text_split_mode="pages",  
    context="/document",  
    maximum_page_length=2000,  
    page_overlap_length=500,  
    inputs=[  
        InputFieldMappingEntry(name="text", source="/document/content"),  
    ],  
    outputs=[  
        OutputFieldMappingEntry(name="textItems", target_name="pages")  
    ],  
)  
  
embedding_skill = AzureOpenAIEmbeddingSkill(  
    description="Skill to generate embeddings via Azure OpenAI",  
    context="/document/pages/*",  
    resource_url=AZURE_OPENAI_ACCOUNT,  
    deployment_name="text-embedding-3-large",  
    model_name="text-embedding-3-large",
    dimensions=1024,
    inputs=[  
        InputFieldMappingEntry(name="text", source="/document/pages/*"),  
    ],  
    outputs=[  
        OutputFieldMappingEntry(name="embedding", target_name="text_vector")  
    ],  
)

entity_skill = EntityRecognitionSkill(
    description="Skill to recognize entities in text",
    context="/document/pages/*",
    categories=["Location"],
    default_language_code="en",
    inputs=[
        InputFieldMappingEntry(name="text", source="/document/pages/*")
    ],
    outputs=[
        OutputFieldMappingEntry(name="locations", target_name="locations")
    ]
)
  
index_projections = SearchIndexerIndexProjection(  
    selectors=[  
        SearchIndexerIndexProjectionSelector(  
            target_index_name=index_name,  
            parent_key_field_name="parent_id",  
            source_context="/document/pages/*",  
            mappings=[  
                InputFieldMappingEntry(name="chunk", source="/document/pages/*"),  
                InputFieldMappingEntry(name="text_vector", source="/document/pages/*/text_vector"),
                InputFieldMappingEntry(name="locations", source="/document/pages/*/locations"),  
                InputFieldMappingEntry(name="title", source="/document/metadata_storage_name"),  
            ],  
        ),  
    ],  
    parameters=SearchIndexerIndexProjectionsParameters(  
        projection_mode=IndexProjectionMode.SKIP_INDEXING_PARENT_DOCUMENTS  
    ),  
) 

cognitive_services_account = CognitiveServicesAccountKey(key=AZURE_AI_MULTISERVICE_KEY)

skills = [split_skill, embedding_skill, entity_skill]

skillset = SearchIndexerSkillset(  
    name=skillset_name,  
    description="Skillset to chunk documents and generating embeddings",  
    skills=skills,  
    index_projection=index_projections,
    cognitive_services_account=cognitive_services_account
)
  
client = SearchIndexerClient(endpoint=AZURE_SEARCH_SERVICE, credential=credential)  
client.create_or_update_skillset(skillset)  
print(f"{skillset.name} created")

Создание и запуск индексатора

Индексаторы — это компонент, который задает все процессы в движении. Индексатор можно создать в отключенном состоянии, но по умолчанию он выполняется немедленно. В этом руководстве создайте и запустите индексатор, чтобы получить данные из хранилища BLOB-объектов, выполнить навыки, включая фрагментирование и векторизацию, а также загрузить индекс.

Индексатор занимает несколько минут. По завершении вы можете перейти к последнему шагу: запрос индекса.

from azure.search.documents.indexes.models import (
    SearchIndexer,
    FieldMapping
)

# Create an indexer  
indexer_name = "py-rag-tutorial-idxr" 

indexer_parameters = None

indexer = SearchIndexer(  
    name=indexer_name,  
    description="Indexer to index documents and generate embeddings",  
    skillset_name=skillset_name,  
    target_index_name=index_name,  
    data_source_name=data_source.name,
    # Map the metadata_storage_name field to the title field in the index to display the PDF title in the search results  
    field_mappings=[FieldMapping(source_field_name="metadata_storage_name", target_field_name="title")],
    parameters=indexer_parameters
)  

# Create and run the indexer  
indexer_client = SearchIndexerClient(endpoint=AZURE_SEARCH_SERVICE, credential=credential)  
indexer_result = indexer_client.create_or_update_indexer(indexer)  

print(f' {indexer_name} is created and running. Give the indexer a few minutes before running a query.')    

Выполнение запроса для проверки результатов

Отправьте запрос, чтобы убедиться, что индекс работает. Этот запрос преобразует текстовую строку "what's NASA's website?" в вектор для поиска вектора. Результаты состоят из полей в инструкции select, некоторые из которых печатаются в виде выходных данных.

На данный момент нет чата или создания искусственного интеллекта. Результаты — это подробное содержимое из индекса поиска.

from azure.search.documents import SearchClient
from azure.search.documents.models import VectorizableTextQuery

# Vector Search using text-to-vector conversion of the querystring
query = "what's NASA's website?"  

search_client = SearchClient(endpoint=AZURE_SEARCH_SERVICE, credential=credential, index_name=index_name)
vector_query = VectorizableTextQuery(text=query, k_nearest_neighbors=50, fields="text_vector")
  
results = search_client.search(  
    search_text=query,  
    vector_queries= [vector_query],
    select=["chunk"],
    top=1
)  
  
for result in results:  
    print(f"Score: {result['@search.score']}")
    print(f"Chunk: {result['chunk']}")

Этот запрос возвращает одно совпадение (top=1), состоящее из одного блока, определенного поисковой системой, наиболее релевантной. Результаты запроса должны выглядеть примерно так:

Score: 0.01666666753590107
Chunk: national Aeronautics and Space Administration

earth Science

NASA Headquarters 

300 E Street SW 

Washington, DC 20546

www.nasa.gov

np-2018-05-2546-hQ

Попробуйте несколько дополнительных запросов, чтобы получить представление о том, что поисковая система возвращает напрямую, чтобы сравнить его с ответом с поддержкой LLM. Повторно запустите предыдущий скрипт с помощью этого запроса и "patagonia geography" задайте top значение 3, чтобы вернуть несколько ответов.

Результаты этого второго запроса должны выглядеть так же, как и в следующих результатах, которые легко редактируются для сотрясения. Выходные данные копируются из записной книжки, которая усечена ответ на то, что вы видите в этом примере. Вы можете развернуть выходные данные ячейки, чтобы просмотреть полный ответ.

Score: 0.03306011110544205
Chunk: 

Swirling Bloom off Patagonia
Argentina

Interesting art often springs out of the convergence of different ideas and influences. 
And so it is with nature. 

Off the coast of Argentina, two strong ocean currents converge and often stir up a colorful 
brew, as shown in this Aqua image from 

December 2010. 

This milky green and blue bloom formed on the continental shelf off of Patagonia, where warmer, 
saltier waters from the subtropics 

meet colder, fresher waters flowing from the south. Where these currents collide, turbulent 
eddies and swirls form, pulling nutrients 

up from the deep ocean. The nearby Rio de la Plata also deposits nitrogen- and iron-laden 
sediment into the sea. Add in some 
...

while others terminate in water. The San Rafael and San Quintín glaciers (shown at the right) 
are the icefield’s largest. Both have 

been receding rapidly in the past 30 years.

В этом примере проще определить, как возвращаются блоки, а также как ключевые слова и поиск сходства определяют верхние совпадения. Этот конкретный блок определенно содержит сведения о Патагонии и географии, но это не совсем относится к запросу. Семантический рангировщик будет способствовать более релевантным блокам для лучшего ответа, но в качестве следующего шага давайте посмотрим, как подключить поиск ИИ Azure к LLM для поиска беседы.

Следующий шаг