PRODСуверенная европейская платформа BaaSОткрыть панель управления →

Родной ИИ · 10 минута чтения

Учебное пособие: конвейер RAG с Postgres и pgvector

Affane Daylami · Fondateur · 13 апреля 2026 г.

Вернуться в блог

Создание конвейера RAG на Postgres обычно требует самостоятельной сборки нескольких частей: среза текста, вызова внедрения, таблицы pgvector, запроса на сходство. Это классический LangChain + PGVectorchain. В Aurabase этот конвейер уже существует на стороне сервера: два вызова, ragIngest() и rag(), заменяют его, используя при этом стандартные PostgreSQL и pgvector, без добавления собственной векторной базы.

Этот текст на английском языке был создан автоматически на основе французского оригинала и еще не проверялся.
Эта страница была переведена автоматически. Английская версия является авторитетной.

Собственный RAG является частью собственного искусственного интеллекта, интегрированного в бэкэнд Aurabase, наряду с NL2SQL: это не сторонний сервис, который можно собрать поверх общей базы. Предварительные условия для выполнения этого руководства: существующий проект Aurabase, настроенный поставщик LLM (OpenAI или Google Gemini для внедрения, один из трех собственных поставщиков для генерации) и ключ API проекта.

Самое необходимое
  • Конвейер Aurabase RAG состоит из двух вызовов: ragIngest() для индексации документа и rag() для запроса и генерации ответа. Управление фрагментами, встраиванием и векторным поиском осуществляется на стороне сервера.
  • Под капотом это стандартный PostgreSQL и pgvector: таблица embeddings с одним векторным столбцом для каждого класса измерения (768, 1536, 3072) и частичным индексом HNSW для каждого класса.
  • При формировании фрагментов используется настоящий токенизатор (tiktoken o200k) с настраиваемым перекрытием и защитой от взрыва в больших документах.
  • Полученное содержимое нейтрализуется перед внедрением в приглашение: документ, который пытается избежать своего тега, чтобы подделать системные инструкции, явно обезвреживается.
  • Только OpenAI и Gemini генерируют внедрения на стороне Aurabase. У Anthropic/Claude нет общедоступного API для встраивания, он остается зарезервированным для генерации окончательного ответа.
#
Концепция

Как работает этот конвейер RAG

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

Чанкинг (tiktoken)→Внедрение (пакетный)→хранилище pgvector (HNSW)→Поиск по сходству→Дополненная генерация

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

#
Шаг 1

Создать проект

В отличие от типичного pgvector, размещаемого самостоятельно, вам не нужно запускать CREATE EXTENSION vector или самостоятельно создавать таблицу для этого конвейера. Схема embeddings проекта с векторными столбцами и индексами HNSW предоставляется автоматически при создании проекта.

terminalbash
# Учетная запись Aurabase + CLI
npm i -g @aurabase/cli
aura login

# Создайте проект и свяжите его с этой папкой.
aura projects create mon-assistant --engine postgres
aura link --project-id <uuid-du-projet>

# Получить ключи API связанного проекта
aura projects api-keys

Поставщик внедрения настраивается один раз, на стороне проекта (Студия → IA → Поставщики). Именно этот поставщик определяет эффективный размер ваших векторов, поэтому столбец, используемый в таблице embeddings.

#
Шаг 2

Индексируйте свои документы с помощью ragIngest().

Для индексации документа достаточно одного вызова: текст разбивается на фрагменты, каждый фрагмент векторизуется, а затем сохраняется в запрошенном пространстве имен. Для разделения используется настоящий токенизатор (tiktoken, кодировка o200k_base), а не простое разделение по пробелам, которое остается правильным для текста без пробелов, как в некоторых азиатских языках.

app/api/ingest/route.tstypescript
import { aura } from '@/lib/aurabase'

export async function POST(req: Request) {
  const { content, metadata } = await req.json()

  const { data, error } = await aura.ai.ragIngest({
    namespace: 'docs-produit',
    content,
    metadata,
  })

  if (error) return Response.json({ error }, { status: 400 })
  return Response.json(data) // { идентификатор, фрагменты }
}

В необработанном HTTP эквивалентным маршрутом является POST /v1/ai/{project_id}/rag/ingest, аутентифицированный ключом API проекта.

