Skip to main content
Glama
ITIS Navigator MCP Server

ITIS Navigator MCP Server

README.md
# ИТИС Навигатор

Локальный помощник по документам ИТИС КФУ на Python с RAG, Qwen3:4b и настоящим
MCP-сервером. Документы индексируются локально, а ответы проверяются по JSON-схеме
и сопровождаются ссылками на найденные фрагменты. Проект не является официальным сервисом КФУ.

## Требования

- Windows 11, Python 3.12 или 3.13; код поддерживает Python >=3.11.
- [Git](https://git-scm.com/downloads/win) для клонирования.
- [Ollama для Windows](https://ollama.com/download/windows) и модель `qwen3:4b`.
- Интернет для первой установки Python-пакетов, скачивания моделей и получения документов.
  После загрузки поиск и Qwen работают локально; расписание требует сети.
- NVIDIA GPU не обязательна. Эмбеддинги работают на CPU. Генерация Qwen на CPU
  может быть заметно медленнее; скорость зависит от памяти, процессора и ускорителя.
  Оставьте несколько гигабайт диска для Python-зависимостей и эмбеддингов, отдельно — для Qwen.

Основной RAG не требует Docker, Node.js, Google API, GitHub-токена или ключей
OpenRouter/Gemini. Node.js >=22.13 и npm нужны только для необязательного расписания.

## Установка

Команды выполняются в PowerShell. Активация окружения, права администратора и
изменение глобальной ExecutionPolicy не нужны.

1. Склонируйте репозиторий и перейдите в него:

   ```powershell
   git clone https://github.com/AveryanovKirill/itis-navigator-rag.git
   cd itis-navigator-rag
   ```

2. Создайте **своё** окружение и установите зависимости. Если установлен Python 3.13,
   замените `-3.12` на `-3.13`:

   ```powershell
   py -3.12 -m venv .venv
   .\.venv\Scripts\python.exe -m pip install --cache-dir .cache/pip -r requirements-lock.txt
   .\.venv\Scripts\python.exe -m pip check
   Copy-Item .env.example .env
   $env:PYTHONIOENCODING = 'utf-8'
   ```

   Не перезаписывайте существующую `.env`. `requirements-lock.txt` фиксирует
   версии зависимостей; `requirements.txt` содержит допустимые диапазоны.

3. Установите и запустите Ollama, затем загрузите Qwen:

   ```powershell
   ollama pull qwen3:4b
   ```

   Это загрузка модели на вашем компьютере, а не обращение к облачной генерации.
   Если фоновая Ollama не запущена, откройте приложение или `ollama serve` в отдельном окне.

4. Подготовьте документы. Полные копии материалов КФУ и готовый индекс с ними
   не распространяются в репозитории. Адреса, ограничения и ручной способ описаны
   в [SOURCES.md](SOURCES.md). Для получения официальных текстов в пустую `docs/`:

   ```powershell
   .\.venv\Scripts\python.exe -m src.bootstrap --fetch-official
   ```

   Первая загрузка эмбеддингов требует доступа к Hugging Face; `HF_HUB_OFFLINE=1`
   на этом этапе **не нужен**. Импорт не обходит ограничения сайта. Если сайт недоступен,
   сохраните разрешённые UTF-8 `.txt`/`.md` в `docs/`, заполните `data/sources.json`
   по `data/sources.example.json` и выполните:

   ```powershell
   .\.venv\Scripts\python.exe -m src.bootstrap
   ```

   Создаются chunks и NumPy-индекс. Уже готовый совместимый индекс проверяется без
   перестроения. Для намеренного обновления корпуса вашей копии используйте
   `--rebuild-index`. Стартовый THRESHOLD из `.env.example` требует проверки на новых данных.

5. Проверьте Ollama и наличие модели без генерации:

   ```powershell
   .\.venv\Scripts\python.exe -m src.cli doctor
   ```

Альтернатива шагам установки Python-зависимостей и индекса — `./setup.ps1 -FetchOfficial`.
Он создаёт `.venv`, устанавливает зависимости, создаёт `.env`, получает тексты при пустой
`docs/`, загружает эмбеддинги и готовит отсутствующий индекс. Ollama устанавливается
отдельно, Qwen загружается командой выше. Скрипт не меняет глобальные настройки Windows.
Если политика PowerShell запрещает локальные `.ps1`, используйте пошаговые команды Python;
обход или изменение политики не требуется.

## Запуск

В `.env` по умолчанию `LLM_PROVIDER=ollama`, адрес — `OLLAMA_BASE_URL=http://127.0.0.1:11434`.
Модель зафиксирована как `qwen3:4b`. На медленном CPU можно увеличить
`OLLAMA_TIMEOUT_SECONDS`; ускорение от этого не появляется. API-ключи для этих команд не нужны.

```powershell
# Проверка сервера и наличия Qwen, без генерации
.\.venv\Scripts\python.exe -m src.cli doctor

# Настоящий поиск по сохранённому индексу, без LLM
.\.venv\Scripts\python.exe -m src.cli search 'К какому заместителю директора ИТИС обращаться по академическим стипендиям?'

# Одинаковый вопрос без документов и с RAG
.\.venv\Scripts\python.exe -m src.cli ask v1 'К какому заместителю директора ИТИС обращаться по академическим стипендиям?'
.\.venv\Scripts\python.exe -m src.cli ask v2 'К какому заместителю директора ИТИС обращаться по академическим стипендиям?'

# initialize/list_tools/call_tool настоящего MCP по stdio, без LLM
.\.venv\Scripts\python.exe -m src.cli mcp-check 'К какому заместителю директора ИТИС обращаться по академическим стипендиям?'

# Тесты алгоритмов, схем и MCP; модель для unit-тестов не нужна
.\.venv\Scripts\python.exe -m pytest -q
```

По желанию используйте оболочку: `./run.ps1 doctor` или `./run.ps1 --help`.
`v1` намеренно не получает документы и может отказаться отвечать; `v2` использует
MCP-поиск. Наличие номера источника ещё не доказывает правильность каждого утверждения.
Актуальность сохранённых правил проверяйте по официальному источнику и области применения.

Для необязательного расписания выполните `./scripts/setup_schedule.ps1`, затем
`python -m src.cli schedule 11-307 понедельник` через Python из `.venv`.
Без этой настройки основной RAG продолжает работать. Источник и ограничения
расписания описаны в SOURCES.md; точное «завтра» не гарантируется без проверки условий.

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

```text
src/          эмбеддинги, нарезка, индекс, поиск, MCP, Qwen, схемы и CLI
prompts/      системные инструкции
scripts/      настройка необязательного инструмента расписания
docs/        локальные разрешённые UTF-8 документы; изначально пусто
index/        локально создаваемые chunks, векторы и метаданные
data/        локальные сведения об источниках и исходные загрузки
eval/        место для собственных вопросов и эталонов
reports/      локальные результаты команд; не публикуются
tests/       алгоритмы, схемы, API и реальное MCP-соединение
setup.ps1     первый запуск и подготовка отсутствующего индекса
run.ps1       оболочка основного CLI
```

Документы, индекс, кэши и результаты команд исключены из Git. Вымышленные данные
в `tests/fixtures/demo/` предназначены только для тестов и не становятся правилами КФУ.

## Как работает система

Вопрос пользователя → MCP `search_docs` → эмбеддинг вопроса → векторный поиск NumPy →
до трёх фрагментов → Qwen3:4b → проверка JSON Pydantic → ответ с источниками.
Поиск выполняется внутри MCP-инструмента, клиент соединяется с отдельным процессом
через stdio официального Python SDK MCP. Для ручного запуска сервера: `python -m src.mcp_server`
из `.venv`; он ожидает MCP-сообщения, это не интерактивный чат.

Документы сначала нарезаются по 800 символов с перекрытием 150. Одна и та же
`intfloat/multilingual-e5-small` кодирует документы и вопросы в 384-мерные векторы.
Векторы нормализованы; скалярное произведение даёт косинусное сходство. Индекс хранится
на диске. Qwen не обучается заново: найденный текст добавляется в контекст запроса.
Данные документов не должны переопределять системные инструкции.

## Частые проблемы

- **Ollama не запущена:** откройте приложение, проверьте адрес в `.env`, выполните `doctor`.
- **Qwen не скачана:** выполните `ollama pull qwen3:4b`. Проект не выбирает другую модель автоматически.
- **Не найдены Python-модули:** используйте именно `.venv/Scripts/python.exe` и повторите установку зависимостей.
- **Не скачались эмбеддинги:** проверьте доступ к Hugging Face; уберите `HF_HUB_OFFLINE=1`
  для первой загрузки и выполните `python -m src.bootstrap --download-embeddings-only` из `.venv`.
- **Нет индекса:** добавьте документы и выполните `python -m src.bootstrap`. После осознанного
  изменения корпуса или модели индекса используйте `--rebuild-index` в своей копии.
- **Медленно без GPU:** это допустимый режим. Закройте лишние приложения, дождитесь
  первой загрузки Qwen и при необходимости увеличьте timeout. Одинаковая скорость на разных ПК не обещается.