feat(llm): переход на реляционные узлы промпта, db_cli context и очистка от регулярок
This commit is contained in:
@@ -0,0 +1,185 @@
|
||||
# **PROJECT BRAIN: SCUD Orion AI & Context API (Master Technical & Architectural Manifesto)**
|
||||
|
||||
**Версия документа:** 5.0 (Ultimate Developer & LLM Context Engine)
|
||||
**Назначение:** Исчерпывающий контекстный дамп проекта для немедленного продолжения разработки в любой передовой LLM без потери исторического контекста, с полным пониманием бизнес-логики, схем баз данных, подводных камней и нерешенных задач.
|
||||
|
||||
## ---
|
||||
|
||||
**1\. Архитектурный паспорт и инфраструктурный профиль**
|
||||
|
||||
| Компонент | Параметры и стек |
|
||||
| :---- | :---- |
|
||||
| **Среда и ОС** | Linux Docker Home (Debian/Ubuntu), Python 3.11/3.12 в виртуальном окружении venv, Git/Gitea. Разработка ведется через VS Code Remote-SSH. |
|
||||
| **Локальная СУБД проекта** | SQLite (data/scud\_orion\_ai.db), режим PRAGMA journal\_mode \= WAL, PRAGMA synchronous \= NORMAL, PRAGMA foreign\_keys \= ON. |
|
||||
| **СКУД Источник (MSSQL)** | MS SQL Server 172.16.31.221\\SQL (база Orion-14.01.21-1), драйвер ODBC Driver 18 for SQL Server (TrustServerCertificate=yes, Encrypt=no). Доступ через pyodbc. |
|
||||
| **1С:ЗУП 3.1 Источник (MSSQL)** | MS SQL Server ACCOUNT-01 (база ZUP30, пользователь scud\_reader). Прямое чтение таблиц dbo.\_Reference299 (сотрудники) и dbo.\_InfoRg16921 (состояния отсутствий). Резервная Samba-шара: /mnt/scud\_share. |
|
||||
| **Локальный контур LLM** | Ollama на http://192.168.11.3:11434 (GPU NVIDIA RTX 5070 Ti 16GB). Модель qwen2.5:14b (основной агент, Function Calling, анализ аномалий), qwen2.5vl:7b-q8\_0 (OCR документов/картинок). |
|
||||
| **Web API & Фронтенд** | FastAPI (Uvicorn), JWT (HS256, 30 дней), Passlib (bcrypt). Фронтенд: Single Page Application (HTML5, Tailwind CSS, Vanilla JS) с Generative UI виджетами. |
|
||||
|
||||
## ---
|
||||
|
||||
**2\. Энциклопедия подводных камней, инцидентов и принятых инженерных решений**
|
||||
|
||||
### **2.1. Галлюцинации LLM и переход к парадигме Python-Driven Diff**
|
||||
|
||||
> * **Проблема:** Попытка передать списки в 300 ФИО напрямую в промпт модели с командой «сравни списки» приводила к потере контекста, выдуманным опечаткам (*«ЛЕНМОРНИИПРОЕКТ ОЭС Варламова Мария»*) и плейсхолдерам ('Васильев Л.И.', ...).
|
||||
> * **Решение:** Утверждена строгая гибридная схема:
|
||||
1. **Детерминированный слой (Python / Pandas / SQL):** читает файлы, нормализует строки, агрегирует совмещения и мгновенно находит 95%+ точных соответствий.
|
||||
2. **Интеллектуальный слой (Qwen 2.5:14b):** вызывается *только на спорный несовпавший остаток* (1–5 записей) в виде строгого JSON-интерфейса Entity Resolution.
|
||||
|
||||
### **2.2. Символьная нормализация и кадровые совмещения (Кейс Балаевой О.Г.)**
|
||||
|
||||
> * **Проблема символов:** Латинские омоглифы (буквы клавиатуры a, c, e, o, p, x, y вместо русских), разделители 1С в скобках ((осн.), (совм.), (внешн.)), неразрывные пробелы \\xa0, буква ё и случайный ввод цифры 0 вместо буквы О.
|
||||
> * **Решение (normalize\_fio):** Очистка скобок через регулярное выражение re.sub(r'\\(.\*?\\)', '', fio), замена латиницы через str.maketrans('aceopxyABCEHKMOPTX', 'асеорхуАВСЕНКМОРТХ'), замена ё-\>е и удаление лишних пробелов.
|
||||
> * **Коллизия 270 vs 271:** В СКУД 270 физических лиц (один пропуск на человека), в 1С — 271 строка. Сотрудник **Балаева Ольга Геннадьевна** числится на двух ставках в разных отделах (*Руководитель управления персоналом* и *Руководитель режимно-секретного отдела*).
|
||||
> * **Решение:** Внедрена группировка датафрейма 1С по fio\_clean с агрегацией должностей и подразделений через разделитель " / ".
|
||||
|
||||
### **2.3. Защита от коллизий полных тёзок и ложных связок однофамильцев (Кейс Семеновых)**
|
||||
|
||||
> * **Инцидент:** Неограниченная строгими правилами LLM связала двух разных сотрудниц — *«Семенову Юлию Борисовну»* (работает) и *«Семенову Дину Дмитриевну»* (в отпуске), посчитав разные имена опечаткой из\-за одинаковой фамилии. В результате Юлии Борисовне ошибочно был приписан статус отпуска.
|
||||
> * **Двухконтурный барьер:**
|
||||
1. **В промпте:** Запрет объединения однофамильцев с разными именами/отчествами.
|
||||
2. **В Python:** Проверка совпадения первых букв имени и отчества. При несовпадении сопоставление ИИ аннулируется с логированием ⚠️ \[Блокировка фейка\].
|
||||
|
||||
### **2.4. Вынесение исключений в exceptions.json и синонимы отделов**
|
||||
|
||||
> * Служебный персонал (отдел «ЭТО», уборщики производственных и служебных помещений, клинеры, дворники, гардеробщики) вынесен в exceptions.json.
|
||||
> * Для сопоставления кратких аббревиатур СКУД и полных названий отделов 1С (*«ОВК» ⟷ «Отдел внутреннего контроля»*) создана таблица department\_synonyms с автоматическим самообучением при работе человека (Human-in-the-Loop).
|
||||
|
||||
### **2.5. Разгадка феномена «исчезающих неизвестных» и аппаратный сбой СКУД 04.08.2026**
|
||||
|
||||
> * **Аномалия:** Утром 04.08.2026 на главном КПП зависли контроллеры входа. У 119 сотрудников не записалось утреннее событие (time\_in \= 'Нет входа'). Из них 57 человек были в отпусках/командировках по 1С. Оставшиеся 74 человека были на работе без утренней отметки. Однако вечерняя сводка показала всего 4–7 «неизвестных».
|
||||
> * **Причина:** Скрипт агрегации видел дневные перемещения (обед, внутренние двери, туалет, вечерний выход) и автоматически проставлял Статус \= 'Присутствовал' и is\_present \= 1, несмотря на то, что колонка Начало\_дня оставалась 'Нет входа'. В итоге 70 человек тихо ушли в «Итого на работе», а системный сбой оборудования был замаскирован.
|
||||
> * **Архитектурный фикс:**
|
||||
1. Введена колонка **first\_activity («Первая активность»)** — вычисление MIN(TimeVal) AS FirstRawEvent по таблице pLogData без учета направления двери.
|
||||
2. Если time\_in \== 'Нет входа', но first\_activity \!= '—', записи ставится anomaly\_flag \= 'ANOMALY\_NO\_IN\_HAS\_ACTIVITY', а is\_present принудительно сбрасывается в 0\.
|
||||
3. Внедрен модуль analyze\_scud\_mass\_failure\_ai(): если доля таких аномалий превышает 5% смены (\>10 чел.), ИИ генерирует системный алерт о массовом сбое контроллеров КПП.
|
||||
> * **Кейс Равина В.Э.:** Главный специалист официально находился в основном отпуске по 1С, утреннего входа на КПП не было, но зафиксирована активность в 14:11:06 и вечерний выход в 17:18:38. Система зарегистрировала истинную кадровую аномалию (физическое присутствие при официальном отпуске).
|
||||
|
||||
### **2.6. Система сквозных датированных снапшотов (срезов)**
|
||||
|
||||
> * **Формат ID:** \[Y\]YYYYMMDD-NNN (например, Y20260804-001 для вчерашнего зафиксированного вечернего среза на 22:00 и 20260805-002 для дневного).
|
||||
> * **Оптимизация:** Функция has\_yesterday\_final\_snapshot() проверяет наличие вчерашнего среза в SQLite: если он есть, повторный тяжелый запрос к MS SQL Орион пропускается.
|
||||
> * **CLI-управление:** Поддержка запуска отчетов по любому историческому снапшоту через ключ \--snapshot \[ID\] и пропуск выгрузки через \--skip-export.
|
||||
|
||||
### **2.7. Web API, Generative UI и управление жизненным циклом сессий (Topic Drift & Ephemeral Buffer)**
|
||||
|
||||
> * **Проблема засорения контекста LLM:** Вывод объемных списков задач, системных промптов и таблиц срезов забивал окно диалога, вызывая галлюцинации и «залипание» модели на старых данных.
|
||||
> * **Решение:**
|
||||
* В 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.
|
||||
|
||||
## ---
|
||||
|
||||
**3\. Полная схема базы данных SQLite (data/scud\_orion\_ai.db)**
|
||||
|
||||
| Таблица | Назначение и бизнес-логика | Структура полей |
|
||||
| :---- | :---- | :---- |
|
||||
| **scud\_logs** | Логи проходов СКУД, расчетное время в здании и снапшоты. | id INTEGER PK AUTOINCREMENT, log\_date TEXT, fio TEXT, fio\_clean TEXT, department TEXT, position TEXT, time\_in TEXT, first\_activity TEXT DEFAULT '—', time\_out TEXT, time\_in\_building TEXT, is\_present INTEGER, anomaly\_flag TEXT DEFAULT 'NONE', snapshot\_time TEXT, snapshot\_id TEXT, created\_at TIMESTAMP |
|
||||
| **zup\_staff** | Штатное расписание 1С:ЗУП на даты срезов. | id INTEGER PK AUTOINCREMENT, snapshot\_date TEXT, fio TEXT, fio\_clean TEXT, department TEXT, position TEXT, created\_at TIMESTAMP |
|
||||
| **zup\_absences** | Документы отклонений 1С (отпуска, больничные, командировки, декреты). | id INTEGER PK AUTOINCREMENT, absence\_date TEXT, fio TEXT, fio\_clean TEXT, absence\_type TEXT, created\_at TIMESTAMP |
|
||||
| **anomalies\_history** | Журнал выявленных кадровых и аппаратных аномалий. | id INTEGER PK AUTOINCREMENT, anomaly\_date TEXT, fio TEXT, anomaly\_type TEXT, details TEXT, human\_status TEXT DEFAULT 'Pending', created\_at TIMESTAMP |
|
||||
| **ai\_knowledge\_base** | Глобальные правила арбитража и приоритеты компании для ИИ. | id INTEGER PK AUTOINCREMENT, rule\_text TEXT UNIQUE, added\_by TEXT DEFAULT 'Human', created\_at TIMESTAMP |
|
||||
| **system\_prompts** | Версионные системные промпты агента (активный по is\_active=1). | id INTEGER PK AUTOINCREMENT, name TEXT, prompt\_text TEXT, is\_active INTEGER DEFAULT 1, updated\_at TIMESTAMP |
|
||||
| **tool\_action\_registry** | Декларативный реестр шаблонов, кнопок и настроек эфемерности инструментов. | id INTEGER PK AUTOINCREMENT, tool\_name TEXT UNIQUE, category TEXT, bypass\_llm INTEGER, success\_template TEXT, follow\_up\_question TEXT, action\_type TEXT, buttons\_json TEXT, is\_active INTEGER, is\_ephemeral INTEGER, updated\_at TIMESTAMP |
|
||||
| **session\_states** | Активные состояния сессий, черновики и счетчик idle\_turns. | session\_id TEXT PRIMARY KEY, state\_type TEXT, pending\_data TEXT, updated\_at TIMESTAMP |
|
||||
| **chat\_messages** | История диалогов с поддержкой разделения на постоянные и эфемерные сообщения. | id INTEGER PK AUTOINCREMENT, session\_id TEXT, role TEXT, content TEXT, is\_ephemeral INTEGER DEFAULT 0, created\_at TIMESTAMP |
|
||||
| **tasks** | Реестр задач операторов с привязкой к user\_id. | id INTEGER PK AUTOINCREMENT, task\_id TEXT, module TEXT, title TEXT, priority TEXT, status TEXT, due\_date TEXT, user\_id INTEGER, created\_at TIMESTAMP |
|
||||
| **users** | Учетные записи операторов (хэши паролей bcrypt, права администратора). | id INTEGER PK AUTOINCREMENT, username TEXT UNIQUE, password\_hash TEXT, is\_admin INTEGER, full\_name TEXT, created\_at TIMESTAMP |
|
||||
| **department\_synonyms** | База соответствия аббревиатур СКУД полным названиям отделов 1С. | id INTEGER PK AUTOINCREMENT, short\_name TEXT UNIQUE, full\_name TEXT, created\_at TIMESTAMP |
|
||||
| **system\_reference** | Справочник команд и примеров промптов для операторов. | id INTEGER PK AUTOINCREMENT, category TEXT, title TEXT, example\_prompt TEXT, description TEXT |
|
||||
|
||||
## ---
|
||||
|
||||
**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, auth, chat, tasks) \# REST эндпоинты
|
||||
│ ├── 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, fast\_path, ollama\_client, prompt\_merger, tool\_injector)
|
||||
│ │ └── db/ (connection, db\_chat, db\_prompts, db\_snapshots, db\_tasks)
|
||||
│ └── static/ (index.html, css/styles.css, js/app.js, js/auth.js, js/chat.js, js/tasks.js)
|
||||
└── docs/
|
||||
└── development\_roadmap.md \# Стратегическая дорожная карта и архитектурный бэклог
|
||||
|
||||
## ---
|
||||
|
||||
**5\. Справочник команд CLI (HOWTO)**
|
||||
|
||||
### **ETL Пайплайн (main\_etl.py):**
|
||||
|
||||
> * python main\_etl.py — стандартный дневной запуск (экспорт из MS SQL, сохранение снапшота, генерация отчетов).
|
||||
> * python main\_etl.py \--skip-export — построение отчетов по последнему имеющемуся снапшоту из SQLite без повторного запроса к MS SQL.
|
||||
> * python main\_etl.py \--snapshot 20260805-001 — точный расчет отчетов по указанному составному ID снапшота.
|
||||
> * python main\_etl.py \-d — запуск в режиме расширенной отладки (DEBUG).
|
||||
|
||||
### **CLI базы данных (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.
|
||||
> 2. **Модуль анализа внутридневных перемещений («Контроль перекуров»):**
|
||||
* Анализ интервалов между событиями OUT (выход) и IN (возврат) по журналу pLogData.
|
||||
* Подсчет суммарного времени нахождения вне рабочего места в течение смены с отсечением технологической нормы (30–40 минут).
|
||||
* Вывод аналитического блока и злостных нарушителей в отдельный лист Excel-отчета и итоговую Markdown-сводку.
|
||||
> 3. **Интерактивный Task Planner & Roadmap Engine:**
|
||||
* Специализированный инструмент для ведения динамических проектных планов и чек-листов с чекбоксами (\[ \] / \[x\]) прямо в диалоге с синхронизацией в таблицу tasks.
|
||||
> 4. **Изолированная среда исполнения кода (Code Execution Sandbox):**
|
||||
* Безопасный изолированный Docker/gVisor контейнер для динамического выполнения генерируемого моделью Python/Pandas кода на лету с возвратом stdout/stderr и графиков в контекст.
|
||||
> 5. **Автоматизация расписания срезов и Telegram-алерты:**
|
||||
* Автозапуск выгрузок в 12:00, 17:00 и 19:00 через systemd-таймеры с фиксацией snapshot\_time.
|
||||
* Отправка мгновенных алертов о массовых сбоях турникетов (\>5%) и критических кадровых конфликтах дежурному системному администратору в Telegram.
|
||||
Reference in New Issue
Block a user