Files
scud_ai/docs/SCUD Orion AI — Полная энциклопедическая хроника, архитектурный паспорт и технический контекст (v4.0).md
T

32 KiB
Raw Blame History

SCUD Orion AI — Полная энциклопедическая хроника, архитектурный паспорт, разбор всех инцидентов и технический контекст проекта

Версия документа: 4.0 (Исчерпывающий монолитный контекстный паспорт для новой сессии)
Стек технологий и инфраструктура: Python 3.11+, FastAPI (Uvicorn), SQLite (WAL mode, PRAGMA synchronous=NORMAL, внешние ключи ON), Ollama REST API (Qwen 2.5:14b — основной текстовый агент и классификатор, Qwen 2.5-VL:7b-q8_0 / Qwen 3-VL:8b — OCR и зрение), MS SQL Server 2019/2022 (СКУД «Орион Pro» ЗАО НВП «Болид», 1С:ЗУП 3.1 через pyodbc / ODBC Driver 18), сетевая Samba-шара (/mnt/scud_share), Git/Gitea, HTML5 / Vanilla JS / Tailwind CSS.

---

1. Исходный бизнес-контекст, роли систем и фундаментальные задачи

Проект решает комплексную проблему контроллинга трудовой дисциплины, автоматического сопоставления кадровых фактов и защиты от рассинхронизации мастер-данных на предприятии со штатом ~270–276 сотрудников.

Источники первичных данных:

  • СКУД «Орион Pro» (Болид): База данных MS SQL Server (SERVER: 172.16.31.221\SQL, DB: Orion-14.01.21-1). Основные таблицы:
  • pLogData — журнал всех сырых физических транзакций турникетов, калиток и внутренних дверей. Ключевые поля: TimeVal (время сервера), DeviceTime (время контроллера), HozOrgan / Hrk (ID сотрудника), Event (код события: 26, 28, 32 — вход; 27, 29, 33 — выход; 54, 55, 64, 65 — внутренние считыватели), Mode (направление: 1 — IN, 2 — OUT), ReaderIndex, DoorIndex.
  • pList — реестр физических лиц и пропусков (ФИО, табельный номер, статус архива).
  • PDivision, PPost — справочники подразделений и должностей СКУД.
  • 1С:ЗУП 3.1 (Кадры): База данных MS SQL Server (SERVER: ACCOUNT-01, DB: ZUP30).
  • dbo._Reference299 — эталонный справочник сотрудников.
  • dbo._InfoRg16921 — периодический регистр сведений состояний сотрудников (отпуска основные, больничные, командировки, декретные отпуска, отпуска без сохранения оплаты).
  • Файловые выгрузки с сетевой шары /mnt/scud_share: файлы Штат_ДД_ММ_ГГГГ.xlsx (шапка 7–8 строк) и Отсутствия_ДД_ММ_ГГГГ.xlsx (шапка 3–4 строки).
  • Реестры статических исключений: static_reason_workers.csv (реестр удаленщиков и постоянных разъездных сотрудников), exceptions.json (декларативный фильтр обслуживающего персонала и спец-отделов).

---

2. Подробнейшая пошаговая хронология разработки, эволюция идей и разбор ошибок

Фаза 1: Первые эксперименты с LLM, выявление галлюцинаций и гибридная парадигма

  • Попытка передачи сырых списков в чат: Первоначальная попытка скормить модели Qwen 2.5:14b список из сотен ФИО с инструкцией «запомни список 1С» показала, что у LLM нет постоянной памяти между сессиями. Модель теряла контекст, путала фамилии и выдавала ответы с троеточиями ('Васильев Л.И.', ...) или придумывала несуществующие строки («ЛЕНМОРНИИПРОЕКТ ОЭС Варламова Мария»).
  • Ошибки openpyxl vs pandas: Первая генерация кода моделью использовала библиотеку openpyxl с построчным перебором ячеек, жестко зашитыми опечатками (поиск слова 'фиио') и падением по FileNotFoundError.
  • Переход к детерминированному пайплайну: Принято ключевое архитектурное решение — LLM не считает математику и не фильтрует 300 строк текста. Всю механическую работу (ETL, слияние, фильтрацию) выполняет быстрый детерминированный Python (pandas, SQL), а локальная LLM выступает исключительно в роли «умного ревизора» на этапе сопоставления сомнительного несовпавшего остатка (Diff).