terminalbash
curl -X POST https://<votre-gateway>/v1/ai/<project_id>/rag/ingest \
  -H "apikey: <votre-cle-api>" \
  -H "Content-Type: application/json" \
  -d '{
    "namespace": "docs-produit",
    "content": "Le texte complet de votre document ici...",
    "metadata": { "source": "guide-utilisateur.pdf" }
  }'

По умолчанию прием является идемпотентным: идентификатор документа создается автоматически (хеш содержимого SHA-256 или metadata.document_id, если вы его предоставляете). При повторной загрузке того же контента существующие фрагменты заменяются, а не дублируются, что делает выполнение периодической синхронизации безопасным для воспроизведения.

#
Шаг 3

Что на самом деле попадает в Postgres

Никакой фирменной магии здесь нет: таблица, которая получает ваши векторы, представляет собой обычную таблицу Postgres с одним столбцом vector для каждого класса измерения и частичным индексом HNSW для каждого столбца (активным только для строк, которые ее заполняют). Вот его реальное определение, упрощенное:

Платформенная схема проекта (упрощенная)sql
create table embeddings (
  id               uuid primary key default gen_random_uuid(),
  project_id       text not null,
  namespace        text not null,
  content          text not null,
  embedding_768    vector(768),
  embedding_1536   vector(1536),
  embedding_3072   vector(3072),
  embedding_model  text,
  dims             int,
  metadata         jsonb default '{}'::jsonb,
  created_at       timestamptz not null default now()
);

-- Частичный индекс HNSW по классам измерений
create index idx_embeddings_vec_1536 on embeddings
  using hnsw (embedding_1536 vector_cosine_ops)
  where embedding_1536 is not null;

-- За пределами 2000 измерений HNSW не поддерживает векторный тип:
-- отлит в полувек для класса 3072
create index idx_embeddings_vec_3072 on embeddings
  using hnsw ((embedding_3072::halfvec(3072)) halfvec_cosine_ops)
  where embedding_3072 is not null;

При каждом поиске векторы сравниваются с оператором косинусного расстояния (<=>), на который нацелены классы операторов индекса vector_cosine_ops и halfvec_cosine_ops. Подробные сведения о компромиссе между отзывом и задержкой между HNSW и IVFFlat см. в статье , посвященной индексации HNSW. Для выбора самого размера внедрения см. сравнение 768 vs 1536 vs 3072.

#
Шаг 4

Запрос и генерирование ответа с помощью rag()

На стороне запроса rag() объединяет векторизацию вопроса, поиск по сходству в пространстве имен, построение расширенного приглашения и вызов модели генерации в едином сетевом обходе на стороне клиента.

app/api/ask/route.tstypescript
import { aura } from '@/lib/aurabase'

export async function POST(req: Request) {
  const { question } = await req.json()

  const { data, error } = await aura.ai.rag({
    question,
    namespace: 'docs-produit',
  })

  if (error) return Response.json({ error }, { status: 400 })
  return Response.json(data)
}

Ответ содержит сгенерированный ответ и его источники, а также фактически используемый поставщик:

ответ (отрывок)json
{
  "data": {
    "answer": "D'après la documentation, ...",
    "sources": [
      { "id": "...", "content": "...", "similarity": 0.87 }
    ],
    "model": "claude-3-5-sonnet",
    "tokens": 412,
    "provider": "anthropic",
    "fallback_used": false
  }
}

Полученное содержимое никогда не вводится в системное приглашение в сыром виде. Это недостоверные данные (загрузка пользователем, проиндексированная страница): документ, содержащий, например, закрывающий тег раздела, за которым следуют ложные инструкции, перед сборкой нейтрализуется, его угловые скобки заменяются скобками, текст сохраняется, но структура разряжается.

Корпус индексируется по другой модели

Если rag() ничего не находит, хотя ваше пространство имен не пусто, ответ содержит явное предупреждение, а не вводящее в заблуждение молчание: ваш корпус, вероятно, проиндексирован по другой модели или другому измерению внедрения. Переиндексируйте его через POST /v1/ai/{project_id}/rag/{namespace}/reindex.

#
Сравнение

От LangChain и самодельного pgvector: что меняется

Если вы уже создали чат-бот RAG на PostgreSQL с помощью LangChain, каждый ручной блок имеет здесь управляемый эквивалент на стороне сервера без изменения базовой базы данных.

