New: - incremental_svg.py: parse_to_valid(prefix) handles any partial SVG - Closes open tags, opens quotes, truncates partial tags - Strips reasoning text and markdown fences from prefix - stream_to_valid(chunks) generator for incremental updates - tests/test_incremental_svg.py: 34 test cases including property-based Fixed (regressions from earlier today): - test_app.py: pass base_url and api_key to on_generate (new UI fields) - test_app.py: on_mode_change defaults updated to n=1 - test_renderer.py: mock both resvg and cairosvg since resvg is now primary - (manual fixes I did as owner, before letting streaming-client start) All tests: 157 passed, 1 skipped, 0 failed
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+ кейсов) |
Установка
# 1) зависимости
pip install -r requirements.txt
Важно для Windows:
cairosvg— это Python-биндинг к нативномуcairo. На Windows чистогоpip install cairosvgобычно недостаточно — нужна библиотекаcairo.dll. Варианты:# вариант 1: conda (рекомендуется) conda install -c conda-forge pycairo cairo # вариант 2: MSYS2 / vcpkg / GTK3 runtimeЕсли cairo не установлен — UI стартует, но PNG-превью будут пропущены (в логе появится
WARNINGот renderer.py).
Настройка LM Studio
- Запустить LM Studio локально (
http://127.0.0.1:1234). - Загрузить модель, например
qwen/qwen3.5-35b-a3b. - Включить 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 |
Запуск
python app.py
UI откроется на http://127.0.0.1:7860. Кнопка «Сгенерировать» отправляет
промпт в LM Studio, валидирует SVG, рисует PNG-превью и сохраняет запись
в SQLite.
Тесты
python -m pytest tests/ -v
Покрытие — validator.py (well-formed, viewBox, forbidden tags, http refs,
on*-атрибуты).
Smoke-тест импорта (без живого LM Studio)
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
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.