← Архитектура (текст)
🏗️ Архитектура — блок-схемы
1. Система — компоненты и связи
👤 Пользователь
Браузер
Загрузка файлов
HTTPS
SSE
⚡ Flask-фронтенд
Managed Python (Nubes)
Jinja2-шаблоны
Промпт-редактор
Чат с LLM
REST API
Выделенная VM
📄 Парсинг документов
pdfplumber · python-docx
🏷️ Классификация
3-этапный фильтр мусора
🤖 LLM-сравнение
extract + diff · группировка
HTTP/2
🧠 LLM
api.aillm.ru
gpt-oss-120b
🗄️ PostgreSQL 15
JSONB · Event Sourcing · spec_events
2. Пайплайн обработки одного файла
📤 Загрузка
Multipart-парсинг
SHA-256 хеш
Формат: pdf/docx/zip
🔍 Парсинг
Извлечение текста
Извлечение таблиц
→ elements_json
🏷️ Фильтр #1-#2
Имя файла → мусор?
Заголовки → мусор?
0 токенов LLM
мусор → стоп
🤖 Фильтр #3 — LLM
Тип: договор/допник/
спецификация/мусор
Номер, дата, контрагент
мусор → стоп
📋 Группи-
ровка
По номерам
договоров
Срав-
нение
ADD
UPDATE
🛡️ Защита: ZIP-бомба (500/500/100×) · Path traversal · Whitelist форматов · content_hash · UNRESOLVED · нормализация чисел/дат · price×qty=sum
📊 База: documents (метаданные + elements_json) · classify_results · spec_events (аудит) · spec_current (спецификация) · prompts (версионирование)
Бинарные файлы удаляются после парсинга. Промежуточные данные — требуется автоочистка.
3. Event Sourcing — как работает сравнение
Документы группы (отсортированы по doc_date)
📄 Договор
базовый
📄 Допник
#1
📄 Допник
#2
...
🤖 LLM: промпт extract
Извлечение всех услуг
→ массив ADD-операций
🗄️ spec_events
ADD услуга X
ADD услуга Y
(неизменяемый лог)
📊 spec_current
Услуга X | 100₽ | 10 шт
Услуга Y | 200₽ | 5 шт
🤖 LLM: промпт diff
(допник #1) vs spec_current
→ ADD / UPDATE / DELETE
🗄️ spec_events
UPDATE услуга X
DELETE услуга Y
ADD услуга Z
📊 spec_current (обн.)
Услуга X | 150₽ | 10 шт
Услуга Z | 300₽ | 2 шт
цикл по допникам
Каждый допник сравнивается с актуальной spec_current → операции накапливаются в spec_events → spec_current пересчитывается
4. Защита — эшелоны
🔴 Уровень 1 — Загрузка: ZIP-бомба (500 файлов / 500MB / ratio 100×) · Path traversal · Whitelist .pdf .docx .doc .zip
🟠 Уровень 2 — Парсинг: cp437→utf8 для битых имён · content_hash (SHA-256) · дедупликация · try/except → logging.warning
🟡 Уровень 3 — Классификация: фильтр по имени файла · фильтр по заголовкам (2000 симв.) · LLM-фильтр · мусор → garbage
🟢 Уровень 4 — Сравнение: ADD без имени → UNRESOLVED · UPDATE/DELETE без цели → UNRESOLVED · нормализация 1 000,50→1000.50 · дат · price×qty=sum