Фаза 2: Нормализация ФИО, кодировки и коллизия совместителей (Кейс Балаевой О.Г.)

  • Символьные ловушки:
  • Латинские буквы-двойники (омоглифы a, c, e, o, p, x, y, случайно набранные в английской раскладке).
  • Служебные суффиксы в скобках, добавляемые 1С ((осн.), (совм.), (внешн.)).
  • Буквы ё/е, двойные пробелы, неразрывные пробелы \xa0 и случайный ввод цифры 0 вместо буквы О.
  • Функция normalize_fio(): Разработан строгий конвейер очистки:
    def normalize_fio(fio):
    if not fio or not isinstance(fio, str): return ""
    fio_clean = re.sub(r'\(.*?\)', '', fio) # Удаление скобок
    fio_clean = fio_clean.replace('\xa0', ' ')
    trans = str.maketrans('aceopxyABCEHKMOPTX', 'асеорхуАВСЕНКМОРТХ')
    fio_clean = fio_clean.translate(trans)
    fio_clean = fio_clean.replace('ё', 'е').replace('Ё', 'Е')
    return " ".join(fio_clean.strip().split()).title()
  • Коллизия 270 vs 271: В СКУД числилось 270 уникальных человек, а в 1С — 271 строка. Ручной разбор показал, что Балаева Ольга Геннадьевна занимает две ставки в 1С (Руководитель управления персоналом и Руководитель режимно-секретного отдела) при одном физическом пропуске в СКУД.
  • Решение: Внедрена обязательная группировка штата 1С по fio_clean с объединением должностей и подразделений через " / ".

Фаза 3: Защита Entity Resolution от однофамильцев (Инцидент с Семеновыми)

  • Сбой модели: При передаче несовпавших ФИО в Qwen 2.5 модель ошибочно сопоставила «Семенову Юлию Борисовну» (которая была на работе) с «Семеновой Диной Дмитриевной» (находившейся в отпуске), посчитав это опечаткой в имени из-за одинаковой фамилии. В результате Юлия Борисовна получила статус нарушителя («в отпуске, но пришла»).
  • Двухконтурная защита:
  1. В системный промпт ИИ зашито категорическое правило: однофамильцы с разными именами/отчествами — строго разные люди, объединение запрещено.
  2. В Python встроен дублирующий барьер: если фамилии совпадают, но инициалы/первые буквы имен различаются, связь ИИ принудительно аннулируется с логированием ⚠️ [Блокировка фейка].

Фаза 4: Декларативные исключения и синонимы отделов

  • Переход к exceptions.json: Исключение клининга, дворников, гардеробщиков и хозяйственного персонала отдела «ЭТО» вынесено из кода в конфигурационный файл exceptions.json (поддержка списков departments, positions, fio, position_keywords).
  • База синонимов отделов (department_synonyms): Для сопоставления сокращений СКУД с длинными названиями 1С (например, «ОВК» ⟷ «Отдел внутреннего контроля») создана таблица SQLite, автоматически обучаемая при подтверждениях оператора.

Фаза 5: Аппаратный сбой СКУД 04.08.2026, разгадка «исчезающих неизвестных» и Первая активность

  • Анатомия сбоя: Утром 04.08.2026 зависли регистраторы входа на главном КПП. У 119 сотрудников не записалось событие входа (time_in = 'Нет входа'). Из них 57 человек были официально закрыты документами 1С (отпуска, командировки). Оставшиеся ~74 человека реально пришли на работу, но утренней отметки не имели. Однако вечером сводка выдала всего 4–7 «неизвестных».
  • Вскрытие механизма ошибки: Было обнаружено, что скрипт агрегации видел дневные перемещения сотрудников (выходы на обед, считыватели туалетов, внутренние двери) и автоматически выставлял Статус = 'Присутствовал' и is_present = 1. Из-за этого люди попадали в категорию «Итого на работе», а массовый аппаратный сбой скрывался.
  • Внедрение «Первой активности»:
  1. В базу данных и выгрузки Excel добавлена колонка first_activity («Первая активность») — минимальное время любого события дня в здании (MIN(TimeVal) AS FirstRawEvent без учета направления двери).
  2. Если time_in == 'Нет входа', но first_activity != '—', записи присваивается anomaly_flag = 'ANOMALY_NO_IN_HAS_ACTIVITY', а is_present принудительно сбрасывается в 0.
  3. Внедрен модуль analyze_scud_mass_failure_ai(): при превышении порога в 5% смены (>10 человек) ИИ поднимает тревогу о массовом сбое контроллеров КПП.
  • Кейс Равина В.Э.: Сотрудник находился в официальном отпуске, утреннего входа не имел, но пришел после обеда (первая активность 14:11:06, выход 17:18:38). Система корректно зафиксировала истинную кадровую аномалию (физическое присутствие при официальном отпуске).

