Files
rip-help-system/README.md
sabo d323bee712 Rename healthz label to Статус на услугата; document live URL.
API tab and OpenAPI summary now say status instead of health; docs point to rip.inex-project.net.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-27 10:54:51 +03:00

187 lines
8.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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-haiku-4-5 | Модел за класификация |
| `MIN_IMAGE_PX` | 50 | Картинки под NxN px се пропускат |
---
## Webapp (FastAPI)
`webapp/` съдържа FastAPI app за server deploy (Coolify / Docker).
### Endpoint-и
| Метод | Път | Описание |
|---|---|---|
| GET | `/` | HTML viewer (Home/Editor/Search/Generator); query `?prefix=RIP&home=1` |
| GET | `/images/<file>` | Сервира картинка от `OUTPUT_DIR/images/` |
| GET | `/home-image` | Home image (от `HOME_IMAGE` env var или `Bairaci.png`) |
| GET | `/api/sections` | JSON списък със секции; query `?prefix=` |
| POST | `/api/keywords/<code>` | `{keywords: "..."}` → UPDATE в DB |
| GET | `/healthz` | Health check (DB ping) |
### Env vars
| Var | Default | Описание |
|---|---|---|
| `HELP_DB_CONN` | — | libpq формат за Postgres (задължително) |
| `OUTPUT_DIR` | `./data` | Директория с `images/` подпапка |
| `HOME_IMAGE` | — | Абсолютен път към home картинка (опционален) |
### Локален dev
```
pip install -r requirements-webapp.txt
$env:HELP_DB_CONN="host=192.168.88.18 port=5432 dbname=rip_help_system user=sa password=..."
$env:OUTPUT_DIR="q:\RIP_Help_Source\Output"
python -m uvicorn webapp.main:app --reload
# отвори http://127.0.0.1:8000/?prefix=RIP&home=1
```
### Coolify deploy
1. В Coolify: New Resource → Application → Public/Private Repository
2. URL: `https://git.inex-project.net/sabo/rip-help-system.git`
3. Build pack: **Dockerfile**
4. Environment variables (в Coolify UI, не в git):
- `HELP_DB_CONN=host=... port=5432 dbname=rip_help_system user=... password=...`
- `OUTPUT_DIR=/data/help_output`
- `HOME_IMAGE=/data/help_output/Bairaci.png` (по избор)
5. Persistent storage (volume): `/data/help_output` (там качваш картинките с WinSCP/rsync)
6. Port: 8000
7. Custom domain: **`https://rip.inex-project.net`** → Coolify прави HTTPS (Let's Encrypt) автоматично
Live: [https://rip.inex-project.net/?prefix=RIP](https://rip.inex-project.net/?prefix=RIP) · health: [/healthz](https://rip.inex-project.net/healthz)
### Качване на картинки на сървъра
Локалният `help_processor.py` пише в `q:\RIP_Help_Source\Output\` (включително `images/` подпапка). За deploy:
```
# с WinSCP — sync на цялата директория
local: q:\RIP_Help_Source\Output\
remote: /home/sabo/share/help_output/ ← Coolify volume mount
```
Базата (Postgres на 192.168.88.18) се ползва от webapp-а директно.