Skip to content

Ruen189/DiamondRAG

Repository files navigation

Методолог — ИИ-ассистент для студентов

RAG-бот в Telegram, помогающий студентам с методологиями разработки ПО: Agile, Scrum, Kanban, DevOps, планирование задач, документация.

Архитектура

┌─────────────┐     ┌──────────────┐     ┌─────────────────┐
│  Telegram    │────▶│  Bot (Python)│────▶│  llama.cpp      │
│  пользователь│◀────│  + RAG       │◀────│  server (LLM)   │
└─────────────┘     │  + ChromaDB  │     └─────────────────┘
                    │  + SQLite    │
                    └──────────────┘

Компоненты:

  • llama.cpp server — обслуживает LLM через OpenAI-совместимый API
  • ChromaDB — векторная БД для хранения базы знаний (embedded, внутри контейнера бота)
  • SQLite — хранение истории диалогов, summary, обратной связи
  • aiogram 3 — Telegram-бот с асинхронной обработкой

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

1. Настройка переменных окружения

cp .env.example .env
# Отредактируйте .env: укажите TELEGRAM_TOKEN и модель

2. Запуск через Docker Compose

docker compose up -d

Это запустит:

  • llama-server — скачает модель через -hf флаг и запустит сервер
  • bot — Telegram-бот с RAG-пайплайном

3. Запуск без Docker (локально)

# Терминал 1: запустите llama-server
llama-server -hf unsloth/Qwen3.5-9B-GGUF:UD-Q4_K_XL -c 128000 --host 0.0.0.0 --port 8765

# Терминал 2: запустите бота
pip install -r requirements.txt
python -m app.main

4. Запуск с GPU (NVIDIA)

Раскомментируйте секцию deploy в docker-compose.yml для llama-server:

deploy:
  resources:
    reservations:
      devices:
        - driver: nvidia
          count: all
          capabilities: [gpu]

Используйте образ ghcr.io/ggml-org/llama.cpp:server-cuda вместо ghcr.io/ggml-org/llama.cpp:server.

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

Переменная По умолчанию Описание
MODEL_HF unsloth/Qwen3.5-9B-GGUF:UD-Q4_K_XL Модель для -hf флага llama.cpp
CONTEXT_SIZE 128000 Размер контекстного окна (-c флаг)
LLM_HOST llama-server Хост llama.cpp сервера
LLM_PORT 8765 Порт llama.cpp сервера
IS_MULTIMODAL true Поддерживает ли модель изображения
IS_REASONING_MODEL true Является ли модель рассуждающей (thinking)
TELEGRAM_TOKEN Токен Telegram-бота
MAX_QUEUE_SIZE 3 Макс. размер очереди сообщений на пользователя
RAW_MESSAGES_SIZE 10 Минимум сырых сообщений в контексте
MESSAGES_SUMMARY_SIZE 5 Дополнительный буфер сырых сообщений
SUMMARY_TOKENS_SIZE 12000 Макс. размер summary в токенах
SUMMARY_MODEL_HF (= MODEL_HF) Отдельная модель для сжатия
SUMMARY_LLM_HOST (= LLM_HOST) Хост для summary-модели
SUMMARY_LLM_PORT (= LLM_PORT) Порт для summary-модели
RAG_TOP_K 5 Количество фрагментов из векторной БД
RAG_SCORE_THRESHOLD 0.35 Порог релевантности для RAG
EMBEDDING_MODEL sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2 Модель эмбеддингов

Как работает RAG

Когда RAG используется

RAG (Retrieval-Augmented Generation) используется автоматически на основе релевантности вопроса:

  1. Каждый вопрос пользователя отправляется в векторную БД (ChromaDB)
  2. Извлекаются RAG_TOP_K наиболее похожих фрагментов
  3. Если хотя бы один фрагмент имеет score >= RAG_SCORE_THRESHOLD — он включается в контекст
  4. Если ни один фрагмент не достаточно релевантен — RAG-контекст не добавляется

RAG используется для:

  • Вопросов о методологиях (Agile, Scrum, Kanban, DevOps)
  • Вопросов о планировании, документации, ролях в команде
  • Любых тем, по которым есть материалы в базе знаний

RAG НЕ используется для:

  • Приветствий и общих вопросов
  • Тем, по которым нет релевантных документов в базе
  • В этих случаях ассистент использует общие знания LLM, предупреждая об этом

Порог релевантности

RAG_SCORE_THRESHOLD=0.35 — косинусное сходство. Значения:

  • >0.7 — высокая релевантность, точное совпадение темы
  • 0.5–0.7 — средняя релевантность, смежная тема
  • 0.35–0.5 — низкая релевантность, может быть полезно
  • <0.35 — нерелевантно, не включается в контекст

Управление контекстом диалога

Изоляция контекста пользователей

Каждый пользователь Telegram имеет полностью изолированный контекст:

  • SQLite хранит историю сообщений с привязкой к user_id
  • Summary (сжатие старых сообщений) хранится отдельно для каждого пользователя
  • Очередь обработки — отдельная для каждого пользователя
  • Контексты никогда не пересекаются: запросы и данные одного пользователя недоступны другому

Персистентность контекста

Контекст не теряется при перезапуске или сбое:

  • Все сообщения сохраняются в SQLite сразу при получении
  • Summary хранится в SQLite с отметкой времени
  • При перезапуске бот загружает историю из БД
  • SQLite-файл хранится на Docker volume (sqlite_data)

Структура контекстного окна

┌──────────────────────────────────────┐
│  1. Системный промпт (инструкция)   │
│  2. Summary (если есть)              │
│  3. Последние N сырых сообщений      │
│  4. RAG-фрагменты (если релевантны)  │
│  5. Текущий вопрос пользователя      │
└──────────────────────────────────────┘

Сжатие сообщений (Summary)

  • Если сообщений <= RAW_MESSAGES_SIZE + MESSAGES_SUMMARY_SIZE - 1 (по умолчанию 14) — все в сыром виде
  • Если больше — последние RAW_MESSAGES_SIZE (10) остаются сырыми, остальные сжимаются в summary
  • Новый summary объединяется с существующим
  • Если summary > SUMMARY_TOKENS_SIZE (12000 токенов) — пересжимается
  • Для сжатия можно использовать отдельную модель (SUMMARY_MODEL_HF)

Мультимодальность

  • IS_MULTIMODAL=true — бот принимает изображения и отправляет их в LLM
  • IS_MULTIMODAL=false — при отправке изображения бот отвечает: "Простите, я понимаю только текст"
  • Модели unsloth с UD-квантизацией (TurboQuant) поддерживают мультимодальность

Рассуждающие модели (Thinking)

Для моделей вроде Qwen3.5, которые генерируют <think>...</think> блоки:

  1. IS_REASONING_MODEL=true — включает фильтрацию
  2. Пользователю сначала отправляется: "Рассуждаю, подождите..."
  3. После получения ответа <think> блоки вырезаются
  4. Пользователь видит только финальный ответ без рассуждений

Очередь сообщений

  • Каждый пользователь имеет очередь размером MAX_QUEUE_SIZE (по умолчанию 3)
  • Если пользователь отправляет сообщение, пока предыдущее обрабатывается — оно встаёт в очередь
  • Если очередь полна — новые сообщения игнорируются с уведомлением
  • Обработка строго последовательная для каждого пользователя

TurboQuant

Модели unsloth с префиксом UD- используют TurboQuant — оптимизированную квантизацию, обеспечивающую:

  • Более быстрый инференс
  • Меньший размер модели
  • Минимальную потерю качества

Пример: unsloth/Qwen3.5-9B-GGUF:UD-Q4_K_XL — модель 9B параметров с квантизацией Q4_K_XL в формате TurboQuant.

Расширение базы знаний

Добавление документов

  1. Создайте файл .md в data/knowledge_base/:
# Пример: data/knowledge_base/testing_practices.md
  1. Формат файла — обычный Markdown:
