Files
2026-hypn0-site/hypn0/hypn0_site/services/naming.py
T

188 lines
6.2 KiB
Python

"""
Сервис генерации гипнотических названий для картин галереи.
Включает:
- Локальный генератор псевдослучайных гипно-заголовков (в стиле Гипножабы, психоделики и мемов).
- Закладку (интерфейс и спецификацию) для будущей интеграции с 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