Files
contracts/History/architecture/pipeline.md
T

8.7 KiB
Raw Blame History

Пайплайн обработки договора

Схема

┌─────────────────────────────────────────────────────────────────────┐
│                    👤 ПОЛЬЗОВАТЕЛЬ                                  │
│  Открывает / → выбирает файлы → жмёт «Обработать»                  │
└──────────────────────────┬──────────────────────────────────────────┘
                           │ multipart/form-data (files)
                           ▼
┌─────────────────────────────────────────────────────────────────────┐
│  app.py: _upload_page() POST                                        │
│  Принимает файлы, запускает пайплайн                                │
└──────────────────────────┬──────────────────────────────────────────┘
                           │
            ┌──────────────┼──────────────┐
            ▼              ▼              ▼
        file.docx      file.pdf      file.zip
            │              │              │
            ▼              ▼              ▼
┌─────────────────────────────────────────────────────────────────────┐
│  ① parser.py                                                        │
│  docx → python-docx → elements JSON                                 │
│  pdf  → pdfplumber  → elements JSON                                 │
│  doc  → libreoffice → docx → python-docx                            │
│  zip  → zipfile → каждый файл рекурсивно                            │
│                                                                     │
│  Выход: [{type:"paragraph", style, text}, {type:"table", rows}]     │
│  НИЧЕГО не фильтрует, не теряет                                     │
└──────────────────────────┬──────────────────────────────────────────┘
                           │ elements JSON
                           ▼
┌─────────────────────────────────────────────────────────────────────┐
│  ② textify.py                                                       │
│  elements → линейный текст                                          │
│                                                                     │
│  [No Spacing] Приложение № 1                                        │
│  [Heading 3] Состав и стоимость Услуг                               │
│  --- Таблица (9×6) ---                                              │
│  | № | Наименование | Цена | Объем | Сумма | Дата |                 │
│  | 1 | Аренда стойко-места | 213 905 | 3 | 641 716 | 01.04.2026 |  │
└──────────────────────────┬──────────────────────────────────────────┘
                           │ текст (строка)
                           ▼
┌─────────────────────────────────────────────────────────────────────┐
│  ③ extractor.py + llm_client.py                                     │
│  текст → промпт → LLM (gpt-oss-120b) → JSON                         │
│                                                                     │
│  Промпт: «Найди таблицы услуг, извлеки строки в JSON»               │
│  Ответ: [{"row_num":1, "name":"Аренда...", "price":213905,          │
│           "qty":3, "sum":641716, "date_start":"2026-04-01"}, ...]   │
└──────────────────────────┬──────────────────────────────────────────┘
                           │ строки спецификации
                           ▼
┌─────────────────────────────────────────────────────────────────────┐
│  ④ differ.py                                                        │
│  Сравнение с предыдущим допником                                    │
│                                                                     │
│  rows_old vs rows_new → changes:                                    │
│    added:     новая услуга                                          │
│    changed:   цена 213905 → 250000, дата 01.04 → 25.04             │
│    deleted:   услуга убрана                                         │
│    unchanged: без изменений                                         │
└──────────────────────────┬──────────────────────────────────────────┘
                           │ изменения
                           ▼
┌─────────────────────────────────────────────────────────────────────┐
│  ⑤ Сохранение в PostgreSQL                                          │
│                                                                     │
│  documents      ← исходный файл + распарсенный текст                │
│  contracts      ← договор                                           │
│  supplements    ← допник                                            │
│  spec_rows      ← строки спецификации                               │
│  spec_history   ← история изменений                                 │
└──────────────────────────┬──────────────────────────────────────────┘
                           │
                           ▼
┌─────────────────────────────────────────────────────────────────────┐
│  Ответ пользователю: HTML-страница с таблицей результатов           │
│  «Извлечено 14 строк, добавлено 14, изменено 0, удалено 0»         │
│  + полная таблица услуг с ценами                                    │
└─────────────────────────────────────────────────────────────────────┘

Кратко

файлы → parser → textify → LLM → differ → PostgreSQL → HTML-страница

Слои

# Слой Что делает
parser.py docx/pdf/doc/zip → JSON
textify.py JSON → текст
extractor.py + llm_client.py текст → LLM → строки
differ.py сравнение с предыдущим
db.py + schema.py сохранение в БД
app.py сборка, приём формы, отдача HTML