Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

База знаний (RAG)

Вопрос-ответный сервис по тематическому корпусу «внедрение AI в бизнес-процессы»: каждый ответ строится только на проиндексированных источниках и сопровождается кликабельными цитатами.

Full-cycle RAG demo: ingestion of open-source corpora, local embeddings (multilingual-e5-base), pgvector retrieval, LLM answers with inline citations and an eval harness.

CI Node >= 18 License: MIT

Живое демо

preview

demo

Как это работает (простыми словами)

Обычная нейросеть отвечает «по памяти» — и может незаметно выдумать. Здесь она работает как библиотекарь: прежде чем отвечать, находит в собственной библиотеке нужные страницы и отвечает строго по ним, прикладывая номера сносок. Библиотека собирается заранее: открытые документы по теме режутся на фрагменты, каждому фрагменту присваивается числовой «адрес смысла» (эмбеддинг), и всё складывается в базу. Когда вы задаёте вопрос, он превращается в такой же «адрес», база мгновенно находит самые близкие по смыслу фрагменты, и уже по ним модель формулирует ответ со ссылками [1], [2] на первоисточники. Любую фразу ответа можно перепроверить одним кликом.

Архитектура

  ingest/ingest.py (по расписанию / вручную)
  git clone открытых репозиториев (MIT)
        │ markdown → чанки ~600 токенов
        ▼
  embedder/server.py  (FastAPI + sentence-transformers,
        │              intfloat/multilingual-e5-base, mode=passage)
        ▼ 768-мерные L2-нормированные векторы
  PostgreSQL + pgvector (rag_sources, rag_chunks, HNSW cosine)
        ▲
        │ top-k по cosine similarity
  server/server.mjs ── POST /api/agents/rag/answer
        │  1) embedQuery (mode=query) → вектор вопроса
        │  2) retrieveChunks → топ-6 фрагментов
        │  3) prompt «отвечай только по источникам» → OpenRouter LLM
        │  4) парсинг сносок [N] → citations
        ▼
  public/agents/rag/  (чат с цитатами и списком источников)

  eval-контур: ingest/eval.py гоняет ingest/eval-questions.yaml через API,
  считает recall@5 и latency p50/p95, пишет baseline в rag_eval_runs.

Стек

  • Node.js без фреймворков (node:http), единственная зависимость сервера — postgres.
  • OpenRouter API как генератор ответов: используются free-модели, primary выбирается по живому ранкингу, при ошибке провайдера — один retry на fallback-модель.
  • PostgreSQL 16 + pgvector 0.6, HNSW-индекс по cosine (ingest/schema.sql).
  • Локальный embedder: FastAPI + sentence-transformers, модель intfloat/multilingual-e5-base (768d, RU+EN), CPU-only sidecar (embedder/).
  • Ingestion на Python: клонирование git-репозиториев с открытой лицензией, чанкинг markdown по токенам (target 600 / max 750 / overlap 100), батчевый эмбеддинг (ingest/ingest.py).
  • Eval-харнесс: recall@5 и latency по фиксированному набору вопросов (ingest/eval.py), результаты в БД.
  • Фронтенд: статический HTML + vanilla JS, без сборки.

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

cd server
npm install
cp ../.env.example .env       # вписать OPENROUTER_API_KEY
npm start
# открыть http://127.0.0.1:8787/agents/rag/

Без Postgres и embedder-а сервер поднимется, но /api/agents/rag/* будут отвечать configured: false — это ожидаемо. Полный цикл:

  1. Поднять Postgres с pgvector и применить ingest/schema.sql.
  2. Запустить embedder: cd embedder && pip install -r requirements.txt && uvicorn server:app --host 127.0.0.1 --port 8788 (на сервере — через install.sh + systemd-юнит).
  3. Заполнить корпус: cd ingest && pip install -r requirements.txt && RAG_DB_URL=... RAG_EMBEDDER_URL=http://127.0.0.1:8788 python ingest.py --sources sources.yaml --workdir ./sources.
  4. Раскомментировать RAG_DB_URL и RAG_EMBEDDER_URL в .env и перезапустить сервер.
  5. (Опционально) снять baseline: python eval.py --questions eval-questions.yaml — recall@5, latency p50/p95.

Переменные окружения

Переменная Обязательна Описание
OPENROUTER_API_KEY да (для ответов) Ключ OpenRouter; без него /answer отвечает 503
RAG_DB_URL да (для RAG) Строка подключения к Postgres с pgvector
RAG_EMBEDDER_URL да (для RAG) URL embedder-sidecar-а, например http://127.0.0.1:8788
LLM_POOL_HOST / LLM_POOL_PORT нет Адрес и порт HTTP-сервера (по умолчанию 127.0.0.1:8787)
OPENROUTER_MODEL нет Жёстко заданная primary-модель (иначе — топ живого ранкинга)
LLM_POOL_DEFAULT_MODEL нет Модель по умолчанию, если ранкинг недоступен
OPENROUTER_FALLBACK_MODEL нет Fallback-модель для retry
LLM_POOL_REASONING_EFFORT нет Уровень reasoning (low/medium/high)
LLM_POOL_RANKING_URL нет Источник живого ранкинга free-моделей
RAG_EMBED_MODEL / RAG_EMBED_DIM нет Отображаются в /status (по умолчанию 768)
RAG_TOP_K нет Сколько фрагментов доставать (по умолчанию 6, максимум 10)
RAG_MIN_SCORE нет Порог cosine-score для включения фрагмента в промпт (0.5)
RAG_QUERY_MAX_CHARS / RAG_SNIPPET_MAX_CHARS нет Лимиты длины вопроса и сниппета
RAG_EMBEDDER_TIMEOUT_MS нет Таймаут запроса к embedder (15000)
LLM_POOL_RATE_WINDOW_MS / LLM_POOL_RATE_LIMIT нет Окно и лимит rate-limit по IP (5 мин / 20)
LLM_POOL_CHAT_TIMEOUT_MS / LLM_POOL_RANKING_TIMEOUT_MS нет Таймауты запросов к OpenRouter и ранкингу

API

Метод Путь Описание
GET /api/llm-pool/health Health-check: наличие ключа, текущая primary/fallback-модель
GET /api/llm-pool/quota Статус free-tier квоты OpenRouter (скользящее окно ошибок)
GET /api/agents/rag/status Статус корпуса: число источников/фрагментов, embedder, последний eval; 503 configured:false без БД
POST /api/agents/rag/answer { "question": "...", "k"?: 1–10 } → ответ с citations, retrievedSources, таймингами retrieval и метаданными модели

Ограничения демо

  • Rate limit: 20 запросов с одного IP за 5 минут (429 с Retry-After).
  • Вопрос обрезается до 1000 символов; тело запроса — до 128 KB.
  • Требуются внешние сервисы: PostgreSQL + pgvector (корпус и eval) и embedder-sidecar (Python, ~1 GB RAM под модель). Без них роуты RAG честно отвечают configured: false.
  • Генерация идёт через free-модели OpenRouter: возможны паузы и 429; сервер делает один retry на fallback-модель, статус квоты виден в /api/llm-pool/quota.
  • Faithfulness в eval-контуре не считается (шумно на free-моделях) — метрика зарезервирована как NULL.

Часть портфолио antonov-ai.ru · MIT License

About

RAG-пайплайн целиком: ingestion -> pgvector -> retrieval -> ответы с цитатами + eval-контур. Демо: antonov-ai.ru/agents/rag

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages