Files
omnisvg-lite/README.md
Mavis 2394eff1c0 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
2026-06-13 15:32:54 +03:00

5.2 KiB

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

  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

Запуск

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.