"Сделал AI-ассистента на RAG: Go + Next.js + локальная LLM"

01.06.2026
#Go#Next.js#RAG#Ollama#PostgreSQL#pgvector#AI

Скриншот

1.png

2.png

📦 GitHub

Репозиторий: github.com/dmironovru/rag-assistant

Локальный AI-помощник, который отвечает на вопросы по документам. Всё работает на твоём компьютере — никаких облачных API и платных ключей.

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

git clone git@github.com:dmironovru/rag-assistant.git
cd rag-assistant
./start.sh

Скрипт проверяет зависимости, качает модели (~4.5 ГБ), создаёт базу и поднимает всё окружение. Первый запуск — 10–15 минут (качаются модели), следующие — 30 секунд.

Что за проект

Мне давно хотелось собрать что-то, что умело бы отвечать на вопросы по документации, но при этом работало бы локально. Без OpenAI, без интернета, без риска, что мои данные утекут.

Так появился RAG Assistant.

RAG (Retrieval-Augmented Generation) — это когда система сначала ищет релевантные куски в документах, а потом на их основе генерирует ответ. Вместо того чтобы просто спрашивать у LLM «в лоб», мы даём ей конкретный контекст, и она отвечает уже с опорой на факты.

Вот как это выглядит изнутри:

  1. Пользователь задаёт вопрос.
  2. Система находит похожие по смыслу куски текста в документах через векторный поиск.
  3. Эти куски передаются в локальную модель (Ollama), которая генерирует ответ.
  4. В ответе показываются источники — чтобы можно было проверить, откуда взялась информация.

Что использовал

  • Frontend: Next.js 16, React 19, Tailwind CSS
  • Backend: Go 1.23, chi, pgx
  • AI: Ollama (mistral:7b + nomic-embed-text)
  • Database: PostgreSQL 16 + pgvector
  • Infra: bash-скрипты (start.sh / stop.sh)

Go выбрал за скорость и простоту. Next.js — за удобный SSR и клиентский чат. PostgreSQL с pgvector — за то, что не надо поднимать отдельную векторную базу.

Как работает векторный поиск

Самая интересная часть — как искать похожие тексты.

Я разбиваю документы на чанки (по 200–300 символов), каждый чанк превращаю в вектор через модель nomic-embed-text, и сохраняю в PostgreSQL c pgvector. Потом, когда приходит вопрос, я делаю то же самое с вопросом и ищу ближайшие по косинусному расстоянию чанки:

query := `
    SELECT content, source,
           1 - (embedding <=> $1::vector) AS similarity
    FROM document_chunks
    ORDER BY embedding <=> $1::vector
    LIMIT 10
`

Оператор <=> — это косинусное расстояние в pgvector. Чем оно меньше, тем больше похожи векторы. Я беру топ-10 чанков и передаю их в LLM.

С чем пришлось повозиться

Выбор модели

По умолчанию использую mistral:7b — для английского отлично, для русского терпимо. Если нужен русский — меняю на qwen2.5:7b через .env.

Размер модели

Модели весят по 4–5 ГБ. При первом запуске start.sh скачивает их через Ollama. Это занимает время, зато потом всё работает локально.

Блокировка Docker Hub

Как и в прошлых проектах, столкнулся с тем, что Docker Hub в РФ заблокирован. Но я решил вообще отказаться от Docker — слишком много зависимостей (Ollama, PostgreSQL, Go, Node). Нативный запуск оказался стабильнее и проще в отладке. Весь процесс свёлся к одному bash-скрипту.

Качество ответов

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

Архитектура

┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│   Frontend      │     │   Go Backend    │     │   Ollama        │
│   (Next.js 16)  │────▶│   (RAG API)     │────▶│   (LLM)         │
│   :3000         │     │   :8080         │     │   :11434        │
└─────────────────┘     └────────┬────────┘     └─────────────────┘
                                 │
                    ┌────────────▼────────────┐
                    │   PostgreSQL + pgvector │
                    │   Чанки + эмбеддинги    │
                    └─────────────────────────┘

Как добавить свои документы

По умолчанию в репозитории лежит демо-файл — «Гарри Поттер и Тайная комната». Чтобы добавить свои документы:

  1. Открываешь интерфейс на http://localhost:3000.
  2. Нажимаешь «Загрузить файл».
  3. Выбираешь TXT, PDF или DOC.
  4. Система автоматически индексирует файл, разбивает на чанки и генерирует эмбеддинги.
  5. Задаёшь вопросы по содержимому.

Также можно индексировать через командную строку:

cd backend
go run cmd/ingest/main.go ./storage/uploads/my_document.txt

Репозиторий: github.com/dmironovru/rag-assistant
Стек: Go, Next.js, PostgreSQL, pgvector, Ollama