Фаза 6: Архитектурная миграция под Gitea и система срезов (снапшотов)

  • Безопасный рефакторинг: Монолит разделен на слои (core/, services/, scripts/, modules/web_api/) через git mv с сохранением истории коммитов в ветке refactor/modular-structure.
  • Формат ID снапшота: Введена схема [Y]YYYYMMDD-NNN (например, Y20260804-001 для вчерашнего зафиксированного вечернего среза на 22:00 и 20260805-002 для дневного).
  • Оптимизация экспорта: Если в SQLite уже зафиксирован вчерашний срез с префиксом Y, повторный тяжелый SQL-запрос к СКУД Орион не выполняется (функция has_yesterday_final_snapshot).
  • Инспекция и CLI: Написан инструмент scripts/db_cli.py с командами stats, snapshots, scud, absences, anomalies, rules, prompts, tools, sessions, dump, snapshot del.

Фаза 7: Web API, Generative UI, управление памятью LLM и Topic Drift Guard

  • FastAPI & Безопасность: Развернут Web API с JWT-авторизацией (bcrypt), изолированными задачами пользователей (tasks с привязкой к user_id), гостевым режимом и ролевой моделью.
  • Проблема деградации контекста LLM: Вывод объемных списков задач, текстов системных промптов и таблиц снапшотов засорял контекстное окно чата, приводя к галлюцинациям и «залипанию» модели на старых правилах.
  • Решение проблемы памяти (Topic Drift & Ephemeral Context):
  • В таблицу chat_messages добавлен флаг is_ephemeral = 1 для временных сообщений.
  • Введены двухфазные сессии (PROMPT_PREVIEW → PROMPT_FOLLOWUP) и детерминированный счетчик отвлечений idle_turns.
  • Context Guard: На 3-м шаге отвлечения оператора на сторонние темы система отвечает на вопрос и выводит интерактивное напоминание с кнопками [Завершить настройку] / [Показать промпт]. При idle_turns > 3 происходит автоочистка сессии вызовом db_purge_ephemeral_messages().
  • Fast-Path: Прямой перехват команд подтверждения («да», «подтверждаю», «сохранить») и выхода («нет, спасибо», «закончить настройку») без обращения к LLM (ответ за 0.05 сек).
  • Декларативный реестр действий (tool_action_registry): Хранение шаблонов ответов, типов кнопок и признаков эфемерности в SQLite.
  • Generative UI (Интерактивные карточки задач): Инструмент db_get_tasks возвращает полезную нагрузку TASK_INTERACTIVE_CARD. Фронтенд рендерит живой виджет с табами (Все / В работе / В планах / Завершенные), чекбоксами и inline-созданием задач через REST API без вызова LLM.

---

3. Полная схема базы данных SQLite (data/scud_orion_ai.db)

Таблица Назначение и бизнес-логика Полная структура колонок
scud_logs Хранение логов проходов СКУД, расчетного времени и снапшотов. id (PK), log_date, fio, fio_clean, department, position, time_in, first_activity, time_out, time_in_building, is_present, anomaly_flag, snapshot_time, snapshot_id, created_at
zup_staff Штатное расписание 1С:ЗУП на даты срезов. id (PK), snapshot_date, fio, fio_clean, department, position, created_at
zup_absences Официальные кадровые отклонения 1С (отпуска, больничные, командировки, декреты). id (PK), absence_date, fio, fio_clean, absence_type, created_at
anomalies_history Журнал выявленных кадровых и аппаратных аномалий. id (PK), anomaly_date, fio, anomaly_type, details, human_status, created_at
ai_knowledge_base Глобальные правила арбитража и приоритеты компании для ИИ. id (PK), rule_text, added_by, created_at
system_prompts Версионные системные промпты агента (активный промпт по is_active=1). id (PK), name, prompt_text, is_active, updated_at
tool_action_registry Декларативный реестр шаблонов, кнопок и настроек эфемерности инструментов. id (PK), tool_name, category, bypass_llm, success_template, follow_up_question, action_type, buttons_json, is_active, is_ephemeral, updated_at
session_states Активные состояния сессий, черновики и счетчик idle_turns. session_id (PK), state_type, pending_data, updated_at
chat_messages История диалогов с поддержкой разделения на постоянные и эфемерные сообщения. id (PK), session_id, role, content, is_ephemeral, created_at
tasks Реестр задач пользователей с привязкой к user_id. id (PK), task_id, module, title, priority, status, due_date, user_id, created_at
users Учетные записи операторов (хэши паролей bcrypt, права администратора). id (PK), username, password_hash, is_admin, full_name, created_at
department_synonyms База знаний соответствия аббревиатур СКУД полным названиям отделов 1С. id (PK), short_name, full_name, created_at
system_reference Справочник команд и примеров промптов для операторов. id (PK), category, title, example_prompt, description