# Тестирование ПО

## Виды тестирования

### Unit-тесты
Unit-тесты проверяют отдельные модули...

### Интеграционные тесты
Проверяют взаимодействие компонентов...
  1. Перезапустите бота — новые документы автоматически индексируются:
docker compose restart bot

Как работает индексация

  • Документы разбиваются на чанки по ~800 символов с перекрытием 150 символов
  • Каждый чанк получает эмбеддинг через paraphrase-multilingual-MiniLM-L12-v2
  • Чанки сохраняются в ChromaDB с метаданными (source, chunk_index)
  • При повторном запуске уже существующие чанки пропускаются (дедупликация по ID)

Рекомендации по документам

  • Используйте заголовки #, ##, ### для структуры
  • Разделяйте темы двойным переносом строки
  • Пишите на русском (модель эмбеддингов мультиязычная)
  • Оптимальный размер документа: 1000–5000 символов
  • Темы: Agile, Scrum, Kanban, DevOps, CI/CD, ГОСТы, управление проектами

Логирование

Каждый запрос генерирует структурированный JSON-лог в logs/bot.log:

{
  "trace_id": "uuid",
  "chat_id": 123,
  "inbound": {
    "telegram_message_id": 456,
    "text": "Привет, продолжим?",
    "received_at": "2026-03-30T12:00:00Z"
  },
  "context_window": {
    "messages": [
      {"id": "m0", "role": "system", "tokens": 150},
      {"id": "m1", "role": "user", "tokens": 20}
    ],
    "total_tokens": 500
  },
  "compression": {
    "strategy": "summary+state",
    "input_chars": 8000,
    "output_chars": 900,
    "summary_text": "...",
    "created_at": "2026-03-30T12:00:01Z"
  },
  "rag": {
    "query": "Что такое Scrum?",
    "num_results": 3,
    "used": true,
    "top_score": 0.82
  },
  "llm_call": {
    "model": "unsloth/Qwen3.5-9B-GGUF:UD-Q4_K_XL",
    "prompt": "...",
    "response": "...",
    "prompt_tokens": 600,
    "completion_tokens": 200,
    "latency_ms": 950
  },
  "completed_at": "2026-03-30T12:00:02Z"
}

Тесты

# Запуск тестов
python -m pytest tests/ -v

# С покрытием
python -m pytest tests/ --cov=app --cov-report=term-missing

# Текущее покрытие: 63%

Команды бота

Команда Описание
/start Приветствие + сбор обратной связи
/reset Сбросить контекст диалога
/feedback Оставить отзыв (оценка 1–5 + комментарий)
/help Список команд

Структура проекта

RAG/
├── docker-compose.yml       # Оркестрация сервисов
├── Dockerfile               # Образ бота
├── .env                     # Переменные окружения
├── .env.example             # Пример для пользователей
├── requirements.txt         # Python-зависимости
├── app/
│   ├── main.py              # Точка входа
│   ├── config.py            # Настройки (из .env)
│   ├── logger.py            # Структурированное логирование
│   ├── bot/
│   │   ├── handlers.py      # Обработчики Telegram
│   │   └── queue_manager.py # Очередь сообщений
│   ├── llm/
│   │   ├── client.py        # Клиент llama.cpp API
│   │   └── thinking.py      # Фильтр рассуждений
│   ├── rag/
│   │   ├── vectordb.py      # ChromaDB обёртка
│   │   └── pipeline.py      # RAG-пайплайн + промпт
│   ├── memory/
│   │   ├── context.py       # Формирование контекста
│   │   └── summary.py       # Сжатие в summary
│   └── storage/
│       └── persistence.py   # SQLite (сообщения, summary, feedback)
├── data/
│   └── knowledge_base/      # Markdown-документы базы знаний
├── tests/                   # Unit-тесты (79 тестов, 63% покрытие)
├── chroma_data/             # ChromaDB (Docker volume)
├── sqlite_data/             # SQLite (Docker volume)
└── logs/                    # Логи

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors