Skip to content

About

Чат с базой ваших исследований: отчёты, сырые данные и записи интервью. Ответы со ссылками на конкретную страницу, строку или таймкод. Self-hosted RAG на FastAPI + Next.js + pgvector, любые OpenAI-совместимые модели.

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Гипотениум (Hypotenium)

Чат с базой ваших UX-исследований. Загрузите отчеты, сырые данные и записи интервью — и задавайте вопросы. Ответы ссылаются на конкретную страницу, строки или таймкод источника.

🇬🇧 English version: README.en.md

Статус: рабочий MVP, используется внутри команды исследователей.

Что умеет

  • База знаний из исследований. Исследование — это название, дата и любое число файлов: PDF-отчеты, CSV с сырыми данными, аудио- и видеозаписи интервью. Файлы автоматически режутся на фрагменты, векторизуются и индексируются; медиа транскрибируется с таймкодами.
  • Ответы только по источникам, с цитатами. Каждый тезис помечен маркером [n]. Клик открывает панель источника: страницу PDF, строки CSV или фрагмент интервью с мини-плеером, который перематывает на нужное место. Если в базе ничего нет — ассистент честно говорит об этом, а не выдумывает.
  • Честные источники. Цитаты — снимки: если исследование удалили, старые чаты покажут, на что ссылались, с пометкой «источник удален», а в новых ответах удаленное больше не появится.
  • Чаты с историей. Уточняющие вопросы переформулируются с учетом контекста, даты в вопросе мягко приоритизируют исследования того периода, номера цитат сквозные внутри чата, ответы рендерятся как Markdown. Чатом можно поделиться по ссылке и отозвать доступ.
  • Любые модели. Три слота — чат, эмбеддинги, транскрибация — каждый указывает на любой OpenAI-совместимый API: OpenAI, OpenRouter, локальные Ollama/vLLM, GigaChat и т.д. Конфиг перечитывается на лету; при смене модели эмбеддингов — переиндексация в один клик.
  • Админка (Супердоступ). Управление исследованиями и файлами (с пометками к файлам, которые улучшают поиск), выдача доступа пользователям, переключение моделей.
  • Опциональная локальная транскрибация. Контейнер с GigaAM дает русское распознавание речи с таймкодами и нормализацией чисел полностью на вашей машине — аудио никуда не уходит.

Быстрый старт

Нужны Docker с Compose v2 и API-ключ любого OpenAI-совместимого провайдера.

git clone <этот репозиторий> hypotenium && cd hypotenium
cp .env.example .env          # впишите ключ в LLM_API_KEY
docker compose up -d

Откройте http://localhost:3000 и войдите как admin@example.com / admin12345 (смените оба значения в .env, прежде чем давать доступ кому-то еще). Затем Супердоступ → Исследования: добавьте исследование с парой файлов, дождитесь обработки и задайте вопрос.

Первый запуск собирает два образа (3–5 минут). Данные лежат в docker-volume'ах (pgdata, files-data) и переживают перезапуски и пересборки.

Как пользоваться

1. Добавить исследования

Исследования добавляют администраторы в разделе Супердоступ → Исследования (пункт «Супердоступ» внизу бокового меню виден только админам).

  1. Нажмите «+ Добавить исследование».
  2. Заполните название и дату проведения. Дата важна: по ней работает мягкий фильтр, когда в вопросе упоминается период («что говорили в 2024 году»). Комментарий к исследованию необязателен.
  3. Прикрепите файлы — сколько угодно за раз: PDF-отчеты, CSV с сырыми данными (кодировка и разделитель определяются автоматически), аудио и видео интервью (до 500 МБ каждый). К каждому файлу можно написать комментарий: что внутри, какой сегмент, кто респондент. Комментарий попадает в контекст поиска, поэтому чем точнее пометка — тем лучше находятся нужные фрагменты.
  4. Сохраните форму. Файлы уйдут в фоновую обработку: извлечение текста, транскрибация медиа, нарезка на фрагменты, эмбеддинги. Статус виден в таблице («в очереди» → «обработка…» → «готово»), список обновляется сам. Транскрибация часового интервью занимает минуты, остальное — секунды.

Внутри исследования можно дописать файлы позже, поменять комментарии (индекс по файлу пересчитается) и удалить исследование целиком — тогда оно исчезает из поиска, а в старых чатах его цитаты помечаются как «источник удален».

2. Задать вопрос

Главный экран — поле вопроса. Спрашивайте как коллегу: «Почему пользователи бросают оформление карты?», «Что респонденты говорили про уведомления в интервью 2024 года?». Ассистент ищет по всей базе и отвечает только по найденному: каждый тезис помечен номером [n], клик по нему открывает панель источника — страницу PDF, строки CSV или момент интервью с плеером. Если в базе ничего нет, он так и скажет, а не додумает.

Уточняющие вопросы задавайте в том же чате — контекст сохраняется. Кнопка «Поделиться» дает ссылку на чат для других пользователей сервиса; доступ можно отозвать.

3. Пользователи и доступ

  • Первый администратор создается автоматически из ADMIN_EMAIL / ADMIN_PASSWORD в .env.
  • Остальные регистрируются сами по ссылке «Зарегистрироваться» на экране входа (email + пароль) и попадают в статус «ожидает доступа» — базу они пока не видят.
  • Администратор в Супердоступ → Администрирование нажимает «Выдать доступ». Там же можно назначить еще одного админа («Сделать админом»), снять права или удалить пользователя вместе с его чатами. Последнего администратора снять нельзя.
  • Все допущенные пользователи видят одну общую базу исследований; чаты у каждого свои, пока ими не поделились.

4. Сменить модели

Модели задаются в файле config/models.yaml — три слота: chat (ответы), embedding (поисковый индекс), transcription (аудио → текст). Файл перечитывается на лету: сохранили — следующий запрос уже идет через новую модель, перезапуск не нужен.

Слот Что делает Требования
chat ответы, переформулировка запроса, названия чатов любой chat-completions endpoint со стримингом
embedding векторный индекс для поиска любой embeddings endpoint; размерность определяется автоматически
transcription аудио/видео → текст endpoint /audio/transcriptions; сегменты verbose_json дают таймкоды

Подойдет любой провайдер с OpenAI-совместимым API. В файле есть готовые примеры — достаточно раскомментировать и подставить ключ:

  • OpenAI (по умолчанию): ключ в LLM_API_KEY в .env.
  • Агрегаторы (OpenRouter, polza.ai, Together): меняете base_url и имя модели, ключ — тот же ${LLM_API_KEY} или своя переменная из .env.
  • Локальные модели через Ollama: base_url: http://host.docker.internal:11434/v1, ключ не нужен. Вместе с локальным транскрибером получается полностью офлайн-вариант.
  • GigaChat: у него собственная OAuth-авторизация, она поддержана — provider: gigachat, ключ в GIGACHAT_AUTH_KEY.
  • Локальная транскрибация GigaAM (русская речь, таймкоды, аудио не покидает машину): добавьте COMPOSE_PROFILES=gigaam в .env, выполните docker compose up -d и направьте слот transcription на http://transcriber:9000/v1. Образ тяжелый (~1 ГБ + веса), поэтому по умолчанию выключен.

Два правила:

  • Смена embedding-модели делает индекс несовместимым. Ничего не ломается: в Супердоступ → Исследования появится желтая плашка с кнопкой «Переиндексировать» — она пересчитает эмбеддинги всех фрагментов новой моделью в фоне, без повторной транскрибации. Пока идет пересчет, старые фрагменты не участвуют в поиске.
  • Личные настройки держите в config/models.local.yaml. Он в .gitignore и имеет приоритет над models.yaml, так что при обновлении репозитория ваши ключи и выбор моделей не затрутся.

Параметры поиска там же, в секции rag: top_k — сколько фрагментов передавать модели, min_similarity — порог отсечения нерелевантных, history_messages — сколько сообщений чата учитывать в контексте.

Как устроено

загрузка ──► worker: извлечение (pypdf / csv / ffmpeg + ASR) ──► чанки ──► эмбеддинги ──► pgvector
вопрос ──► переформулировка с историей ──► векторный поиск (+ мягкий фильтр дат) ──► LLM с нумерованными источниками ──► стрим с цитатами [n] ──► снимки цитат в БД
  • Бэкенд: FastAPI, SQLAlchemy 2 (async), PostgreSQL 16 + pgvector, воркеры arq на Redis. Ответы стримятся через SSE.
  • Фронтенд: Next.js 15 (App Router), чистый CSS без UI-фреймворка.
  • Обработка файлов: постраничное извлечение PDF с чисткой колонтитулов, определение кодировки и разделителя CSV, извлечение и нарезка аудио через ffmpeg, фильтр «мусорных» фрагментов, пометки к файлам в контексте эмбеддинга.
  • Цитаты: модель ссылается на позиции в списке источников, сервер на лету переводит их в сквозные номера чата и сохраняет снимок (исследование, файл, локатор, полный текст фрагмента) при каждом сообщении.
Сервис Порт Роль
web 3000 фронтенд Next.js
api 8000 бэкенд FastAPI, Swagger на /docs
worker — фоновая обработка (транскрибация, эмбеддинги, переиндексация)
postgres 5432 PostgreSQL + pgvector
redis — очередь задач
transcriber 127.0.0.1:9000 опциональный локальный GigaAM (профиль gigaam)

Полное техническое задание с принятыми решениями, моделью угроз и планом второй итерации — в docs/TZ.md.

Экспериментально: инструменты чата

В чате есть система модулей, которые ведут собственный сценарий поверх RAG. Первый — брифинг задачи на исследование: когда в базе нет ответа, ассистент предлагает завести задачу, задает заказчику по одному вопросу, проверяет гипотезы по критериям NN/g, методологическую часть предлагает сам и сохраняет задачу в Markdown в tasks/. По умолчанию выключен (tools.research_task: false в config/models.yaml), пока сценарий дошлифовывается — включите, чтобы попробовать.

Разворачивание не на localhost

Для ноутбука или внутреннего сервера достаточно docker compose up. Перед тем как открывать сервис наружу:

  1. Задайте случайный JWT_SECRET и настоящий ADMIN_PASSWORD в .env (пока стоят дефолты, API пишет предупреждение в лог).
  2. Спрячьте оба сервиса за HTTPS (любой reverse proxy) и пропишите публичные адреса в FRONTEND_ORIGIN / NEXT_PUBLIC_API_URL, затем пересоберите web (адрес API зашивается при сборке).
  3. Добавьте rate-limit на /auth/login на прокси.
  4. Если используете GigaChat с verify_ssl: false — вместо этого установите в образ сертификаты НУЦ Минцифры.
  5. Загруженные файлы лежат в volume files-data в открытом виде — решите, нужно ли шифрование at rest.

За пределы вашей инфраструктуры уходят только запросы, которые вы настроили: чат и эмбеддинги — к провайдерам из models.yaml; с локальным транскрибером аудио обрабатывается на вашей машине.

Планы

  • Гибридный поиск (BM25 + векторы, RRF) для точных чисел, годов и названий продуктов.
  • Графики по сырым CSV-данным прямо в ответах.
  • Проверка цитат после генерации (ловить пересказ, выданный за цитату).
  • Доведение инструмента брифинга задач.
  • Английский интерфейс / i18n.
  • Разбор PDF с графиками и сложной версткой через VLM.

Участие

Issues и pull request'ы приветствуются — см. CONTRIBUTING.md.

Лицензия

MIT.

About

Чат с базой ваших исследований: отчёты, сырые данные и записи интервью. Ответы со ссылками на конкретную страницу, строку или таймкод. Self-hosted RAG на FastAPI + Next.js + pgvector, любые OpenAI-совместимые модели.

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages