🤖 Как это работает?
Пять простых сценариев — от выбора коллекции до поиска. Нажми, чтобы развернуть.
📂 Выбор коллекции — рабочее пространство документов
📂 Как выбирается коллекция
Переключатель — в шапке сервиса (справа, рядом с кнопкой темы):
Выберите коллекцию: [test_docs ▾]. В списке — только рабочие коллекции сервиса (служебные npa/tech/default скрыты). Переключение мгновенное: весь сервис перестраивается под выбранную коллекцию без перезагрузки страницы. Если доступна одна коллекция — переключатель скрывается (она и так активна).- 🔄 Переключение валидируется: коллекция должна существовать в Qdrant, а у пользователя — быть назначенной (права проверяются и в UI, и на сервере);
- 🧩 У каждой коллекции — своё наполнение, свои настройки, справочники, промпты и история;
- 🆕 Для нового проекта — просто создайте коллекцию в Qdrant и назначьте её пользователю — она появится в списке.
🔗 Что завязано на коллекцию
- 📥 Загрузка документов — новые документы попадают в активную коллекцию;
- 🔍 Поиск по смыслу — ищет только внутри активной коллекции (+ порог точности — свой у каждой);
- 🧠 Классификация — соседи и тематики берутся из активной коллекции;
- 📸 Снапшоты — резервные копии активной коллекции;
- 📖 Справочники (тематики/отправители/получатели/типы) — свои на коллекцию;
- ⚙️ Настройки (контраст, порог, лимиты, теги) — свои на коллекцию;
- 📝 Промпты — свои на коллекцию;
- 📊 История классификаций и статистика — свои на коллекцию.
🗂️ Особенность: задачи работают локально
Очередь задач (загрузка → распознавание → анализ → загрузка в Qdrant) хранится локально у каждой копии сервиса и не синхронизируется между сервисами. Это сделано намеренно:
- 🖥️ Каждая копия сервиса обрабатывает только свои загруженные документы;
- 🚦 Не возникает «войны за очередь» — две копии не пытаются обработать одну задачу;
- 💾 Конфигурация (справочники, настройки, промпты, история) — общая через MySQL, а задачи — локальные;
- ℹ️ При переключении коллекции очередь задач не меняется — это технический журнал обработки, не данные коллекции.
⚙️ Настройка — один раз, чтобы система говорила на вашем языке
📖 Справочники
(вкладка «Справочники») — замкнутые списки, из которых система обязана выбирать. Нейросети запрещено сочинять свои значения:
- 🏷️ Тематики — перечень тем для классификации («МРГ 1279», «ФСТЭК», «ГИС ГМП»...). Чем точнее список, тем чётче разделение документов;
- 🏢 Отправители — организации, от которых приходят письма. Реквизиты стандартизированы: «Минэк», а не «Министерство экономического развития РФ»;
- 📬 Получатели — организации-адресаты;
- 📥 Типы документов — письма, приказы, протоколы, соглашения...
⚙️ Параметры загрузки
(Настройки → «📤 Загрузка»)
- 📄 Лимит страниц загрузки (max_pages_load) — сколько первых страниц PDF обрабатывать при загрузке в хранилище. 0 = весь документ. Если документ длиннее лимита — сервис предупредит «в хранилище попадёт только начало». Полезно для больших файлов: экономит время распознавания;
- 🏷️ Автотеги при загрузке (auto_tags) — записывать ли предложенные нейросетью теги сразу в хранилище, или вы решаете сами при проверке карточки.
🧠 Параметры классификации
(Настройки → «Классификация»)
- 🏷️ Предложения тегов (tag_suggestions) — показывать ли нейросетевые теги при классификации (бейджи в карточке результата);
- 🎚️ Контраст (contrast) — 1..100, насколько резко «выпячивать» главную тематику: высокий контраст делает разницу между основной темой и остальными более драматичной (100 = почти всегда 100% у лидера), низкий — распределение вероятностей более ровное, когда темы похожи;
- ⚖️ Поправка на частоту темы (IDF) — всегда глобальная — защита от перекоса базы. Если одной темы в коллекции много, а другой мало — без поправки частая тема почти всегда выигрывает. Поправка делит вес темы на √log(1 + число её документов по всей коллекции): редкие темы не тонут, частые не доминируют. Насыщение — темы с числом документов ≥ порога штрафуются одинаково (настраивается, кэшируется при выборе коллекции);
- 👥 Бонус поддержки (support_boost) — вклад каждого дополнительного документа темы в топ-10 соседей: тема «большинства» становится увереннее одиночной;
- 🔑 Бонус ключевых слов (kw_boost / dir_kw_boost) — мягкий бонус (по умолчанию 0.05) за каждое найденное в тексте ключевое слово из справочника (кап 4 слова). Раздельные слайдеры: для тем и для направлений (направления используют свои ключевые слова на этапе каскада);
- 📄 Лимит страниц классификации (max_pages) — 1..10: сколько страниц текста «видит» классификатор (объём текста и число чанков растут вместе). Больше — точнее, но дольше.
📝 Промпты
(Настройки → «Промты») — тексты заданий для нейросети:
- 📝 Реквизиты и содержание — извлечение даты, номера, отправителя, получателя, темы + краткое содержание (при загрузке);
- 💡 Обоснование тематики — почему выбрана именно эта тема;
- 📝 Краткое содержание (классификация) — summary для вкладки классификации;
- 🏷️ Автотеги — генерация тегов-предложений.
🗄️ Коллекция
(Настройки → «Коллекция»; переключатель коллекций — в шапке) — резервные копии и точность поиска:
- 📸 Создать снапшот — мгновенная резервная копия коллекции (≈1 сек, ~600 МБ). Рекомендуется после каждого массового наполнения;
- ⬆️ Загрузить снапшот — восстановить коллекцию из копии (заменяет текущую! подтверждение перед запуском). Восстановление занимает 2–3 секунды;
- 🗑 Удалить снапшот — освободить место (каждый ~600 МБ);
- 💡 Зачем снапшоты: защищают от потери данных — например, при сбое или случайном удалении документов. Храните 2–3 последних;
- 🎯 Порог точности поиска (0–100%) — фильтр для поиска по смыслу в коллекции: показываются только документы со сходством не ниже порога. 0% = без отсечки (показывать всё). Чем выше порог — тем меньше «мусора», но можно потерять погранично похожие документы. Рекомендация: 60–80%.
💡 Важно: к промптам «Реквизиты» и «Обоснование» сервис автоматически дописывает блок «ДОСТУПНЫЕ ЗНАЧЕНИЯ» из справочников — нейросеть обязана выбирать отправителя/получателя/тематику только из ваших списков. В редактируемый текст промпта этот блок не попадает.
📥 Наполнение коллекции — загрузите PDF, дальше всё само
Коллекция — семантическое хранилище: документы лежат «по смыслу» (векторами), у каждого — структурированная карточка. Каждый документ проходит цепочку статусов:
🕐
В очереди
Документ принят, ждёт распознавания
→
⏳
Распознавание
GPU читает PDF; если длиннее лимита — предупреждение
→
🧠
Анализ
Реквизиты + тематика по похожим документам
→
✅
Готово
Карточка открыта для проверки и правок
→
📤
Загрузка в Qdrant
Эмбеддинг + запись в хранилище (виден прогресс %)
→
🚀
В хранилище
Терминальный ✅ — готов к поиску
❌
Ошибка
Терминальный — с причиной; можно повторить
⛔
Отменено
Терминальный — остановлено вручную
🔴 Терминальные статусы — конечные точки жизненного цикла: документ больше не обрабатывается автоматически (🚀 в хранилище / ❌ ошибка / ⛔ отменено).
⚙️ Всю цепочку выполняет единый воркер (одна очередь, FIFO): распознавание, анализ, а загрузку в Qdrant кнопка просто ставит в очередь — ответ приходит мгновенно, прогресс виден в таблице задач. Анализ (реквизиты + теги + тематика) идёт параллельно через пул из 2 конкурентных LLM-исполнителей. При рестарте сервиса обработка продолжается с контрольных точек (распознанный текст и реквизиты сохраняются) — ничего не пересчитывается и не теряется.
✏️ Редактирование метаданных — два уровня
- Карточка при загрузке (статус «✅ Готово»): открывается форма с полями — тематика, дата, номер, тип, отправитель, получатель, ссылка на документ, теги, краткое содержание. Правки сохраняются кнопкой «💾 Сохранить мету» до отправки в хранилище. Там же — кнопка «🚀 В Qdrant» (с проверкой дубликатов) и «🔁 Перезапустить воркер» при сбоях;
- Прямо в коллекции (вкладка «Коллекция», статус «🚀 В хранилище»): у любого документа справа — карандашик ✏️. Открывается режим редактирования: те же поля (ссылка, тема, тип, дата, номер, отправитель, получатель) + теги (✕ удалить / «+» добавить) + 🗑 удалить документ. Изменения мгновенно пишутся во все фрагменты документа (даже если их 2500) и сразу доступны для поиска и классификации. Число чанков не редактируется — это факт хранения.
🧠 Классификация — для новых документов, которых ещё нет в хранилище
⚙️ Процесс
Автоматически, ~0.5–2 минуты. На вкладке — 3 плитки прогресса:
- 🖼️ OCR (жёлтая — идёт, зелёная — готово) — распознавание текста через Marker. Классификация имеет приоритет: при старте она сбрасывает Marker — задачи очереди отменяются (их можно перезапустить «Повторить»), а ваш документ распознаётся первым;
- 🔍 VECTOR — эмбеддинг текста (e5-large, 1024) и поиск соседей в Qdrant;
- 🧠 LLM — нейросеть пишет обоснование и краткое содержание (параллельно с другими LLM-задачами через пул из 2 конкурентных исполнителей).
Ошибка любого этапа — плитка краснеет, ответ не поступит.
🎯 Как выбирается тема
- Текст (первые N страниц, настройка «Страниц для классификации» 1–10) режется на чанки по 1200 символов — чем больше страниц, тем больше чанков (10 страниц ≈ 17 чанков) — и превращается в векторы (модель e5-large, 1024 измерения);
- Для каждого чанка ищутся 25 ближайших соседей в активной коллекции (параллельно, до 6 потоков);
- Нормализация: от одного документа берётся не более 3 чанков — «Гиганты» (документы на сотни страниц) не заглушают остальные;
- Остаётся топ-10 уникальных документов; у каждой темы берётся лучший score соседа (тема с 10 посредственными соседями не побеждает тему с одним отличным);
- Поправка на частоту (IDF) — всегда глобальная: вес темы делится на √log(1 + число её документов в коллекции), знаменатель не бывает меньше 1 (одиночная тема не усиливается); насыщение — темы с числом документов ≥ порога штрафуются одинаково. Порог и бонус поддержки — настраиваемые, есть кнопка «🧮 Рассчитать автоматически» (по распределению частотности тем и направлений);
- Поддержка (kNN-голосование): каждый дополнительный документ темы в топ-10 добавляет бонус к весу (настраивается) — тема «большинства» увереннее одиночной;
- Ключевые слова (из справочника): слова-основы из «ключевых слов» темы, найденные в тексте (например, «уязвимост» ловит уязвимости/уязвимостей), дают мягкий бонус (по умолчанию 0.05 за слово, кап 4 слова) — доводка там, где эмбеддинги слабы, но маркерные слова совпадают. Направления и темы имеют раздельные ключевые слова и бонусы;
- Каскад «направление → тема»: направление определяется тем же принципом на уровне направлений — лучший score соседа направления (не сумма!) + своя поправка IDF (по числу файлов направления, своё насыщение), своя поддержка и свои ключевые слова направления. Затем основная тема выбирается только среди тематик этого направления, вероятности нормируются по направлению;
- Веса проходят через контраст (настройка) → вероятности тематик;
- Нейросеть пишет обоснование, сверяясь со справочниками отправителей/получателей.
📦 Результат — три карточки
- 📄 Информация о документе — превью первой страницы (живёт 2 минуты — защита от несанкционированного просмотра), ID задачи, имя, размер, краткое содержание, теги;
- 📊 Результат классификации — 🎯 основная тематика с процентом уверенности, 💡 обоснование, 📈 возможные тематики, 🔍 похожие документы;
- ✅ Оценка — вы оцениваете правильность, накапливается статистика качества. Если верной темы нет в предложенных — выберите «Нет правильной темы» и укажите правильную из справочника: она сохранится в историю (колонка «Правильная тема») и поможет точнее оценивать качество классификации;
🔌 API для разработчиков
Вкладка «🔌 API», авторизация — Basic Auth реквизитами учётной записи
POST /api/v1/classify — классификация PDF (multipart, поле file), синхронно (1–5 мин): направление + тематика + вероятности + обоснование + «возможные тематики направления» + «иные возможные тематики» + похожие документы; требует collection (обязательный параметр)
POST /api/v1/eval — оценка результата по task_id (1 = верна, 2 = среди предлагаемых, 3 = нет верной)
GET /api/v1/health — проверка доступности
POST /api/v1/eval — оценка результата по task_id (1 = верна, 2 = среди предлагаемых, 3 = нет верной)
GET /api/v1/health — проверка доступности
💡 Каждая классификация (и из UI, и из API) попадает в «Историю классификации» с пометкой источника — оценки можно выставлять и там, и через API.
🔍 Поиск — три способа найти документ
🔍 Три способа найти документ
| Способ | Как работает | Пример |
|---|---|---|
| 🎯 По смыслу | Фраза или вопрос превращаются в вектор — находятся документы с похожим содержанием, даже если слова не совпадают. В таблице результатов — колонка «Сходство»: зелёное ≥80% — почти наверняка то, что искали | «продление лицензии на ветеринарную деятельность» найдёт письма об этом другими словами |
| 🏷️ По тегам | Точное совпадение меток | всё с тегом «срочно» |
| 📋 По реквизитам | Фильтры по структурированным полям | тематика = «ФСТЭК» + отправитель = «Минэк» + дата за период |
💡 Фильтры комбинируются. А блок «Похожие документы» в классификации — тот же поиск по смыслу, применённый автоматически.
📊 Статистика сервиса
—
🧭 Направлений в базе
—
🏷️ Тематик в базе
—
📄 Документов в коллекции
—
🧠 Проведено классификаций
1️⃣ Загрузи PDF
Перетащи PDF сюда или нажми для выбора
распознавание через Marker OCR
распознавание через Marker OCR
🧠 Классификация документа
Загрузи PDF — он будет распознан через Marker, найдены похожие документы в Qdrant, и по ним определена наиболее вероятная тематика.
Перетащи PDF сюда или нажми для выбора
📈 Распределение оценок
🗒️ Оценки
| Дата | Файл | Основная тема | Score | Источник | Оценка | Правильная тема | task_id |
|---|
📖 Справочники
Табличное управление: добавление, переименование, удаление значений. Сохраняется в SQLite.
🧭 Направления
| Значение |
|---|
🏷️ Тематики
| Значение | Направление |
|---|
🏢 Отправители
| Значение |
|---|
📬 Получатели
| Значение |
|---|
📥 Типы документов
| Значение |
|---|
📊 Распределение по направлениям
🗄️ Документы в хранилище
| Сходство | Ссылка | Направление | Тема | Тип | Дата | Номер | Отправитель | Получатель | Теги | Чанков | Добавлен |
|---|
🩺 Статус сервисов
Состояние зависимых сервисов на ПК.
| Сервис | Статус |
|---|
🗄️ Коллекция
Снапшоты и точность поиска. Коллекция переключается в шапке сервиса (Выберите коллекцию).
В коллекции показываются только документы со сходством не ниже порога. 0% — показывать всё.
| Название | Точек | Документов | Размер | Создан | Действия |
|---|---|---|---|---|---|
| Загрузка... | |||||
Снапшотов пока нет. Нажмите «Создать снапшот», чтобы сделать резервную копию коллекции.
📤 Загрузка
Поведение при загрузке документов.
Qwen предлагает теги при распознавании — кликабельные бейджи в форме. Подсказки не пишутся в Qdrant сами по себе.
При включении автотеги (предложенные Qwen) автоматически записываются в Qdrant вместе с пользовательскими. Пользовательские теги записываются всегда.
В Qdrant загружаются только первые N страниц документа. 0 = весь документ.
🧠 Классификация
Тематика по соседям + обоснование выбора (Qwen).
Чем выше — тем резче разница между темами: лидер усиливается, аутсайдеры гаснут. 1 — без контраста.
🏷️ Поправки для тем
⚖️ Поправка на частоту темы (IDF) — всегда по всей коллекции (глобально, кэш).
Темы с числом файлов ≥ порога штрафуются одинаково. 1 — одиночные темы тоже штрафуются; 3-5 — типично для небольших баз; выше — для больших коллекций.
Каждый файл темы в топ-10 добавляет бонус к score. 0 — только близость; 0.05 — поддержка заметно влияет.
Слова из ключевых слов темы (справочник), найденные в тексте, усиливают её score (кап 4 слова). 0 — не учитывать.
🧭 Поправки для направлений
Направления с числом файлов ≥ порога штрафуются одинаково. Число файлов направления = сумма файлов его тем.
Каждый файл направления в топ-10 соседей добавляет бонус к весу направления.
Слова из ключевых слов направления (справочник), найденные в тексте, усиливают его вес (кап 4 слова). 0 — не учитывать.
Сколько страниц текста «видит» классификатор (≈2000 символов на страницу): объём текста и число чанков растут вместе с лимитом. Больше — точнее, но дольше (до ~1 мин).
🗑️ Очистка истории оценок классификации:
📝 Промты
Редактирование промтов LLM. Применяются сразу при следующем вызове.
🔌 API классификации
Публичный REST API для классификации PDF-документов. Отдельная авторизация — не путать с логином админа.
🌐 Базовый URL
https://owl.seganim.ru
🔑 Авторизация
| Тип | Логин | Пароль |
|---|---|---|
| Basic Auth | логин УЗ | пароль УЗ |
Реквизиты любой УЗ, чья роль имеет доступ к вкладке «🔌 API». Заголовок:
Authorization: Basic base64(логин:пароль)📄 Метод: POST /api/v1/classify
| Параметр | Тип | Обязательный | Описание |
|---|---|---|---|
file | file (multipart/form-data) | ✅ | PDF-файл для классификации |
collection | строка (multipart/form-data) | ✅ | Коллекция Qdrant для поиска соседей (не зависит от коллекции, установленной в приложении) |
Время ответа: 1-5 мин (Marker OCR + эмбеддинги + Qwen).
📦 Ответ (JSON)
{
"collection": "test_docs",
"file": "письмо.pdf",
"task_id": "cls_1786879199882",
"direction": "Межведомственное взаимодействие",
"main_topic": "ФНС - ЕГРЮЛ и ЕГРИП",
"main_topic_score": 0.71,
"rationale": "Документ отправлен ФНС и содержит информацию о регистрации в СМЭВ3 видов сведений из ЕГРЮЛ и ЕГРИП...",
"tags": ["СМЭВ", "ЕГРЮЛ"],
"summary": "Письмо ФНС о переходе на новые форматы ЕГРЮЛ/ЕГРИП в СМЭВ3...",
"direction_topics": [
{"topic": "Минфин и Казначейство - ГИС ГМП", "score": 0.29}
],
"topics": [
{"topic": "ФНС - ЕГРЮЛ и ЕГРИП", "score": 0.71},
{"topic": "Совещание по разрешительной деятельности", "score": 0.18}
],
"neighbors": [
{"date": "2026-08-10", "doc_number": "12-45/2026", "sender": "ФНС", "topic": "ФНС - ЕГРЮЛ и ЕГРИП", "score": 0.99}
]
}
direction — основное направление (каскад: направление → тема внутри него); direction_topics — возможные тематики направления (без основной); topics — все кандидаты (включая «иные возможные тематики»); task_id — ID задания для оценки через /api/v1/eval.✅ Метод: POST /api/v1/eval
| Параметр | Тип | Обязательный | Описание |
|---|---|---|---|
task_id | string | ✅ | ID задания из ответа classify — файл, тема и score берутся из истории автоматически |
correctness | int | — | 1 = основная верна, 2 = верна среди предлагаемых, 3 = нет верной |
Ответ:
{"ok": true, "id": 58, "task_id": "cls_...", "correctness": 1, "updated": true} · если task_id не найден — 404🩺 Метод: GET /api/v1/health
Проверка доступности API.
{"status": "ok", "service": "doc-manager-classify", "version": "1.0"}
🧪 Тест-кейс (curl)
# Проверка здоровья
curl -u ЛОГИН:ПАРОЛЬ https://owl.seganim.ru/api/v1/health
# Классификация PDF (collection — обязателен!)
curl -u ЛОГИН:ПАРОЛЬ -X POST \
https://owl.seganim.ru/api/v1/classify \
-F "file=@/путь/к/документу.pdf" \
-F "collection=test_docs"
# Оценка результата (task_id — из ответа classify)
curl -u ЛОГИН:ПАРОЛЬ -X POST \
https://owl.seganim.ru/api/v1/eval \
-H "Content-Type: application/json" \
-d '{"task_id":"cls_...","correctness":1}'
Python:
import requests
r = requests.post(
"https://owl.seganim.ru/api/v1/classify",
auth=("ЛОГИН", "ПАРОЛЬ"),
files={"file": open("документ.pdf", "rb")},
timeout=600,
)
print(r.json())
👤 Учётная запись
Информация о текущем пользователе и смена реквизитов доступа.
ℹ️ Информация об учётной записи
| Параметр | Значение |
|---|---|
| Пользователь | — |
| Роль | — |
📂 Доступные коллекции
—
🧭 Доступные разделы
—
✏️ Изменение реквизитов
👑 Админка
Управление пользователями, ролями и доступными коллекциями.
👥 Пользователи
➕ Новый пользователь
🎭 Роли и доступ к вкладкам
➕ Новая роль