Основная навигация

Справится ли Postgres с вашим RAG-конвейером?

Мы протестировали подход pgai с опорой на базу данных, чтобы понять, где он упрощает работу с RAG, а где сложным нагрузкам всё ещё нужна дополнительная гибкость.

Краткое резюме

  • LLM могут одновременно «видеть» лишь ограниченный объём текста — контекстное окно. Для небольших задач этого достаточно, но при работе с базой знаний на тысячи страниц подход перестаёт работать. Даже при достаточном контекстном окне качество может снижаться из-за проблемы «иголки в стоге сена».

  • RAG (retrieval augmented generation, «генерация с дополнением результатами поиска») — распространённый подход: вы поддерживаете базу знаний (документы, вики, политики, расшифровки и т. п.), выполняете семантический поиск по запросу пользователя, с помощью эмбеддингов находите наиболее релевантные фрагменты, а затем передаёте их в LLM вместе с вопросом. Это ограничивает контекст модели и при правильной реализации может повысить качество ответов и сократить число галлюцинаций.

  • pgai — расширение Postgres с открытым исходным кодом и сопутствующие инструменты, которые помогают создавать процессы «ИИ-поиска» на базе проверенной СУБД PostgreSQL с открытым исходным кодом.

  • Основная идея — перенести больше стандартных этапов RAG на уровень базы данных (загрузка → разбиение → создание эмбеддингов → их синхронизация), а не использовать БД лишь как хранилище эмбеддингов.

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

Подход RAG

RAG можно реализовать множеством способов. Подробный разбор разных подходов читайте в статье «Практические примеры специализированных RAG-решений». Если важно качество, вариантов реализации оказывается неожиданно много, но типичный подход «по умолчанию» обычно выглядит так:

  1. Берём набор документов.

  2. Делим их на фрагменты. Это можно сделать множеством способов, например по абзацам или смысловым группам.

  3. Преобразуем каждый фрагмент в эмбеддинг.

  4. Сохраняем эмбеддинги в векторной базе данных (Pinecone, Milvus и т. п.) или в Postgres с помощью pgvector.

  5. При поступлении запроса ищем наиболее близкие фрагменты `и передаём их в LLM (и здесь тоже есть множество вариантов).

Во многих стеках этапы (1)–(3) выполняются вне базы данных — в коде приложения или конвейере обработки данных, а база в основном используется для:

  • хранения эмбеддингов

  • поиска по эмбеддингам

Назначение pgai

pgai — расширение Postgres с открытым исходным кодом, разработанное Timescale, которое стремится стереть эту границу.

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

  • Вы указываете, для какой таблицы или документов нужно создать эмбеддинги.

  • Вы выбираете модель эмбеддингов и стратегию разбиения на фрагменты.

  • Остальным управляет pgai, в том числе обновляет эмбеддинги при изменении исходных данных.

Преимущества выглядят привлекательно:

  • Меньше специализированного связующего кода, который нужно сопровождать.

  • Проще поддерживать актуальность эмбеддингов при изменении исходных документов.

  • Postgres/pgai управляет повторными попытками, ограничениями частоты запросов, сбойными заданиями и т. д.

Примечание для читателя: pgai включает pgvector — ещё одно очень популярное расширение Postgres для RAG. pgvector добавляет в Postgres хранение векторов и поиск по сходству, а pgai на этой основе автоматизирует этапы RAG-конвейера: разбиение на фрагменты, создание эмбеддингов и их актуализацию.

Первые впечатления от pgai

Что нам понравилось

1) Его легко запустить.

Базовый сценарий довольно прост:

  • Загрузите Docker-образы Timescale (база данных и рабочий процесс).

  • Укажите API-ключ поставщика эмбеддингов.

  • Выполните небольшой SQL-скрипт, чтобы объявить векторизатор: что преобразовывать в эмбеддинги, как делить данные на фрагменты и какую модель использовать.

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

2) Удобно выполнять весь конвейер «рядом» с базой данных.

pgai может загружать содержимое из таблиц и документы из таких хранилищ, как S3, а затем анализировать их, делить на фрагменты и создавать эмбеддинги. Он также поддерживает разные форматы текстовых документов, включая PDF, Markdown и другие.

Что показалось ограничивающим

1) Вы теряете значительную часть контроля, а в RAG он порой необходим.

RAG-системам с высоким качеством ответов часто требуются специализированные конвейеры, например:

  • особые правила разбиения на фрагменты — по заголовкам, страницам, репликам собеседников и т. д.;

  • разбиение на фрагменты с учётом метаданных — с сохранением названий разделов, временных меток, авторов и типа документа;

  • разные стратегии создания эмбеддингов для разных типов документов.

Во всём перечисленном pgai предлагает меньше гибкости.

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

Было бы здорово, если бы Timescale добавила более продвинутые стратегии разбиения, подобные представленным в библиотеках вроде Chonkie, а также поддержку таких передовых решений, как контекстный поиск Anthropic.

2) В приоритете текст, а не мультимодальность.

Многие интересные задачи RAG уже не ограничиваются текстом:

  • PDF-файлы с диаграммами;

  • снимки экрана и изображения;

  • аудиозаписи;

  • видеоклипы.

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

Если pgai со временем обеспечит сквозную поддержку мультимодальных моделей — загрузку, разбиение и создание эмбеддингов для крупных изображений, аудио и видео из S3 с надёжной синхронизацией, — это будет весомым преимуществом. Но сегодня он работает только с текстовыми эмбеддингами.

3) Если вам нужны только эмбеддинги, pgai может не понадобиться.

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

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

Слой преобразования текста в SQL

Особенно удачный сценарий использования pgai — создание интерфейса преобразования текста в SQL для ваших баз данных. Это довольно легко реализовать с помощью модуля semantic_catalog из pgai. Достаточно выполнить следующую настройку:

Bash

OPENAI_API_KEY="your-OpenAPI-key-goes-here"TARGET_DB="postgres://user:password@host:port/database"CATALOG_DB="postgres://user:password@host:port/database"

а затем с помощью команды pgai semantic-catalog create поручить семантическому каталогу обработать словари данных. В результате из вашего хранилища данных формируется контекст примерно такого вида:

Plain Text

---schema: postgres_airname: aircrafttype: tabledescription: Lists aircraft models with performance characteristics and unique codes.columns:- name: model  description: Commercial name of the aircraft model.- name: range  description: Maximum flight range in kilometers.- name: class  description: Airframe class category or configuration indicator.- name: velocity  description: Cruising speed of the aircraft.- name: code  description: Three-character aircraft code serving as the primary key....

Теперь pgai может использовать этот контекст несколькими способами:

С помощью семантического поиска:

Этот запрос вернёт таблицы, функции и другие объекты, которые могут относиться к вашему запросу на естественном языке:

Bash

pgai semantic-catalog search -p "Your natural language question goes here!"

Получение необработанного контекста:

Команда выведет необработанный контекст YAML, связанный с вашим запросом на естественном языке:

Bash

pgai semantic-catalog search -p "Your natural language question goes here!" --render

Генерация SQL:

Также можно сразу сгенерировать необработанный SQL-код, необходимый для ответа на запрос. Контекст с предыдущего этапа отправляется в LLM, которая генерирует ответ:

Bash

pgai semantic-catalog generate-sql -p "Your natural language question goes here!"

Как можно использовать pgai уже сейчас

Если вы создаёте относительно простую RAG-систему, pgai стоит попробовать, когда вам нужны:

  • Postgres в качестве основной системы хранения данных;

  • минимум связующего кода;

  • автоматически синхронизируемые эмбеддинги;

  • быстрый способ добавить к базам данных преобразование текста в SQL;

  • возможность поэкспериментировать с новыми инструментами RAG и расширениями Postgres.

Когда стоит проявить осторожность

Вероятно, с pgai стоит повременить, если вашему RAG-конвейеру требуется что-либо из следующего:

  • сложная специализированная логика загрузки данных или разбиения на фрагменты;

  • множество типов документов с разными требованиями к анализу;

  • мультимодальные эмбеддинги.

Наконец, pgvector явно получил широкое распространение, но пока неясно, вызовет ли pgai сопоставимый интерес и, следовательно, получит ли такую же поддержку — хотя проект существует всего около 18 месяцев.

График истории звёзд на GitHub, показывающий рост популярности pgai от Timescale с течением времени.

Итоги

pgai предлагает интересный подход к RAG: база данных берёт на себя больше рутинных операций, благодаря чему код приложения становится проще.

На данный момент он:

  • пригоден и действительно удобен для простых конфигураций RAG;

  • недостаточно гибок для более специализированных конвейеров, особенно мультимодальных.

Проект выглядит многообещающе, и определённо стоит следить за его развитием.

Автор

Andrew Liubinas