Initial commit: working RIP/INEX_TM help processing pipeline

- help_processor.py: parses .docx/.html/.pdf/.doc/.txt, extracts images,
  classifies sections via Claude API, writes to SQL Server
- generate_html.py: builds interactive HTML viewer (Home/Editor/Search/Generator)
- save_keywords.py: applies keyword edits back to DB
- Prefix-scoped DB schema (RIP_help_files, RIP_help_sections) so multiple
  projects share the same database without collision
- BAT launchers per project (RIP_load.bat, INEX_TM_load.bat, ...) load
  credentials from gitignored .env via _load_env.bat
- Rich HTML preservation for .html sources (html_text column)
- Image extraction for all formats with MS Word / LibreOffice fallback for .doc

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-20 11:52:11 +03:00
commit 711053b8bd
16 changed files with 2421 additions and 0 deletions

124
README.md Normal file
View File

@@ -0,0 +1,124 @@
# RIP Help System — Help-файл декомпозитор и viewer
Обработва help-файлове (`.html`, `.htm`, `.docx`, `.doc`, `.pdf`, `.txt`), декомпозира ги на секции, извлича картинки, класифицира секциите с Claude API (заглавие + ключови думи), и записва всичко в SQL Server. После генерира интерактивен HTML viewer.
## Архитектура
```
Входни файлове → help_processor.py → SQL Server → generate_html.py → help_viewer.html
(.docx, .html, (RIP_help_*) (Home / Редактор /
.pdf, .doc) Търсене / Генератор)
save_keywords.py ← keywords_changes.json
(от Редактора на viewer-а)
```
## Инсталация
```
pip install -r requirements.txt
```
За стар `.doc` формат — едно от:
- **LibreOffice** в PATH (кросплатформено)
- **MS Word** (Windows, чрез pywin32 COM — автоматичен fallback)
## Конфигурация
Копирай `.env.example` като `.env` и попълни:
```
ANTHROPIC_API_KEY=sk-ant-...
HELP_DB_CONN=DRIVER={ODBC Driver 18 for SQL Server};TrustServerCertificate=yes;SERVER=host,port;DATABASE=db;UID=user;PWD=password
```
`.env` е gitignore-нат. Bat файловете го зареждат автоматично през `_load_env.bat`.
## Употреба (Windows)
### Обработка на нов проект
Първо създай `<PROJECT>_load.bat` и `<PROJECT>_view.bat` (вж. `RIP_load.bat`, `RIP_view.bat` като образец).
| BAT | Какво прави |
|---|---|
| `RIP_load.bat` | Incremental — обработва само нови/променени файлове по SHA-256 hash |
| `RIP_load_force.bat` | `--force --purge-missing` — преобработва всичко, изтрива orphans |
| `RIP_view.bat` | Генерира `help_viewer.html` за prefix=RIP и го отваря в браузъра |
### Директно от CLI
```
python help_processor.py --prefix=<PREFIX> <input_dir> <output_dir>
python help_processor.py --prefix=<PREFIX> --force --purge-missing <input_dir> <output_dir>
python generate_html.py --prefix=<PREFIX> # без Home таб
python generate_html.py --prefix=<PREFIX> --home img.png # с Home таб
```
## Prefix scoping
Всеки проект има свой `--prefix` (напр. `RIP`, `INEX_TM`). Прави следните неща изолирани между проектите:
- Кодовете на секциите: `RIP_0001_SEC_0001` vs `INEX_TM_0001_SEC_0001`
- skip-by-hash (incremental) — само в рамките на prefix-а
- `--purge-missing` — изтрива orphans само в текущия prefix
- `generate_html.py --prefix=X` — viewer-а филтрира по prefix
## Структура на базата
### `RIP_help_files`
| Поле | Тип | Описание |
|---|---|---|
| id | INT IDENTITY | PK |
| prefix | NVARCHAR(50) | Project scope |
| file_path | NVARCHAR(1000) | Пълен път до файла |
| file_hash | CHAR(64) | SHA-256 за incremental |
| processed_at | DATETIME2 | Последна обработка |
| section_count | INT | Брой секции |
UNIQUE constraint: `(prefix, file_path)`
### `RIP_help_sections`
| Поле | Тип | Описание |
|---|---|---|
| id | INT IDENTITY | PK |
| prefix | NVARCHAR(50) | Project scope |
| code | NVARCHAR(80) | `<PREFIX>_NNNN_SEC_NNNN` (UNIQUE) |
| source_file | NVARCHAR(1000) | Източник |
| title | NVARCHAR(500) | AI-генерирано заглавие |
| keywords | NVARCHAR(300) | До 5 ключови думи |
| char_count | INT | Размер на чистия текст |
| output_path | NVARCHAR(1000) | Път до `.txt` файла |
| images | NVARCHAR(MAX) | JSON масив с относителни пътища |
| html_text | NVARCHAR(MAX) | Rich HTML с форматиране (само за `.html` източници) |
| created_at, updated_at | DATETIME2 | |
## HTML Viewer — 3 / 4 таба
- **Home** (опционален, ако `--home <image>` е подаден) — началов екран с изображение
- **Редактор** — таблица със секции; inline редактиране на ключови думи; ✓ Save → JSON download → `save_keywords.py` → UPDATE в БД
- **Търсене** — карти със секции; multi-keyword (intervals = AND, "phrase" = literal); preview с картинки
- **Генератор** — drag & drop ordering → export като HTML (self-contained, всички картинки base64-embed-нати)
## Картинки
Извличат се по време на парсване:
- `.docx``<a:blip>` в paragraph drawings → bytes от related_parts
- `.html` — локални файлове и `data:` URLs; HTTP пропуска
- `.pdf``pdfplumber.page.crop(bbox).to_image()` като PNG
- `.doc` — след LibreOffice/MS Word конверсия до `.docx`
Филтър ≥ 50×50 px (PIL детектва), за да отрязва иконки/булети.
Записват се в `<output_dir>/images/<code>_img_NN.<ext>`. В текста placeholder `[IMG: images/...]`. В DB `images` колоната съдържа JSON масив с пътищата.
## Constants (в `help_processor.py`)
| Константа | Default | Описание |
|---|---|---|
| `MIN_SECTION_TOKENS` | 60 | Под този праг секцията се слива с предишната |
| `MAX_AI_CHARS` | 4000 | Символи, пращани към Claude |
| `AI_MODEL` | claude-sonnet-4-6 | Модел за класификация |
| `MIN_IMAGE_PX` | 50 | Картинки под NxN px се пропускат |