---

4. Актуальная архитектура каталогов и назначение файлов

scud_ai/
├── config.py # Конфигурация: пути, расчет дат, URL Ollama, параметры MS SQL
├── exceptions.json # Декларативные фильтры исключений (ОВК, уборщики, подрядчики)
├── main_etl.py # Оркестратор ETL: экспорт СКУД/1С -> SQLite -> Excel/MD отчеты
├── project_code_snapshot.md # Полный исходный код всех файлов репозитория
├── core/
│ └── database.py # Драйвер SQLite (WAL), функции сохранения/загрузки срезов
├── services/
│ ├── scud_export.py # Прямой SQL-экспорт из MS SQL «Орион Pro»
│ ├── zup_extractor.py # Прямой SQL-экспорт из MS SQL 1С:ЗУП 3.1
│ ├── data_loader.py # Загрузка данных, нормализация ФИО, расчет первой активности
│ ├── data_validator.py # Проверка свежести и наличия файлов за Вчера и Сегодня
│ ├── excel_exporter.py # Генерация сводки и детального отчета в Excel (openpyxl)
│ ├── text_reporter.py # Построение итогового Markdown-отчета через Qwen 2.5
│ ├── ai_verifier.py # Модули ИИ-аудита, Fuzzy Matching и детекции сбоев СКУД
│ ├── feedback_loop.py # Интерактивный консольный модуль Human-in-the-Loop
│ ├── knowledge_base.py # Интерфейс работы с базой знаний правил
│ └── share_copier.py # Резервное скачивание файлов 1С с шары /mnt/scud_share
├── scripts/
│ ├── db_cli.py # CLI-утилита управления БД, снапшотами, дампами и сессиями
│ ├── fix_snapshots.py # Скрипт переиндексации и нормализации снапшотов
│ ├── init_tool_registry.py # Инициализация декларативного реестра инструментов
│ └── diagnostics/
│ ├── inspect_db.py # Диагностика структуры таблиц и количества записей
│ ├── inspect_ephemeral.py # Анализ распределения постоянных и эфемерных сообщений
│ ├── inspect_files.py # Аудит файлов и размеров на диске
│ └── show_tree.py # Вывод дерева каталогов
├── modules/web_api/
│ ├── main.py # Точка входа FastAPI приложения, роутеры и раздача статики
│ ├── routers/
│ │ ├── admin.py # Управление пользователями
│ │ ├── auth.py # JWT аутентификация и смена паролей
│ │ ├── chat.py # Эндпоинты диалогов (авторизованный и гостевой)
│ │ └── tasks.py # REST API управления задачами
│ ├── llm/
│ │ ├── agent.py # Координатор диалога, Tool Calls и Topic Drift Guard
│ │ ├── schemas.py # Описание JSON-схем инструментов для Ollama
│ │ ├── file_parser.py # Мультимодальный парсер файлов (PDF, PNG, XLSX, TXT)
│ │ ├── db_tools.py # Фасадные вызовы функций БД для агента
│ │ ├── core/
│ │ │ ├── calendar_utils.py # Формирование системного контекста дат и дней недели
│ │ │ ├── fast_path.py # Быстрый перехват команд подтверждения/отмены (0.05 с)
│ │ │ ├── ollama_client.py # HTTP-клиент взаимодействия с Ollama API
│ │ │ ├── prompt_merger.py # Парсинг и слияние правок системного промпта
│ │ │ └── tool_injector.py # Очистка сырых тегов и артефактов Tool Calls
│ │ └── db/
│ │ ├── connection.py # Подключение к scud_orion_ai.db
│ │ ├── db_chat.py # Сохранение истории и очистка эфемерных сообщений
│ │ ├── db_prompts.py # Системные промпты, стейты и реестр действий
│ │ ├── db_snapshots.py # Выборка и удаление снапшотов
│ │ └── db_tasks.py # CRUD операции с задачами пользователей
│ └── static/
│ ├── index.html # SPA разметка (модалки, чат, боковая панель задач)
│ ├── css/styles.css # Стили и мобильные оптимизации
│ └── js/
│ ├── app.js # Инициализация приложения
│ ├── auth.js # Логика входа, смены паролей и администрирования
│ ├── chat.js # Обработка сообщений, Drag&Drop, виджет задач и кнопки
│ └── tasks.js # Управление боковой панелью задач (Drawer)
└── docs/
└── development_roadmap.md # Стратегическая дорожная карта и архитектурный бэклог

---

5. Справочник команд командной строки (CLI Reference)

Главный конвейер контроллинга (main_etl.py)

  • python main_etl.py — стандартный дневной запуск: экспорт свежих данных СКУД и 1С, сохранение снапшота в SQLite, генерация Excel и Markdown отчетов.
  • python main_etl.py --skip-export — построение отчетов по последнему имеющемуся снапшоту из SQLite без повторного запроса к MS SQL.
  • python main_etl.py --snapshot 20260805-001 — точный расчет отчетов по указанному составному ID снапшота.
  • python main_etl.py -d — запуск в режиме расширенной отладки (DEBUG).

CLI-утилита управления SQLite базой данных (scripts/db_cli.py)

  • python scripts/db_cli.py stats — общая статистика количества записей по всем таблицам БД.
  • python scripts/db_cli.py snapshots [ДД.ММ.ГГГГ] — просмотр реестра снапшотов с сортировкой по времени создания (самые свежие сверху).
  • python scripts/db_cli.py scud [ДД.ММ.ГГГГ] [--snapshot ID] [--export-xlsx NAME] — просмотр логов СКУД и опциональный экспорт в Excel.
  • python scripts/db_cli.py absences [ДД.ММ.ГГГГ] — список кадровых отклонений из 1С:ЗУП.
  • python scripts/db_cli.py anomalies — история выявленных аномалий.
  • python scripts/db_cli.py rules — правила базы знаний компании.
  • python scripts/db_cli.py prompts — просмотр системных промптов из таблицы system_prompts.
  • python scripts/db_cli.py tools — вывод декларативного реестра действий инструментов и шаблонов кнопок.
  • python scripts/db_cli.py sessions — просмотр активных сессионных стейтов и висящих черновиков.
  • python scripts/db_cli.py snapshot del [ID] — удаление конкретного снапшота по ID.
  • python scripts/db_cli.py snapshot del --day [ДД.ММ.ГГГГ] — удаление всех снапшотов за выбранный день.
  • python scripts/db_cli.py dump [backup.xlsx] — полный дамп всех таблиц базы данных в многостраничный Excel-файл.

---

6. Стратегическая дорожная карта развития (Roadmap & Backlog)

  1. Масштабирование механизма эфемерного контекста на все инструменты (Rollout Roadmap):
  • Снапшоты (snapshots): Перевод вывода объемных таблиц срезов в эфемерный режим (is_ephemeral = 1), внедрение интерактивного подтверждения при удалении снапшотов по ID/дате через состояния SNAPSHOTS_PREVIEW / SNAPSHOTS_FOLLOWUP.
  • База знаний и аномалии (kb & anomalies): Вывод справочников команд, правил арбитража и списков аномалий исключительно во временный слой для исключения «залипания» модели на устаревших правилах из истории сообщений.
  • Декларативная унификация в tool_action_registry: Расширение схемы таблицы полями followup_state_type, auto_purge_on_exit, guard_question_template для устранения хардкода имен функций в agent.py.
  1. Модуль анализа внутридневных перемещений («Контроль перекуров»):
  • Анализ интервалов между событиями OUT (выход) и IN (возврат) по журналу pLogData.
  • Подсчет суммарного времени нахождения вне рабочего места в течение смены с отсечением технологической нормы (30–40 минут).
  • Вывод аналитического блока и злостных нарушителей в отдельный лист Excel-отчета и итоговую Markdown-сводку.
  1. Интерактивный Task Planner & Roadmap Engine:
  • Специализированный инструмент для ведения динамических проектных планов и чек-листов с чекбоксами ([ ] / [x]) прямо в диалоге с синхронизацией в таблицу tasks.
  1. Изолированная среда исполнения кода (Code Execution Sandbox):
  • Безопасный изолированный Docker/gVisor контейнер для динамического выполнения генерируемого моделью Python/Pandas кода на лету с возвратом stdout/stderr и графиков в контекст.
  1. Автоматизация расписания срезов и Telegram-алерты:
  • Автозапуск выгрузок в 12:00, 17:00 и 19:00 через systemd-таймеры с фиксацией snapshot_time.
  • Отправка мгновенных алертов о массовых сбоях турникетов (>5%) и критических кадровых конфликтах дежурному системному администратору в Telegram.