Files
2026-hypn0-site/hypn0/hypn0_site/services/naming.py
T
2026-09-27 19:19:59 +03:00

137 lines
6.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
Сервис генерации гипнотических названий для картин галереи.
Включает:
- Локальный генератор псевдослучайных гипно-заголовков (в стиле Гипножабы, психоделики и мемов).
- Закладку (интерфейс и спецификацию) для будущей интеграции с 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