Initial commit: OmniSVG-Lite MVP before live-streaming work
- LM Studio client (httpx-based, OpenAI-compatible) - SVG validator (lxml, whitelist tags, no <script>/<foreignObject>/http refs) - PNG renderer (resvg-py primary, cairosvg fallback - no native cairo dep) - History (SQLite, tracks raw/validated/preview paths) - Gradio UI on 127.0.0.1:8788 with: * mode radio (icon/illustration) * n_candidates slider (default 1) * image upload for image-to-SVG * LM Studio URL/token inputs * model dropdown + refresh button - prompts/ with system_icon.txt, system_illustration.txt, few_shot_examples.txt - docs/spec.md, docs/design.md - 122 unit/integration tests passing
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
# OmniSVG-Lite
|
||||
|
||||
Локальный MVP для генерации SVG-иконок и иллюстраций через LM Studio.
|
||||
Gradio UI, локальная SQLite-история, валидация выхода модели через `lxml`,
|
||||
PNG-превью через `cairosvg`.
|
||||
|
||||
> Контракт: см. `docs/spec.md` и `docs/design.md`. Промпт-шаблоны: `prompts/`.
|
||||
|
||||
## Что внутри
|
||||
|
||||
| Файл | Назначение |
|
||||
|--------------------|------------------------------------------------------------------|
|
||||
| `app.py` | Gradio 5 UI: text/prompt → N SVG-кандидатов → PNG-превью → БД |
|
||||
| `lm_client.py` | httpx-клиент к OpenAI-compatible LM Studio, `generate_svg()` |
|
||||
| `prompts.py` | Загрузка шаблонов из `prompts/` + `build_messages()` |
|
||||
| `validator.py` | lxml-парсинг + проверка whitelist/тегов/href/on* |
|
||||
| `renderer.py` | cairosvg → PNG (graceful fallback, если cairo недоступен) |
|
||||
| `history.py` | SQLite WAL, контекст-менеджер `History` |
|
||||
| `prompts/` | system-инструкции + few-shot примеры |
|
||||
| `tests/` | pytest на validator (6+ кейсов) |
|
||||
|
||||
## Установка
|
||||
|
||||
```bash
|
||||
# 1) зависимости
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
> **Важно для Windows**: `cairosvg` — это Python-биндинг к нативному `cairo`.
|
||||
> На Windows чистого `pip install cairosvg` обычно недостаточно — нужна
|
||||
> библиотека `cairo.dll`. Варианты:
|
||||
>
|
||||
> ```bash
|
||||
> # вариант 1: conda (рекомендуется)
|
||||
> conda install -c conda-forge pycairo cairo
|
||||
>
|
||||
> # вариант 2: MSYS2 / vcpkg / GTK3 runtime
|
||||
> ```
|
||||
>
|
||||
> Если cairo не установлен — UI стартует, но PNG-превью будут пропущены
|
||||
> (в логе появится `WARNING` от renderer.py).
|
||||
|
||||
## Настройка LM Studio
|
||||
|
||||
1. Запустить LM Studio локально (`http://127.0.0.1:1234`).
|
||||
2. Загрузить модель, например `qwen/qwen3.5-35b-a3b`.
|
||||
3. Включить **OpenAI-compatible server** в LM Studio.
|
||||
|
||||
Переменные окружения (опционально, все имеют дефолты):
|
||||
|
||||
| Переменная | Дефолт |
|
||||
|---------------------------|-----------------------------------|
|
||||
| `LM_STUDIO_BASE_URL` | `http://127.0.0.1:1234/v1` |
|
||||
| `LM_STUDIO_API_KEY` | `lm-studio` |
|
||||
| `DEFAULT_MODEL` | `qwen/qwen3.5-35b-a3b` |
|
||||
| `REQUEST_TIMEOUT_S` | `120` |
|
||||
| `OMNISVG_DB_PATH` | `~/.omnisvg_lite/history.sqlite` |
|
||||
| `OMNISVG_PREVIEW_DIR` | `~/.omnisvg_lite/previews` |
|
||||
| `LOG_LEVEL` | `INFO` |
|
||||
|
||||
## Запуск
|
||||
|
||||
```bash
|
||||
python app.py
|
||||
```
|
||||
|
||||
UI откроется на `http://127.0.0.1:7860`. Кнопка «Сгенерировать» отправляет
|
||||
промпт в LM Studio, валидирует SVG, рисует PNG-превью и сохраняет запись
|
||||
в SQLite.
|
||||
|
||||
## Тесты
|
||||
|
||||
```bash
|
||||
python -m pytest tests/ -v
|
||||
```
|
||||
|
||||
Покрытие — `validator.py` (well-formed, viewBox, forbidden tags, http refs,
|
||||
on*-атрибуты).
|
||||
|
||||
## Smoke-тест импорта (без живого LM Studio)
|
||||
|
||||
```bash
|
||||
python -c "from app import demo, main; print('imports ok')"
|
||||
```
|
||||
|
||||
Запускается **только импорт**, Gradio-сервер не поднимается. Если gradio не
|
||||
установлен, импорт `app.py` упадёт (gradio захардкожен в `import`).
|
||||
|
||||
## Известные ограничения (MVP)
|
||||
|
||||
- Один пользователь, без авторизации.
|
||||
- Выбор «лучшего» кандидата — по минимальному размеру файла (прокси
|
||||
компактности, не качества). См. `spec.md §4`.
|
||||
- `cairosvg` на Windows без conda — см. выше; UI работает и без PNG-превью.
|
||||
- Размер БД не ограничен; очистка старых превью — на совести пользователя
|
||||
(дизайн §11, open question).
|
||||
|
||||
## Структура SQLite
|
||||
|
||||
```sql
|
||||
CREATE TABLE generations (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
created_at REAL NOT NULL,
|
||||
prompt TEXT NOT NULL,
|
||||
mode TEXT NOT NULL, -- icon | illustration
|
||||
model TEXT NOT NULL,
|
||||
n_requested INTEGER NOT NULL,
|
||||
n_returned INTEGER NOT NULL,
|
||||
temperature REAL NOT NULL,
|
||||
status TEXT NOT NULL, -- ok | partial | failed
|
||||
error_reason TEXT,
|
||||
raw_outputs TEXT NOT NULL, -- JSON list[str]
|
||||
validated_outputs TEXT NOT NULL, -- JSON list[str]
|
||||
previews TEXT NOT NULL, -- JSON list[str] (PNG paths)
|
||||
best_index INTEGER
|
||||
);
|
||||
```
|
||||
|
||||
WAL-режим, индекс по `created_at DESC`.
|
||||
Reference in New Issue
Block a user