Разбивка текстаRecursiveCharacterTextSplitter для установки самостоятельноragIngest(): встроенное разделение tiktoken, 512 токенов / 64 перекрытия по умолчанию
ВложенияРучной вызов OpenAIEmbeddings, управление лимитами пакетовАвтоматически группируемая встроенная временная повторная попытка
Векторное хранилищетаблица pgvector + индекс HNSW для самостоятельного создания и переносаСхема и индексы предоставляются для каждого проекта
Поиск + подсказкаPGVector.similarity_search(), затем вручную собираем приглашениеrag(): поиск и расширенная генерация за один вызов
Восстановленный контентВставлено как указано в командной строкеАвтоматическая нейтрализация меток конструкции перед сборкой

Вы переносите существующий проект, созданный на Supabase, с помощью такой ручной сборки? Логика миграции остальной части серверной части (схема, политики RLS, SDK) описана в нашем руководстве по миграции Supabase на Aurabase.

#
Производство

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

Три параметра напрямую влияют на стоимость и задержку, и все они проверены в сервисном коде aura-ai. Количество попыток временного вызова внедрения (сбой сети, ошибка провайдера 429) по умолчанию равно 3 с базовой задержкой 100 мс. Большие документы по умолчанию встраиваются в подпакеты, ограниченные 2048 фрагментами, чтобы соблюдать ограничения API поставщиков и не допускать сбоев при работе с одним массивным документом. Ограждение (по умолчанию 10 000 фрагментов, настраиваемое) явно отклоняет прием документа, который может создать ненормальное количество фрагментов.

Что касается поиска, размер списка кандидатов HNSW автоматически изменяется до max(64, top_k × 4): чем больше результатов вы запрашиваете, тем больше кандидатов исследует индекс, чтобы сохранить отзыв. Фиксированное значение остается возможным через переменную среды, если ваш корпус имеет определенный профиль.

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

#
Честность

Текущие ограничения, о которых следует знать

Измерение внедрения должно относиться к одному из трех поддерживаемых классов: 768, 1536 или 3072. Поставщик, возвращающий другое измерение, отклоняется с явной ошибкой, никогда не усекается и не приводится автоматически.

Генерация встраивания доступна только через OpenAI или Google Gemini среди трех собственных провайдеров: Anthropic/Claude не предоставляет общедоступный API встраивания, поэтому он используется только для генерации окончательного ответа в этом конвейере, а не для векторизации.

JavaScript SDK пока не предоставляет переопределения top_k и threshold для вызова rag(): они остаются доступными по прямому HTTP, ограниченному соответственно [1, 50] и [0, 1], но не из aura.ai.rag(), как сегодня. Порог сходства по умолчанию (0,3) намеренно является допускающим; сузьте его до плотного корпуса, чтобы избежать нерелевантных источников в подсказке.

#
Иди дальше

Чтобы пойти дальше

КГР охватывает вопросы по неструктурированному контенту (документы, заметки, заявки). При возникновении вопросов о ваших реляционных данных встроенный в Aurabase NL2SQL напрямую преобразует вопрос в проверенный SQL. Подробные сведения о параметрах HNSW и классах измерений, упомянутых выше, см. в статье об индексировании HNSW и сравнении вложенных измерений. Полный справочник по API остается в документации RAG и pgvector и документации AI Gateway.

#
Часто задаваемые вопросы

Часто задаваемые вопросы

Вам нужно самостоятельно управлять расширением pgvector и индексом HNSW?+
Нет. Схема внедрения, расширение pgvector и частичные индексы HNSW (по одному на класс измерений: 768, 1536, 3072) подготавливаются автоматически при создании проекта. Вы напрямую вызываете ragIngest(), затем rag(); тонкая настройка индекса (ef_search, режим итеративного_сканирования) остается доступной на стороне сервера, если ваш корпус имеет определенный профиль.
Какой размер внедрения мне следует выбрать для моего варианта использования?+
Aurabase проверяет измерение, возвращаемое вашим поставщиком, на соответствие трем поддерживаемым классам: 768, 1536 и 3072. Выбор зависит от настроенной модели внедрения (например, text-embedding-3-small в OpenAI создает 1536 измерений) и предполагает компромисс между отзывом, стоимостью и размером хранилища, подробно описанными в нашем сравнении, посвященном внедрению измерений.

ГОТОВЫ К РАЗВЕРТЫВАНИЮ?

Ваш бэкэнд за пять минут.

Кредитная карта не требуется · 500 МБ бесплатно · 50 000 MAU