doc/AI/RAG2/eRAG/Tyler/3_1.md
2025-10-21 17:40:17 +03:00

49 KiB
Raw Blame History

Глава 3 (начало)

Глава 3: "Загрузка в поисковый сервис (Search service ingestion)".


===== Страница 42 =====

38

3 Загрузка в поисковый сервис

Эта глава раскрывает • Подготовку структурированных данных, таких как SQL-записи, для загрузки в поисковую систему • Создание поисковой системы и загрузку обработанных записей • Создание гибридной функции поиска для поиска записей по векторам и ключевым словам • Оценку, какие поисковые сервисы использовать, а каких избегать

Добро пожаловать в Главу 3! Давайте поговорим о чем-то, что может прозвучать немного противоречиво в сегодняшнем хайп-цикле вокруг ИИ:

Вам не обязательно использовать векторы и эмбеддинги для RAG.

Богохульство, скажете вы. Вздерните его на стропила, гневно кричите вы. Позвольте мне объяснить:

В RAG ваша задача — не найти похожие векторы. Ваша задача — накормить языковую модель правильным текстом. Вы можете найти этот текст как вам угодно: если у вас есть 30-летний SQL-поиск, который каждый раз дает правильный ответ, используйте его для извлечения контекста для вашего RAG. Если быстрый поиск в Google дает вам всю необходимую информацию, тогда используйте Google Search API в вашем пайплайне RAG. Я призываю вас мыслить нестандартно: каждое руководство по RAG, которое я когда-либо видел на YouTube, начинается с «Первый шаг в RAG — это построить векторную базу данных…». Я кричу на экран: нет, нет, НЕТ! Не просто предполагайте, что векторная база данных будет лучшим способом для вашей системы RAG. Вы можете выбрать неправильный инструмент для работы, подобно попытке чистить рыбу молотком. То, как вы ищете свои данные в вашей системе RAG, должно быть лучшим, самым быстрым и наиболее точным способом для ВАШИХ данных, независимо от того, какую форму они принимают.

===== Страница 43 =====

Если, после испытания множества различных вариантов, вы решите, что векторные базы данных лучше всего подходят для вашей конкретной ситуации, это нормально. Но не слепо принимайте, что векторные базы данных — лучший путь: когда дело доходит до извлечения правильного текста, одного лишь векторного поиска часто недостаточно. Даже лучшие модели эмбеддингов сегодня борются с извлечением правильного контекста более чем в 70% случаев. Это оставляет огромный 30% зазор, где ваша модель уверенно галлюцинирует на основе неправильного ввода.

(Источник: https://huggingface.co/spaces/mteb/leaderboard, фильтр по задаче, Retrieval.)

Текстовый поиск, с другой стороны, существует десятилетиями. Он был создан для решения именно этой проблемы: поиска релевантных документов на основе беспорядочного, неоднозначного человеческого языка. Булева логика, фильтры, нечеткое совпадение, устойчивость к опечаткам, усиление фраз — все то, что поисковые системы делают годами. И они стали действительно хороши в этом.

В нашем случае мы попробовали использовать векторный поиск Azure CosmosDB для MongoDB. Мы не могли получить правильный результат даже в топ-100 попаданий. Это не редкая случайность — это симптом более глубокой проблемы. Большинство реализаций RAG не работают в масштабе (по некоторым оценкам, до 80%), потому что они слишком сильно полагаются на векторный поиск и не используют полностью гибкий текстовый поиск.

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

Или… вы могли бы пропустить все это и просто использовать современную поисковую систему.

Вот почему эта глава посвящена Azure AI Search. Это поисковая платформа как услуга (search-as-a-service), которая дает вам полнофункциональный поиск по ключевым словам, фильтры, семантическое ранжирование и, да — поддержку векторов, когда вы этого хотите. Вам не нужно склеивать вместе агентские пайплайны переранжирования или накладывать пять фильтров, чтобы получить хоть сколько-нибудь приличный ответ. Вы просто загружаете свои данные, индексируете их и ищете.

Потому что в конце дня цель — не извлечь «наиболее похожий эмбеддинг». Цель — извлечь правильный отрывок текста.

Давайте построим что-то, что действительно работает. Просто для ясности, векторы — не злодеи, но они и не герои. Не полагайтесь на векторный поиск для решения всех ваших проблем.

Для начала мы загрузим несколько примеров SQL-записей, преобразуем их в строковые сводки для более удобного поиска и сохраним их в Azure AI Search. Она оптимизирована для гибридного поиска, сочетая традиционный поиск по ключевым словам с векторным поиском, и без усилий обрабатывает как структурированные (например, SQL-записи), так и неструктурированные данные (например, PDF-документы). На практике вы получаете нужные данные в первых нескольких результатах — часто в первом или втором — без громоздких компромиссов между скоростью или точностью, с которыми вы можете столкнуться в других местах. Мы пробовали много разных решений для поиска, и с тех пор, как мы начали использовать Azure AI Search, у нас не было никаких проблем с извлечением нужных данных. В остальной части этой главы, всякий раз, когда мы упоминаем «AI Search», мы конкретно имеем в виду сервис Azure AI Search.

===== Страница 44 =====

40

Вам может быть интересно, почему мы не предоставляем руководства для AWS, GCP или инструментов поиска с открытым исходным кодом. Ответ прост: я не использовал их в масштабе для RAG. Я не знаю об их производительности в реальных условиях в большой, требовательной среде. Фокус на том, что я лично тестировал под нагрузкой — Azure AI Search — и как этот подход надежно соответствовал нашим потребностям. Сейчас у нас более 50 миллионов записей, распределенных по 10 различным индексам AI Search. Обычно мы получаем ответы за 1-10 секунд, и, что наиболее важно, результаты всегда представляют собой именно ту информацию, которую мы ищем. Я не рекомендую вам использовать один search-as-a-service вместо другого, я просто сообщаю о том, что, как я обнаружил, работает. Мы покажем вам компоненты и продемонстрируем их с помощью Azure, но вы можете взять принципы, изученные в этой главе, и применить их к любому выбранному вами поисковому сервису, при условии, что он отлично справляется с поиском текста.

Некоторые другие альтернативы AI Search одинаково привлекательны. Например, Elasticsearch ценится за свою мощный API и открытый исходный код, хотя его сложность может сделать настройку и обслуживание более обременительными. Algolia обладает высокой производительностью и простым интерфейсом, но цена может быстро возрасти, если вы ограничены в бюджете. Amazon Kendra использует интеллектуальный, высокоточный корпоративный поиск, который seamlessly интегрируется в экосистему AWS, однако его цена может быть высокой для небольших команд. Amazon CloudSearch пытается уменьшить хлопоты, полностью управляя вашей поисковой инфраструктурой — правда, ценой отсутствия некоторых расширенных функций, которые предлагают другие сервисы. Наконец, Swiftype имеет более простой процесс интеграции и множество быстрых настроек, но он может быть не таким глубоким или многофункциональным, как некоторые из его более тяжеловесных аналогов. В конечном счете, ваш выбор должен отражать масштаб, сложность и ресурсные ограничения вашего проекта.

Так много вариантов, но как выбрать? Мой метод прост: я выбираю один единственный запрос и пробую его в нескольких различных вариантах. Какой бы вариант ни дал мне лучшие результаты, тот я и использую. То же самое касается агентов, хостинга и т.д.

Управление одним набором учетных данных Azure также представляет собой минимальные накладные расходы по сравнению с тем, что вы получите: опыт работы с системой, которая может выдерживать enterprise-нагрузки.

Учитывая все это, вам также может быть интересно, почему мы преобразуем SQL-записи в строковые сводки и загружаем их в Azure AI Search. Разве это не большое расточительство ресурсов? Разве мы не можем просто хранить наши данные в SQL-базе данных и искать таким образом? Отличные вопросы! Позвольте мне объяснить.

Короткий ответ заключается в том, что SQL-поиски, как правило, медленные и жесткие. Если у вас миллионы записей, SQL-запрос может занять 30 секунд или больше, чтобы вернуть результаты, что слишком долго в системе RAG, где пользователи ожидают быстрого ответа. Также существует проблема точного совпадения: SQL-запросы обычно требуют точных терминов или структурированных условий. Поиск «надувных игрушек для бассейна» не даст вам «наполненные воздухом веселые поплавки для воды», если база данных называет их именно так. Напротив, поисковый сервис, такой как Azure AI Search, может интерпретировать нечеткие или частичные совпадения и все равно поднимать релевантные записи благодаря своим интегрированным возможностям текстового поиска.

===== Страница 45 =====

41

Azure AI Search действительно имеет некоторые компромиссы. Его может быть сложно настроить (как вы увидите позже в этой главе), и его стоимость может значительно возрасти, как только ваши данные увеличатся. Он также не идеален для выполнения агрегатных запросов — таких как подсчет количества записей, содержащих слово «кошка» — что SQL обрабатывает более изящно с помощью GROUP BY и подобных операций. Вместо этого Azure AI Search превосходно справляется с быстрым поиском отдельных записей, таких как поиск описания одного продукта или обнаружение ссылки на продукт, зарытой в большом PDF-каталоге.

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

Взгляните на блок-схему на рисунке 3.1, чтобы увидеть, где мы сейчас находимся в общем пайплайне RAG: мы на этапе загрузки в поисковый сервис, который обведен пунктирным прямоугольником. В главе 3 вы узнали, как разбивать документы, эмбеддить их и хранить в векторной базе данных — подход, который может хорошо работать для определенных типов данных. В этой главе мы будем настраивать текстовый поисковый сервис.

  1. Введение
  2. Eval
  3. Загрузка в поисковый сервис
  4. Агенты для извлечения данных
  5. Развертывание, масштабирование и нагрузочное тестирование
  6. Отказ от ответственности и обратная связь
  7. Безопасность и управление

Построение системы RAG (Часть 1)

Развертывание и Улучшение (Часть 2)

  1. Мониторинг и дашборды
  2. Написание читаемого кода
  3. Разное дополнения

Поддержка (Часть 3)

Рисунок 3.1 Эта блок-схема показывает ключевые этапы пайплайна RAG. Основное внимание уделяется загрузке в поисковый сервис (пунктирный круг), где необработанные данные предварительно обрабатываются и эмбедятся перед добавлением в Azure AI Search для семантического поиска. Этот шаг соединяет переход от подготовки данных к извлечению.

Мы также будем работать со структурированными данными, в частности с SQL-записями. Наша примерная база данных содержит 500 записей, каждая из которых имеет название продукта, описание и некоторые технические характеристики. Чтобы следовать along, просто загрузите файл базы данных по этой ссылке:

https://github.com/Tylersuard/EnterpriseRAG/blob/main/Ch03/products.db

===== Страница 46 =====

42

Мы используем здесь sqlite3, потому что это просто и выполняет свою работу. Плюс, синтаксис sqlite3 достаточно близок к другим SQL-системам, поэтому код будет знаком, если вы привыкли к более крупной, enterprise-уровня базе данных.

Готовы нырнуть? Поехали.

Теперь мы настроим индекс Azure AI Search, чтобы мы могли обрабатывать наши примеры SQL-записей и быстро и точно искать по ним. Для начала вам понадобится учетная запись Azure. Если у вас ее еще нет, перейдите на портал Azure и зарегистрируйтесь (www.portal.azure.com). Не волнуйтесь, там есть бесплатный тариф, с которым вы можете экспериментировать. Как только вы войдете, перейдите к строке поиска на портале Azure, введите Azure AI Search и нажмите на появившийся значок. На открывшейся странице создайте новый поисковый сервис. Если у вас еще нет группы ресурсов, создайте ее и дайте ей имя — любое, что имеет для вас смысл. Давайте назовем ваш новый поисковый сервис что-то вроде «products-ai-search» (при условии, что это имя доступно) и выберите расположение близко к вам для лучшей производительности. Имейте в виду, что тарифы более высокого уровня могут стоить до 300 долларов в месяц. Если вы просто экспериментируете, лучше придерживаться бесплатного тарифа или не забудьте удалить сервис, когда закончите с этим руководством. После того как вы определились с настройками, просто нажмите «Создать» и дайте ему минуту на запуск.

Как только он будет готов, откройте сервис на портале Azure и создайте новый индекс. Давайте назовем его «product-search-index.» Вам нужно будет определить поля для этого индекса, включая «ProductName», «ProductDescription», «TechnicalSpecifications», «Manufacturer», «Summary» и «DateModified». Мы используем строки для всех них, отчасти потому, что Azure AI Search поддерживает несколько типов данных, но выход за пределы строк может усложниться. Например, если вы выберете int64 или float, вам придется конвертировать эти числа всякий раз, когда вы отправляете или извлекаете данные, что может быть хлопотнее, чем оно того стоит. Придерживаться строк keeps все проще, поэтому мы рекомендуем это, если вам абсолютно не нужно использовать определенные типы данных в вашем поисковом индексе. Первые четыре поля — ProductName, ProductDescription, TechnicalSpecifications и Manufacturer — будут поступать непосредственно из SQL-записей, которые вы загрузили ранее. Мы также объединим эти поля в одну строку под названием «Summary», что упрощает эмбеддинг всей записи. Наконец, добавьте поле «Vector» типа collection (Edm.Single), чтобы вы могли хранить эмбеддинги для каждой записи. Это дает вам лучшее из обоих миров: вы можете использовать как текстовый, так и векторный поиск для более гибкого и точного поиска.

===== Страница 47 =====

43

Вы увидите несколько различных опций для каждого поля при настройке вашего индекса. Если поле доступно для извлечения (retrievable), это означает, что когда вы выполняете поиск и получаете результаты, информация этого поля не будет скрыта. Для важных текстовых полей вы захотите оставить эту галочку включенной. Вы можете оставить ее выключенной для векторов, потому что, даже though векторы помогают вам искать, вы не обязательно хотите получать список из 1536 элементов в результатах поиска. Фильтруемое (Filterable) поле может быть использовано для включения или исключения записей во время поиска. Например, если продукт имеет поле типа «SOLD_OUT», вы можете установить это поле как фильтруемое, чтобы находить только записи, которые все еще доступны для продажи. Сортируемое (Sortable) поле позволяет вам упорядочивать результаты по этому полю. Например, вы можете захотеть отсортировать названия продуктов по алфавиту. Доступное для поиска (Searchable) поле — это то, по которому вы можете искать по ключевым словам, в то время как фасетное (Facetable) поле полезно, когда вы хотите группировать или подсчитывать результаты, например, выяснить, сколько продуктов принадлежит к определенной категории. Вы должны установить searchable в on для любых важных полей.

Для ProductName лучше включить retrievability, filterability, sortability и searchability, поскольку люди, вероятно, будут искать товары по имени. ProductDescription обычно просто должен быть retrievable и searchable, потому что это часто абзац или два, по которым вам не нужно фильтровать или сортировать. TechnicalSpecifications похож — обычно достаточно retrievable и searchable. Manufacturer, с другой стороны, должен быть filterable и sortable, чтобы пользователи могли сужать результаты до одного бренда или перечислять их все в алфавитном порядке. Мы также помечаем его как facetable, потому что вы, возможно, someday захотите подсчитать, сколько продуктов у каждого производителя. Summary может оставаться retrievable и searchable, поскольку это basically все-в-одном текстовое поле. DateModified должен быть filterable и sortable, чтобы вы могли находить самые новые или самые старые записи по мере необходимости.

Для поля «Vector» вы захотите установить размерность (dimensions) в 1536, чтобы они соответствовали эмбеддингам, которые мы будем генерировать с помощью моделей OpenAI. Мы выбираем 1536 измерений для оптимизации баланса между производительностью и эффективностью. Эмбеддинги с более высокой размерностью могут capture более nuanced семантические отношения, но также требуют больше вычислительных ресурсов. Обязательно отключите опцию retrievable, чтобы вам не приходилось иметь дело с массивным массивом из 1536 элементов при каждом поиске. Далее создайте профиль векторного поиска и выберите Exhaustive KNN с косинусным сходством (cosine similarity). Мы используем косинусное по двум причинам: во-первых, косинусное сходство используется для измерения сходства между двумя векторами эмбеддингов путем вычисления косинуса угла между ними. Этот подход фокусируется на направлении, а не на величине векторов, что делает его эффективным для оценки семантического сходства независимо от длины текста. Во-вторых, переключение на HNSW в Azure удваивает пространство, занимаемое вашим векторным индексом. Алгоритм Иерархического Навигируемого Малого Мира (HNSW) отлично подходит для быстрого поиска в огромных наборах данных, но он требует дополнительных структур данных в памяти для эффективного поиска. Мы просто работаем с небольшим набором данных прямо сейчас, поэтому мы будем использовать Exhaustive KNN, потому что он хорошо работает на небольших наборах данных без накладных расходов по памяти HNSW. После того как вы сохранили все эти настройки, ваш индекс должен быть готов. Будьте осторожны, потому что если вы сделаете единственную ошибку, Azure не позволит вам редактировать индекс позже, и вам придется начинать заново. Как только все настроено, ваш готовый индекс должен выглядеть как рисунок 3.2.

===== Страница 48 =====

44

Рисунок 3.2 Правильно настроенный индекс Azure AI Search. Убедитесь, что столбцы Retrievable, Filterable, Sortable, Facetable и Searchable установлены точно так, как показано на этом изображении.

Далее вам понадобятся ваши учетные данные для подключения к сервису Azure AI Search. Откройте ваш поисковый сервис, нажмите на «Настройки», а затем выберите «Ключи», чтобы найти ваш основной ключ администратора. После этого перейдите на страницу «Обзор», чтобы получить URL-адрес конечной точки (endpoint) вашего сервиса. Вы будете полагаться на эти две части информации, ваш ключ и конечную точку, при написании кода, который взаимодействует с Azure AI Search.

Рисунок 3.3 показывает, как загружать структурированные данные, такие как SQL-записи, в Azure AI Search. Процесс начинается с подключения к вашей SQL-базе данных, затем извлечения данных пакетами. Пакетное выполнение запросов намного эффективнее, чем попытка извлечь миллионы строк за один раз, и позволяет избежать узких мест, которые могли бы замедлить как вашу базу данных, так и вашу систему RAG. После извлечения каждого пакета вы суммируете каждую SQL-запись в текст, очищаете этот текст от странных символов и преобразуете его в вектор с помощью API эмбеддингов OpenAI. Как только у вас есть вектор, вы оборачиваете текст и вектор вместе в словарь и загружаете его в Azure AI Search. Если есть еще записи для обработки, вы продолжаете цикл; если нет, вы просто завершаете. Этот пайплайн гарантирует, что ваши структурированные данные полностью подготовлены для гибридного текстового и векторного поиска, делая запросы одновременно гибкими и быстрыми.

===== Страница 49 =====

45

Подключиться к SQL-базе данных

Извлечь записи пакетами

Преобразовать каждую запись в строку

Очистить строки-записи

Сгенерировать эмбеддинги строк-записей

Да

Больше записей?

Загрузить в поисковый сервис

Подготовить документы для загрузки

Конец

Рисунок 3.3 Рабочий процесс загрузки структурированных SQL-данных в Azure AI Search. Процесс начинается с подключения к SQL-базе данных и извлечения записей пакетами. Каждый пакет суммируется, очищается, эмбеддится и подготавливается как документы для загрузки. Пайплайн циклически обрабатывает оставшиеся записи, пока все данные не будут обработаны и загружены.

3.2.1 Настройка кода

Теперь мы можем погрузиться в код. Имея ваш индекс Azure AI Search готовым и ваши учетные данные под рукой, следующий шаг — настройка OpenAI для генерации эмбеддингов из ваших SQL-записей.

Сначала установите необходимые библиотеки:

pip install azure-core azure-search-documents openai

===== Страница 50 =====

46

В вашем локальном Git-репозитории (том же, что вы создали в Главе 2), откройте файл .env, который мы создали в главе 2. Затем добавьте в него следующее:

AI_SEARCH_ENDPOINT=<your search endpoint here>
AI_SEARCH_KEY=<your search key here>
AI_SEARCH_NAME=<the name of your index>

Теперь создайте новый файл с именем upload_sql_records_to_ai_search.py. В начале этого файла добавьте следующие импорты:

Листинг 3.1 Импорт необходимых библиотек

import os    #A
from azure.search.documents import SearchClient    #B
from azure.core.credentials import AzureKeyCredential    #C
from openai import OpenAI    #D
import sqlite3    #E
from dotenv import load_dotenv
load_dotenv()

#A Это позволит нам позже получить доступ к переменным окружения.
#B Это Python SDK от Azure для AI Search.
#C Помогает аутентифицировать запросы к AI Search.
#D Позволяет нам взаимодействовать с API OpenAI.
#E Мы будем использовать это, чтобы открыть наш загруженный файл базы данных.

И теперь мы настраиваем нашего поискового клиента и нашего openai-клиента, используя наши переменные окружения, которые мы определили ранее:

Листинг 3.2 Установите ваши учетные данные

openai_client = OpenAI(api_key=os.environ.get("OPENAI_API_KEY")) #A
search_client = SearchClient(
    endpoint=os.environ.get("AI_SEARCH_ENDPOINT"),    #B
    index_name=os.environ.get("AI_SEARCH_NAME"),    #B
    credential=AzureKeyCredential(os.environ.get("AI_SEARCH_KEY")) #C
)

#A Найдите это на странице вашего API Key на openai.com.
#B Найдите всю эту информацию на странице «Обзор» сервиса AI Search.
#C Найдите это во вкладке «Настройки» в вашем сервисе AI Search.

Отлично! Теперь ваш код готов к общению как с Azure AI Search, так и с API OpenAI.

3.2.2 Суммаризация одной SQL-записи

Теперь давайте посмотрим, как суммировать каждую SQL-запись, прежде чем мы преобразуем ее в текст. В Листинге 3.3 мы определяем функцию summarize_SQL_record(), которая объединяет ключевые поля в одну связную строку, что облегчает модели эмбеддинга capture ее смысл. Рисунок 3.4 показывает схему нашего общего процесса (обратите внимание, что эти эмбеддинги просто выдуманы для примера).

===== Страница 51 =====

47

(Место для Рисунка 3.4 - обычно это диаграмма процесса)

===== Страница 52 =====

48

SQL Запись: "Product Name": "Product XYZ" "Product Description": "A meat toaster" "Manufacturer": "Banana Angel inc." ...

Преобразовать

Строковая Сводка: "Product Name: Product XYZ. Product Description: A meat toaster. Manufacturer: Banana Angel inc. ..."

Эмбеддить

Вектор: [0.1234, 0.5678, 0.9012, -1.333, ...]

Рисунок 3.4 Преобразование SQL-записи в векторный эмбеддинг. Процесс начинается с преобразования необработанной SQL-записи в сводку на естественном языке. Эта сводка затем пропускается через модель эмбеддингов для генерации векторного представления, которое может быть использовано для векторного поиска.

===== Страница 53 =====

49

Листинг 3.3 Суммаризировать SQL-запись

def summarize_SQL_record(sql_record):
    record_summary_string = f""" 
    Product Name: {sql_record[1]} #A
    Product Description: {sql_record[2]} 
    Technical Specs: {sql_record[3]} 
    Manufacturer: {sql_record[4]}""" 
    print(f"Summarized record for {sql_record[1]}: {record_summary_string}")

    return record_summary_string

#A Мы преобразуем одну SQL-запись в текст, включая имена ее столбцов.

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

Листинг 3.4 Очистить строковую сводку

def clean_record_summary(record_summary):
    cleaned_record_summary = record_summary.replace("--", "") #A
    return cleaned_record_summary

#A Удалите любые ненужные символы. Другие примеры могут включать: *, ..., ⚠ и т.д.

Если позже вы заметите ошибки от модели эмбеддингов OpenAI, вам может потребоваться вернуться сюда и расширить функцию очистки, чтобы удалить дополнительные символы.

===== Страница 54 =====

50

3.2.3 Эмбеддить сводку записи

Далее давайте преобразуем очищенную текстовую сводку в эмбеддинг. Обязательно используйте 1536 измерений, чтобы это соответствовало размеру эмбеддинга, определенному в вашем индексе AI Search; в противном случае ваши векторы не будут совместимы. Как мы упоминали в Главе 3, эмбеддинги capture смысл слов в формате, который ИИ может интерпретировать. Мы используем text-embedding-3-small, потому что он обеспечивает хороший баланс между стоимостью и точностью. Хотя OpenAI предлагает и большую модель, мы обнаружили, что разница в производительности не оправдывает дополнительные расходы для большинства случаев использования. Мы также пробовали различные модели с открытым исходным кодом, донастроенные для конкретных доменов, но они, как правило, не соответствовали качеству более универсальных моделей OpenAI.

Листинг 3.5 Эмбеддить очищенную сводку записи

def embed_text(cleaned_record_summary):
    response = openai_client.embeddings.create(    #A
        input=cleaned_record_summary,    #B
        model="text-embedding-3-small",    #C
        dimensions=1536    #D
    )
    return response.data[0].embedding

#A Создание эмбеддингов просто: вы просто отправляете ваш текст в API и получаете список чисел обратно.
#B Ввод очищенной сводки, которую мы создали ранее.
#C Мы используем text-embedding-3-small.
#D Нам нужно использовать то же количество измерений, которое мы установили ранее в нашем индексе AI Search.

После того как каждая SQL-запись суммирована и преобразована в эмбеддинг, пришло время загрузить все в Azure AI Search. Сначала мы получаем текущую дату, чтобы сохранить ее вместе с записью — это может быть полезно позже, когда вы захотите увидеть, когда именно запись была добавлена в ваш индекс. Затем мы создаем словарь, соответствующий полям в вашем индексе AI Search, включая ID записи, текстовую сводку из summarize_sql_record() и эмбеддинг из embed_text(). В этой главе мы часто используем термины «вектор» и «эмбеддинг» взаимозаменяемо. После построения словаря мы вызываем search_client.merge_or_upload_documents(), который отправляет запись в Azure. Быстрый print statement помогает подтвердить, что каждая запись обрабатывается, вместо того чтобы оставить вас смотреть на мигающий курсор. Функция upload_to_AI_Search() ниже объединяет все эти шаги.

===== Страница 55 =====

51

Листинг 3.6 Загрузить запись и эмбеддинг в AI Search

from datetime import date

today = date.today()
date_string = today.strftime("%Y-%m-%d")

def upload_to_AI_Search(record, record_summary, embedded_summary):

    record_to_upload = {}

    record_to_upload["id"] = str(record[0]) #A
    record_to_upload["Summary"] = record_summary #B
    record_to_upload["Vector"] = embedded_summary #C
    record_to_upload["ProductName"] = record[1] #A
    record_to_upload["ProductDescription"] = record[2] #A
    record_to_upload["TechnicalSpecifications"] = record[3] #A
    record_to_upload["Manufacturer"] = record[4] #A
    record_to_upload["DateModified"] = date_string #D

    search_client.merge_or_upload_documents(documents=[record_to_upload])
    print(f"Record for {record[1]} processed and uploaded!") #E

#A Включите название продукта, описание продукта, технические характеристики и производителя в запись как отдельные поля. Мы делаем это, чтобы мы могли искать по производителю, по названию продукта и т.д.
#B Добавьте строку сводки в словарь записи.
#C Добавьте эмбеддинг в словарь записи.
#D Мы добавляем сегодняшнюю дату, чтобы мы могли отслеживать, когда эти записи были созданы в нашем поисковом индексе.
#E Загрузите документ в ваш индекс AI Search.

Здесь мы берем исходную SQL-запись, текстовую сводку этой записи и сгенерированный эмбеддинг и объединяем их в словарь с именем record_to_upload. Мы включаем каждое ключевое поле — ProductName, ProductDescription и так далее — чтобы мы могли легко искать по ним позже. Мы также добавляем текущую дату, чтобы отслеживать, когда каждая запись была добавлена в индекс. Наконец, merge_or_upload_documents() отправляет запись в Azure AI Search, и мы печатаем быстрое сообщение, подтверждающее, что она была обработана.