Перейти к содержимому
Все проекты

AI · Retrieval-augmented generation

RAG база знаний

Мультитенантная база знаний в launch-tools — Go-платформе Launchist. Команды загружают документы, они превращаются в эмбеддинги в PostgreSQL с pgvector, а затем с ними можно общаться в чате: ответы стримятся и опираются на источники.

Моя роль
Backend-разработчик. Реализовал pipeline обработки документов, хранилище на pgvector, семантический поиск и стриминговый чат с историей диалога.
Стек
  • Go
  • Echo
  • LangChain (Go)
  • PostgreSQL
  • pgvector
  • Redis
  • WebSocket

Задача

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

Архитектура

RAG база знаний — Схема архитектурыingestionquestion answeringDocumentspdf · docx · xlsxProcessparse · chunkEmbedembeddingsHistoryconversationpgvectorper namespaceQuestionWebSocketSearchsemantic · top-kContextchunks + historyLLMstreamed answer
Загрузка документов и ответы на вопросы — отдельные потоки. Загруженные файлы парсятся, делятся на чанки, превращаются в эмбеддинги и пачками записываются в pgvector — одна коллекция на пространство. При вопросе запрос превращается в эмбеддинг, ближайшие фрагменты ищутся в пространствах, подключённых к чату, объединяются с историей диалога и отправляются выбранной LLM; ответ стримится клиенту через WebSocket. Сервис написан на Go (Echo) и работает в Google Cloud Run.

Ключевые решения

  1. 01pgvector вместо отдельной векторной БД

    Почему
    Векторы хранятся рядом с документами, метаданными и историей чатов в одном PostgreSQL: фильтрация, join-ы и транзакции работают как обычно, и на одну систему в эксплуатации меньше. Собственное хранилище для LangChain (Go) добавляет HNSW-индекс и фильтры по метаданным, а создание схемы защищено advisory-блокировками PostgreSQL — несколько инстансов Cloud Run могут стартовать одновременно.
    Компромисс
    На очень больших объёмах специализированная векторная БД может индексировать и искать быстрее.
  2. 02Пространства как единица изоляции и поиска

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

    Почему
    Парсинг и создание эмбеддингов медленные и ограничены лимитами API. Обработка файлов вне пути чата и с фиксированным числом параллельных задач сохраняет скорость ответов и бережёт и квоту API, и память инстанса.
    Компромисс
    Новый документ становится доступен для поиска только после завершения обработки.
  4. 04Стриминг ответов с историей диалога

    Почему
    Токены отправляются через WebSocket по мере генерации, поэтому пользователь сразу видит начало ответа. Предыдущие сообщения учитываются, чтобы уточняющие вопросы вроде «а что со вторым вариантом?» понимались правильно.
    Компромисс
    Длинные промпты дороже по токенам, поэтому историю приходится обрезать.

Что я сделал

  • Мультитенантная модель: организации, проекты, пространства (namespaces), участники и приглашения
  • Загрузка PDF, DOCX, XLSX и архивов с ограниченной параллельностью
  • Собственное хранилище на pgvector для LangChain (Go) с HNSW-индексом и фильтрацией по метаданным
  • Стриминг ответов через WebSocket, история диалога и редактируемые системные промпты
  • Несколько LLM-провайдеров (OpenAI, Anthropic, Gemini) и собственные ключи клиентов в GCP Secret Manager