137 lines
6.6 KiB
Python
137 lines
6.6 KiB
Python
"""
|
||
Сервис генерации гипнотических названий для картин галереи.
|
||
|
||
Включает:
|
||
- Локальный генератор псевдослучайных гипно-заголовков (в стиле Гипножабы, психоделики и мемов).
|
||
- Закладку (интерфейс и спецификацию) для будущей интеграции с OpenRouter API (мультимодальные VLM).
|
||
"""
|
||
|
||
import random
|
||
from typing import Optional
|
||
|
||
|
||
# Словари для локального генератора гипно-тайтлов на английском языке
|
||
HYPNO_ADJECTIVES = [
|
||
"Shimmering", "Astral", "Hypnotic", "Vulgar", "Surreal", "Absurd", "Psyche­delic",
|
||
"Pulsating", "Neon", "Trans­cendent", "Cerebral", "Mental", "Subcon­scious", "Cosmic",
|
||
"Halluci­nogenic", "Fractal", "Detached", "Synes­thetic", "Parallel", "Illusory", "Ephemeral",
|
||
"Hypnot­oadian", "Conductive", "Mesme­rizing", "Magnetic", "Carefree", "Oneiric",
|
||
"Psychot­ropic", "Mystical", "Other­worldly", "Spiral", "Quivering", "Slippery", "Misty",
|
||
"Ethereal", "Trance", "Quantum", "Juicy", "Hypno-Absurd", "Psychoactive", "Magical",
|
||
"Synthetic", "Chromatic", "Perceptive", "Perforated", "Vibra­tional", "Neural",
|
||
"Subliminal", "Glitched", "Radioactive", "Brain-Melting", "Galactic", "Phospho­rescent",
|
||
"Chaotic", "Hypnagogic", "Interdim­ensional", "Cybernetic", "Uncanny",
|
||
]
|
||
|
||
HYPNO_NOUNS = [
|
||
"Trance", "Pulsar", "Gaze", "Brain Slug", "Vortex", "Portal", "Path", "Fractal", "Signal", "Spectrum",
|
||
"Resonance", "Mirage", "Oasis", "Abyss", "Labyrinth", "Impulse", "Monolith", "Oracle", "Vector",
|
||
"Clot", "Cascade", "Horizon", "Toadstool", "Pattern", "Contour", "Phantom", "Splash", "Tranqui­lizer",
|
||
"Mist", "Crystal", "Stream", "Singulator", "Pulse", "Glitch", "Synthesis", "Roar", "Tremor",
|
||
"Frontier", "Sentinel", "Gatekeeper", "Whisper", "Spore", "Worm", "Bubble", "Psycho-Spider",
|
||
"Receptor", "Mind-Warp", "Hypnotoad", "Neuron", "Oscil­lation", "Echo", "Hologram", "Matrix",
|
||
"Mind-drill", "Neurotoxin", "Dreamscape", "Substance",
|
||
]
|
||
|
||
HYPNO_GENITIVES = [
|
||
"of Consciousness", "of the Hypnotoad", "of the Subcon­scious",
|
||
"of the Void", "of the Matrix", "of the Psycho-Web", "of the Brain Slug",
|
||
"of the Noosphere", "of the Neo-Modern", "of the Deep Trance",
|
||
"of the Ether", "of the 4th Dimension", "of Pointillism", "of the Substance",
|
||
"of Uncer­tainty", "of the Continuum", "of Acid", "of Pure Perception",
|
||
"of Lucid Dreams", "of Halluci­nations", "of Psyche­delia", "of Trans­cendence",
|
||
"of the Nether­world", "of DOOP Regul­ations", "of Galactic Frequencies",
|
||
"of Grade 24 Bureaucracy",
|
||
]
|
||
|
||
HYPNO_POSTFIXES = [
|
||
"#42", "v3.14", "(Ultra)", "(Phase 7)", "(Alpha)", "(Omega)", "(Protocol 09)", "(Revision 14)",
|
||
"(Extract)", "(Layer 9)", "(Ward 106)", "(Hangar 18)", "(Unfinished Opus)", "(Secret Project)",
|
||
"[Classified]", "(DOOP-66)", "(Sub-Level 4)", "(MK-Ultra)", "С90"
|
||
]
|
||
|
||
|
||
def generate_hypno_title(seed: Optional[int] = None) -> str:
|
||
"""
|
||
Генерирует сочное гипнотическое название для картины на основе словарей.
|
||
Примеры:
|
||
- «Hypnotic Pulsar of the Hypnotoad #42»
|
||
- «Astral Gaze»
|
||
- «Brain Slug of the Void»
|
||
- «Transcendent (Ultra)»
|
||
- «Hypnotic»
|
||
- «Vortex»
|
||
"""
|
||
rng = random.Random(seed)
|
||
adj = rng.choice(HYPNO_ADJECTIVES)
|
||
noun = rng.choice(HYPNO_NOUNS)
|
||
genitive = rng.choice(HYPNO_GENITIVES)
|
||
postfix = rng.choice(HYPNO_POSTFIXES)
|
||
|
||
patterns = [
|
||
# Однословные варианты
|
||
lambda: noun,
|
||
lambda: adj,
|
||
# Двухсловные комбинации
|
||
lambda: f"{adj} {noun}",
|
||
lambda: f"{noun} {genitive}",
|
||
lambda: f"{noun} {postfix}",
|
||
lambda: f"{adj} {postfix}",
|
||
# Трех- и четырехсловные гипно-конструкции
|
||
lambda: f"{adj} {noun} {genitive}",
|
||
lambda: f"{adj} {noun} {postfix}",
|
||
lambda: f"{adj} {noun} {genitive} {postfix}",
|
||
]
|
||
|
||
chosen_pattern = rng.choice(patterns)
|
||
return chosen_pattern()
|
||
|
||
|
||
# =====================================================================
|
||
# ЗАКЛАДКА: 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 = (
|
||
"You are the herald of the almighty Hypnotoad. Create a short (2-4 words), "
|
||
"punchy, ironically absurd, and hypnotic English title "
|
||
"for a halftone SVG artwork shown in the thumbnail. "
|
||
"Reply ONLY with the title, without quotes or introductory words."
|
||
),
|
||
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": "Give a hypnotic title for this artwork:"},
|
||
{"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
|