mod: ядро (04) SVG-генерация записывается в базу
This commit is contained in:
@@ -0,0 +1,187 @@
|
||||
"""
|
||||
Сервис генерации гипнотических названий для картин галереи.
|
||||
|
||||
Включает:
|
||||
- Локальный генератор псевдослучайных гипно-заголовков (в стиле Гипножабы, психоделики и мемов).
|
||||
- Закладку (интерфейс и спецификацию) для будущей интеграции с OpenRouter API (мультимодальные VLM).
|
||||
"""
|
||||
|
||||
import random
|
||||
from typing import Optional
|
||||
|
||||
|
||||
# Словари для локального генератора гипно-тайтлов
|
||||
HYPNO_ADJECTIVES = [
|
||||
"Мерцающий",
|
||||
"Астральный",
|
||||
"Гипнотический",
|
||||
"Психоделический",
|
||||
"Пульсирующий",
|
||||
"Неоновый",
|
||||
"Трансцендентный",
|
||||
"Мозговой",
|
||||
"Ментальный",
|
||||
"Бессознательный",
|
||||
"Космический",
|
||||
"Галлюциногенный",
|
||||
"Фрактальный",
|
||||
"Гипножабий",
|
||||
"Завораживающий",
|
||||
"Магнетический",
|
||||
"Спиральный",
|
||||
"Зыбкий",
|
||||
"Иллюзорный",
|
||||
"Онейрический",
|
||||
"Эфирный",
|
||||
"Трансовый",
|
||||
"Квантовый",
|
||||
"Синтетический",
|
||||
"Хроматический",
|
||||
]
|
||||
|
||||
HYPNO_NOUNS = [
|
||||
"Транс",
|
||||
"Пульсар",
|
||||
"Взгляд",
|
||||
"Слизень",
|
||||
"Вихрь",
|
||||
"Портал",
|
||||
"Разум",
|
||||
"Фрактал",
|
||||
"Сигнал",
|
||||
"Спектр",
|
||||
"Резонанс",
|
||||
"Морок",
|
||||
"Оазис",
|
||||
"Омут",
|
||||
"Лабиринт",
|
||||
"Импульс",
|
||||
"Монолит",
|
||||
"Оракул",
|
||||
"Вектор",
|
||||
"Сгусток",
|
||||
"Каскад",
|
||||
"Горизонт",
|
||||
"Мухомор",
|
||||
"Паттерн",
|
||||
"Контур",
|
||||
"Фантом",
|
||||
"Всплеск",
|
||||
"Взмах",
|
||||
"Взгляд",
|
||||
"Морок",
|
||||
]
|
||||
|
||||
HYPNO_GENITIVES = [
|
||||
"сознания",
|
||||
"Гипножабы",
|
||||
"бессознательного",
|
||||
"пустоты",
|
||||
"матрицы",
|
||||
"психо-паутины",
|
||||
"слизня",
|
||||
"ноосферы",
|
||||
"нео-модерна",
|
||||
"транса",
|
||||
"глубины",
|
||||
"эфира",
|
||||
"плесени",
|
||||
"измерения",
|
||||
"пуантилизма",
|
||||
"субстанции",
|
||||
"неопределенности",
|
||||
"континуума",
|
||||
"кислоты",
|
||||
]
|
||||
|
||||
HYPNO_POSTFIXES = [
|
||||
"#42",
|
||||
"v3.14",
|
||||
"MK-Ultra",
|
||||
"Фаза 7",
|
||||
"Пси-излучение",
|
||||
"Альфа",
|
||||
"Омега",
|
||||
"Частота 432Гц",
|
||||
"Протокол 09",
|
||||
"Ревизия 8",
|
||||
"Экстракт",
|
||||
"Слой 9",
|
||||
"Палата №6",
|
||||
"Ангар 18",
|
||||
"Ангар 18",
|
||||
]
|
||||
|
||||
|
||||
def generate_hypno_title(seed: Optional[int] = None) -> str:
|
||||
"""
|
||||
Генерирует сочное гипнотическое название для картины на основе словарей.
|
||||
Примеры:
|
||||
- «Мерцающий Транс сознания #42»
|
||||
- «Гипножабий Пульсар психо-паутины»
|
||||
- «Астральный Взгляд v3.14»
|
||||
"""
|
||||
rng = random.Random(seed)
|
||||
adj = rng.choice(HYPNO_ADJECTIVES)
|
||||
noun = rng.choice(HYPNO_NOUNS)
|
||||
|
||||
pattern_type = rng.randint(1, 3)
|
||||
if pattern_type == 1:
|
||||
genitive = rng.choice(HYPNO_GENITIVES)
|
||||
postfix = rng.choice(HYPNO_POSTFIXES)
|
||||
return f"{adj} {noun} {genitive} {postfix}"
|
||||
elif pattern_type == 2:
|
||||
genitive = rng.choice(HYPNO_GENITIVES)
|
||||
return f"{adj} {noun} {genitive}"
|
||||
else:
|
||||
postfix = rng.choice(HYPNO_POSTFIXES)
|
||||
return f"{adj} {noun} {postfix}"
|
||||
|
||||
|
||||
# =====================================================================
|
||||
# ЗАКЛАДКА: OpenRouter VLM API Integration (Post-MVP / AI Title)
|
||||
# =====================================================================
|
||||
def generate_title_openrouter(
|
||||
image_bytes: bytes,
|
||||
*,
|
||||
api_key: Optional[str] = None,
|
||||
model: str = "google/gemini-2.5-flash",
|
||||
system_prompt: str = (
|
||||
"Ты — глашатай всемогущей Гипножабы. Придумай короткое (2-4 слова), "
|
||||
"яркое, иронично-абсурдное и гипнотическое название на русском языке "
|
||||
"для полутоновой SVG-картины, изображенной на миниатюре. "
|
||||
"Отвечай ТОЛЬКО названием, без кавычек и вводных слов."
|
||||
),
|
||||
timeout: int = 5,
|
||||
) -> Optional[str]:
|
||||
"""
|
||||
[ЗАКЛАДКА ПОД OPENROUTER API]
|
||||
|
||||
Спецификация интеграции:
|
||||
1. Исходное растровое изображение сжимается до thumbnail 256x256 WebP/JPEG.
|
||||
2. Кодируется в Base64 (data:image/jpeg;base64,...).
|
||||
3. Отправляется POST-запрос на https://openrouter.ai/api/v1/chat/completions:
|
||||
Payload: {
|
||||
"model": model,
|
||||
"messages": [
|
||||
{"role": "system", "content": system_prompt},
|
||||
{
|
||||
"role": "user",
|
||||
"content": [
|
||||
{"type": "text", "text": "Дай гипнотическое название для этой картины:"},
|
||||
{"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{b64_data}"}}
|
||||
]
|
||||
}
|
||||
],
|
||||
"max_tokens": 50,
|
||||
"temperature": 0.9
|
||||
}
|
||||
4. При ошибке таймаута, отсутствии OPENROUTER_API_KEY в .env или сбое сети
|
||||
функция возвращает None, вызывая локальный fallback (generate_hypno_title).
|
||||
"""
|
||||
# TODO: Интегрировать requests / httpx при добавлении OPENROUTER_API_KEY в settings.py
|
||||
if not api_key:
|
||||
return None
|
||||
|
||||
# Заглушка: при отсутствии реального сетевого коннектора возвращаем None для fallback
|
||||
return None
|
||||
Reference in New Issue
Block a user