WizzGPT / app.py
Wizz13150's picture
Update app.py
a357e1c verified
Raw
History Blame Contribute Delete
28.2 kB
import gradio as gr
import random
import os
import threading
import gc
from llama_cpp import Llama
# =========================
# Configuration modèles
# =========================
model_versions = {
"WizzGPTv3": "model/WizzGPTv3-q8_0.gguf",
"WizzGPTv6": "model/WizzGPTv6-q8_0.gguf",
"WizzGPTv7": "model/WizzGPTv7-q8_0.gguf",
"WizzGPTv8": "model/WizzGPTv8-q8_0.gguf"
}
model_descriptions = {
"WizzGPTv3": "Tuned for SDXL. More tag-oriented, more prompt-like, more structured.",
"WizzGPTv6": "Tuned for Flux-style prompting. More natural language, more fluid visual phrasing.",
"WizzGPTv7": "Tuned for Flux.1 / Krea. More natural, weird, exploratory and surprising continuations.",
"WizzGPTv8": "Cinnadust Edition."
}
llm = None
current_model = "WizzGPTv8"
model_lock = threading.Lock()
# =========================
# Prompts
# =========================
prompt_list = [
"A beautiful sunset over",
"A macro shot of",
"Award winning photography of",
"Wide shot of",
"The intricate details of",
"The portrait of a",
"A resin figurine of",
"Painting of",
"A delicate",
"A rustic",
"A stunningly beautiful",
"Masterpiece, best quality",
"Hyperrealistic shot of a",
"Professional fashion shot of",
"Photo of a classy",
"Photo of a glamour",
"(Horror) shot of",
"Cinematic film still of",
"A (monochrome:2) photography of",
"A ",
"Masterpiece, best quality, ultra-detailed,",
"A hyper-realistic, cinematic shot of",
"An incredibly detailed, high-resolution portrait of",
"A breathtaking, photorealistic capture of",
"A vivid, intricately detailed scene of",
"A surreal, ultra-detailed rendering of",
"An exquisitely detailed, cinematic masterpiece of",
"A mesmerizing, hyper-detailed view of",
"A stunning, ultra-realistic depiction of",
"A visually arresting, high-definition snapshot of",
"The ",
"The (hologram) of",
"A surrealist art of",
"The (photography of a __animal__:2), (full-body),",
"The (photo of a (__animal__:__animal__:__weight__) hybrid), full-body,",
"A photo of an Eldritch abomination,",
"A (3D geometrically printed figurine) of",
"An overwhelmingly beautiful",
"An (eerie scene) featuring",
"A serene landscape showcasing",
"A photography of a magnificent",
"A bokeh effect background with",
"The bustling streets of",
"A whimsical depiction of",
"A dramatic aerial view of",
"An enchanting tableau presenting",
"The ancient ruins of",
"A night sky filled with",
"A macro close-up portrait of",
"An (abstract composition) with",
"A snowy scene with",
"The golden hour lighting up",
"A mystical forest where",
"A futuristic cityscape with",
"An ethereal",
"A whimsical",
"Photo of an amazingly beautiful creature with",
"Photo of an iridescent",
"Focus on",
"A meticulously crafted",
"A dramatic chiaroscuro lighting of",
"An artistic interpretation of",
"A vivid depiction of",
"A serene moment captured in",
"A richly textured",
"An evocative scene portraying",
"An epic panorama of",
"An iconic representation of",
"A minimalist composition featuring",
"An avant-garde portrayal of",
"An immersive diorama of",
"A time-lapse sequence showing",
"A haunting silhouette against",
"An ancient mythological scene in",
"A contemporary reimagining of",
"A hyper-detailed rendering of",
"A nostalgic memory preserved in",
"A powerful juxtaposition of",
"A seamless blend of",
"A surreal",
"An evocative interplay of light and shadow",
"A preserved fragment of",
"An intricate lacework of",
"An offbeat take on",
"A reflective surface capturing",
"A slow-motion capture of",
"A stunning vista showcasing",
"A timeless black-and-white portrait of",
"A twisted version of",
"A dynamic motion blur effect in",
"A geometric pattern inspired by",
"A moody fog enveloping",
"A textured overlay on",
"A vibrant explosion of color",
"A carefully orchestrated symmetry in",
"A kaleidoscopic arrangement of",
"A subtle gradation of color in",
"The raw grandeur of",
"A whirlwind of movement in",
"A conceptual representation of",
"An experimental take on",
"A harmonious blend of",
"A poetic rendering of",
"An organic flow of",
"An understated elegance in",
"An unassuming grace in",
"A dynamic shift in",
"A gentle harmony of",
"A graceful curve in",
"A heightened sense of",
"A radiant glow surrounding",
"A resonant soundscape in visual form",
"A strong focal point in",
"An angular perspective on",
"A fleeting moment of",
"A playful interaction between",
"A stark minimalist design featuring",
"A whimsical journey through",
"An organic structure evolving from",
"A visual metaphor for",
"A window into another world through a Stable-Diffusion of",
"A delicate balance between",
"A seamless transition from",
"A tranquil scene",
"The vibrant colors of",
"A peaceful countryside morning in",
"An underwater world revealing",
"The photography of",
"A (2000s vintage RAW photo) of",
"Photoshoot of",
"A breathtaking",
"An extremely detailed",
"An establishing shot of",
"A concept art of",
"A breathtaking portrait of a majestic",
"A charcoal sketch of",
"A dramatic scene of",
"A painting in the style of",
"An isolated",
"An (upper angle shot) of",
"An (aerial perspective photo) of a",
"A high contrast side light scene",
"A dark And mysterious ",
"A clay sculpture of",
"A digital illustration featuring",
"A graffiti art piece depicting",
"A historical reenactment of",
"A leading lines shot of",
"A low angle view of",
"A misty dawn over",
"A mixed media collage showcasing",
"A panoramic view of",
"A pastel portrait of",
"A pencil drawing of",
"A tight shot of",
"A watercolor painting of",
"A National Geographic wildlife photographer capturing",
"A worm's eye view of",
"An ink drawing depicting",
"Masterpiece,",
"A mesmerizing glimpse of",
"A captivating display of",
"A dynamic interplay of",
"A sublime vision of",
"A breathtaking portrayal of",
"A poetic interpretation of",
"A striking composition of",
"A vivid tapestry of",
"An enigmatic depiction of",
"A remarkable fusion of",
"A stunning perspective of",
"A harmonious blend of",
"A radical reinterpretation of",
"A delicate sketch of",
"A vibrant composition of",
"A richly textured portrayal of",
"A pioneering outlook of",
"A refined portrait of",
"A sharp focus on",
"A monumental depiction of",
"A fluid rendering of",
"A kinetic expression of",
"A graceful outline of",
"A provocative framework of",
"A subtle balance of",
"A minimalist construction of",
"A dramatic evolution of",
"A whimsical abstraction of",
"A poignant reflection of",
"A pioneering illustration of",
"A sophisticated visualization of",
"An exuberant composition of",
"A bold expression of",
"A lavish interpretation of",
"A masterful arrangement of",
"A futuristic vision of",
"A radiant convergence of",
"A surrealist portrayal of",
"A fragmented mosaic of",
"A cryptic collage of",
"A crystalline perspective on",
"A dreamlike rendition of",
"A kinetic study of",
"A spontaneous capture of",
"A reflective moment of",
"An intense interplay of",
"A layered narrative of",
"A refined synthesis of",
"A chiaroscuro play of",
"A poetic exploration of",
"A reimagined concept of",
"A vigorous depiction of",
"A textured cascade of",
"A visionary abstraction of",
"A monumental snapshot of",
"A scintillating vignette of",
"A graceful melding of",
"A spectral composition of",
"A radiant interplay of",
"A striking juxtaposition of",
"A refined montage of",
"A nuanced portrayal of",
"A visionary construct of",
"An evocative snapshot of",
"A bold fusion of",
"A delicate overlay of",
"A complex layering of",
"A vivid gradient of",
"A kinetic cascade of",
"A luminous texture of",
"A bold silhouette of",
"A high-resolution photographic capture of",
"A sharply focused photographic study of",
"A meticulously framed photographic moment of",
"An ultra-detailed photographic exploration of",
"A dynamic high-contrast photographic depiction of",
"A bold, hyper-realistic photographic rendering of",
"An intimate photographic snapshot of",
"A vividly composed photographic portrayal of",
"A crisp, professional photographic impression of",
"A timeless black-and-white photographic record of",
"A vividly detailed photographic vignette of",
"A dynamic, low-key photographic interpretation of",
"A refined photographic montage of",
"A compelling photographic narrative of",
"A striking high-key photographic expression of",
"A meticulously captured photographic scene of",
"A visionary photographic perspective on",
"An innovative photographic framing of",
"A sophisticated photographic series of",
"A powerful photographic study of",
"A radiant photographic tableau of",
"A minimalist photographic composition of",
"An edgy photographic take on",
"A vibrant photographic freeze-frame of",
"A kinetic photographic capture of",
"A meticulously arranged photographic display of",
"A dramatic photographic snapshot of",
"A crisp, color-rich photographic impression of",
"A bold photographic experiment capturing",
"An avant-garde photographic reinterpretation of",
"A sharply rendered photographic moment of",
"A compelling photographic sequence of",
"A profound photographic observation of",
"A refined photographic layering of",
"A spontaneous photographic capture of",
"A surreal photographic juxtaposition of",
"A masterfully composed photographic glimpse of",
"A radiant photographic slice of",
"A detailed photographic capture of",
"A visually arresting photographic study of"
]
# =========================
# Helpers
# =========================
def sanitize_prompt(prompt: str) -> str:
prompt = (prompt or "").replace("\r", " ").replace("\n", " ").strip()
return " ".join(prompt.split())
def lightly_clean_completion(text: str) -> str:
text = (text or "").strip().replace("\r", " ").replace("\n", " ")
text = " ".join(text.split())
while text.startswith((",", ".", ";", ":", "-", "_")):
text = text[1:].strip()
return text
def trim_to_sentence_boundary(text: str, max_chars: int = 240) -> str:
text = text.strip()
if len(text) <= max_chars:
return text
trimmed = text[:max_chars].rstrip()
last_stop = max(trimmed.rfind("."), trimmed.rfind(","), trimmed.rfind(";"), trimmed.rfind(":"))
if last_stop > 80:
trimmed = trimmed[:last_stop].rstrip()
return trimmed.rstrip(",;:- ")
def prepare_full_prompt(prompt: str, completion: str) -> str:
prompt = prompt.strip()
completion = lightly_clean_completion(completion)
completion = trim_to_sentence_boundary(completion, 240)
if not completion:
return prompt
if completion.lower().startswith(prompt.lower()):
return completion
if prompt.endswith((" ", ",", ":", ";")):
return f"{prompt}{completion}"
return f"{prompt} {completion}"
def dedupe_preserve_order(items):
seen = set()
out = []
for item in items:
key = item.strip().lower()
if key and key not in seen:
seen.add(key)
out.append(item)
return out
def get_available_models():
return [name for name, path in model_versions.items() if os.path.exists(path)]
# =========================
# Model loading
# =========================
def load_model(model_name):
global llm, current_model
with model_lock:
if llm is not None and current_model == model_name:
print(f"[MODEL] Already loaded: {model_name}")
return
model_path = model_versions[model_name]
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model file not found at {model_path}")
print("\n" + "=" * 60)
print(f"[MODEL] Loading model: {model_name}")
print(f"[MODEL] Path: {model_path}")
llm = None
gc.collect()
llm_local = Llama(
model_path=model_path,
n_ctx=1024,
n_threads=2,
n_batch=256,
verbose=False
)
llm = llm_local
current_model = model_name
print(f"[MODEL] Loaded successfully: {model_name}")
print("=" * 60 + "\n")
# =========================
# Generation
# =========================
def generate_completions(prompt, n_responses, max_tokens, temperature, top_p, top_k, repeat_penalty):
global llm, current_model
prompt = sanitize_prompt(prompt)
if not prompt:
return "Please enter a prompt."
if len(prompt) > 420:
return "Prompt too long. Please keep it under 420 characters."
if llm is None:
try:
load_model(current_model)
except Exception as e:
return f"Error while loading model: {e}"
print("\n" + "=" * 60)
print(f"[PROMPT] {prompt}")
print(f"[MODEL] {current_model}")
print(f"[PARAMS] completions={n_responses}, max_tokens={max_tokens}, temp={temperature}, top_p={top_p}, top_k={top_k}, penalty={repeat_penalty}")
results = []
try:
with model_lock:
for i in range(n_responses):
temp_i = temperature
top_p_i = top_p
top_k_i = top_k
if n_responses > 1:
temp_i = min(2.0, max(0.1, temperature + random.uniform(-0.08, 0.10)))
top_p_i = min(1.0, max(0.15, top_p + random.uniform(-0.04, 0.04)))
top_k_i = max(1, min(128, int(top_k + random.randint(-4, 4))))
output = llm(
prompt,
max_tokens=max_tokens,
temperature=temp_i,
top_p=top_p_i,
top_k=top_k_i,
repeat_penalty=repeat_penalty,
echo=False,
stop=["\n", "\n\n", "Prompt:", "Explanation:", "This image", "In this image"]
)
text = output["choices"][0]["text"].strip()
full = prepare_full_prompt(prompt, text)
if full:
results.append(full)
print(f"[RESPONSE {i+1}] {full}")
else:
print(f"[RESPONSE {i+1}] skipped empty result")
except Exception as e:
print(f"[ERROR] Generation failed: {e}")
print("=" * 60 + "\n")
return f"Generation error: {e}"
results = dedupe_preserve_order(results)
print("=" * 60 + "\n")
if not results:
return "No valid completion generated."
return "\n\n".join(results)
# =========================
# UI callbacks
# =========================
def set_random_prompt(n):
selected = random.choice(prompt_list)
return (
selected,
selected,
f"🎲 Random Prompt{'s' if n > 1 else ''}",
f"✨ Generate Prompt{'s' if n > 1 else ''}"
)
def set_prompt_from_dropdown(choice, n):
if not choice:
return gr.update(), f"🎲 Random Prompt{'s' if n > 1 else ''}", f"✨ Generate Prompt{'s' if n > 1 else ''}"
return choice, f"🎲 Random Prompt{'s' if n > 1 else ''}", f"✨ Generate Prompt{'s' if n > 1 else ''}"
def on_model_change(model_name):
try:
load_model(model_name)
return (
f"Model loaded: {model_name}",
f"<div class='model-note'>{model_descriptions.get(model_name, 'Experimental visual prompt continuation model.')}</div>"
)
except Exception as e:
return (
f"Model load error: {e}",
"<div class='model-note'>Unable to load the selected model.</div>"
)
def clear_all(n):
return "", "", f"🎲 Random Prompt{'s' if n > 1 else ''}", f"✨ Generate Prompt{'s' if n > 1 else ''}"
# =========================
# Init
# =========================
available_models = get_available_models()
if not available_models:
raise RuntimeError("No model files were found in the model/ directory.")
if current_model not in available_models:
current_model = available_models[0]
load_model(current_model)
default_prompt = random.choice(prompt_list)
# =========================
# Theme + CSS
# =========================
theme = gr.themes.Base(
primary_hue="indigo",
secondary_hue="slate",
neutral_hue="slate",
radius_size="lg",
text_size="md",
spacing_size="md"
)
custom_css = """
html, body, .gradio-container {
background:
radial-gradient(circle at 8% 10%, rgba(91, 76, 255, 0.22), transparent 24%),
radial-gradient(circle at 92% 8%, rgba(0, 180, 255, 0.14), transparent 22%),
linear-gradient(180deg, #070b14 0%, #0b1020 100%) !important;
color: #eef2ff !important;
min-height: 100vh;
}
.gradio-container {
width: 100% !important;
max-width: min(1680px, 100vw) !important;
margin: 0 auto !important;
padding-left: clamp(14px, 2vw, 28px) !important;
padding-right: clamp(14px, 2vw, 28px) !important;
}
footer {
display: none !important;
}
.app-shell {
width: 100%;
padding-top: 20px;
padding-bottom: 24px;
}
.hero {
width: 100%;
margin-bottom: 18px;
border: 1px solid rgba(255,255,255,0.08);
background: linear-gradient(135deg, rgba(110, 86, 255, 0.16), rgba(0, 194, 255, 0.08));
border-radius: 24px;
padding: 20px 24px;
box-shadow: 0 14px 40px rgba(0, 0, 0, 0.24);
backdrop-filter: blur(10px);
}
.main-grid {
gap: 18px !important;
align-items: stretch !important;
}
.panel {
background: rgba(12, 17, 30, 0.82) !important;
border: 1px solid rgba(255,255,255,0.07) !important;
border-radius: 22px !important;
box-shadow: 0 14px 34px rgba(0,0,0,0.18) !important;
backdrop-filter: blur(10px);
padding: 16px !important;
}
.left-stack, .right-stack {
gap: 14px !important;
}
.model-note {
margin-top: 8px;
font-size: 13px;
color: #a5b4fc;
line-height: 1.45;
}
.output-panel {
height: 100%;
min-height: 520px;
}
.block-label, label, .gr-form > label, .wrap > label {
color: #dbe7ff !important;
}
.gradio-textbox textarea,
.gradio-textbox input,
.gradio-dropdown input,
.gradio-dropdown textarea,
.gradio-dropdown .secondary-wrap input,
.gradio-dropdown .wrap-inner input,
.gradio-number input,
.gradio-multimodal-textbox textarea {
background: rgba(255,255,255,0.06) !important;
border: 1px solid rgba(255,255,255,0.10) !important;
color: #f8fbff !important;
-webkit-text-fill-color: #f8fbff !important;
border-radius: 16px !important;
opacity: 1 !important;
}
.gradio-textbox textarea::placeholder,
.gradio-textbox input::placeholder,
.gradio-dropdown input::placeholder {
color: #9fb0cb !important;
-webkit-text-fill-color: #9fb0cb !important;
opacity: 1 !important;
}
.gradio-dropdown .wrap-inner,
.gradio-dropdown .wrap,
.gradio-dropdown .secondary-wrap {
color: #f8fbff !important;
}
.gradio-dropdown .token,
.gradio-dropdown .selected,
.gradio-dropdown [data-testid="dropdown"] input,
.gradio-dropdown [data-testid="dropdown"] span {
color: #f8fbff !important;
-webkit-text-fill-color: #f8fbff !important;
}
.gradio-dropdown .options,
.gradio-dropdown .options *,
.gradio-dropdown ul,
.gradio-dropdown li {
background: #111827 !important;
color: #f8fbff !important;
}
.gradio-textbox textarea:disabled,
.gradio-textbox input:disabled,
.gradio-dropdown input:disabled,
.gradio-number input:disabled {
color: #d9e3f3 !important;
-webkit-text-fill-color: #d9e3f3 !important;
opacity: 1 !important;
}
.statusbox textarea,
.statusbox input {
color: #86efac !important;
-webkit-text-fill-color: #86efac !important;
font-weight: 700 !important;
opacity: 1 !important;
}
button {
border-radius: 16px !important;
border: 1px solid rgba(255,255,255,0.08) !important;
font-weight: 700 !important;
transition: all 0.18s ease !important;
}
button:hover {
transform: translateY(-1px);
filter: brightness(1.05);
}
.generate-btn button {
background: linear-gradient(135deg, #6d5dfc 0%, #21c7ff 100%) !important;
color: #ffffff !important;
box-shadow: 0 10px 30px rgba(70, 110, 255, 0.25);
}
.secondary-btn button {
background: rgba(255,255,255,0.07) !important;
color: #eef2ff !important;
}
.slim-btn button {
min-height: 48px !important;
}
.output-panel textarea {
font-size: 15px !important;
line-height: 1.65 !important;
min-height: 420px !important;
}
.copy-note {
color: #94a3b8;
font-size: 12px;
margin-top: 8px;
}
.gradio-textbox, .gradio-dropdown, .gradio-slider, .gradio-accordion {
--block-background-fill: rgba(12, 17, 30, 0.62) !important;
--input-background-fill: rgba(255,255,255,0.04) !important;
}
.gradio-accordion {
background: rgba(12, 17, 30, 0.72) !important;
border: 1px solid rgba(255,255,255,0.07) !important;
border-radius: 18px !important;
}
textarea {
scrollbar-color: rgba(255,255,255,0.24) transparent;
}
.btn-row {
gap: 10px !important;
}
.compact-row {
gap: 12px !important;
}
@media (max-width: 1200px) {
.output-panel {
min-height: 460px;
}
}
@media (max-width: 900px) {
.panel {
border-radius: 18px !important;
padding: 14px !important;
}
.output-panel {
min-height: 360px;
}
}
@media (max-width: 768px) {
.gradio-container {
padding-left: 12px !important;
padding-right: 12px !important;
}
.output-panel {
min-height: 280px;
}
.output-panel textarea {
min-height: 280px !important;
}
.btn-row {
flex-direction: column !important;
}
.btn-row > * {
width: 100% !important;
}
}
"""
# =========================
# UI
# =========================
with gr.Blocks(theme=theme, css=custom_css, title="WizzGPT Prompt Generator") as demo:
with gr.Column(elem_classes=["app-shell"]):
with gr.Column(elem_classes=["hero"]):
gr.Markdown("## ✨ WizzGPT β€” Forget logic. Embrace surprise. This model creates visual wonder, not narrative clarity.")
with gr.Row(equal_height=True, elem_classes=["main-grid"]):
with gr.Column(scale=7, min_width=420, elem_classes=["left-stack"]):
with gr.Column(elem_classes=["panel"]):
with gr.Row(elem_classes=["compact-row"]):
model_selector = gr.Dropdown(
choices=available_models,
value=current_model,
label="🧠 Select Model",
interactive=True
)
model_status = gr.Textbox(
value=f"Model loaded: {current_model}",
label="Status",
interactive=False,
elem_classes=["statusbox"]
)
model_hint = gr.HTML(
f"<div class='model-note'>{model_descriptions.get(current_model, '')}</div>"
)
prompt_input = gr.Textbox(
label="πŸ“ Prompt",
lines=4,
value=default_prompt,
placeholder="Type a prompt start or pick one below..."
)
with gr.Row(elem_classes=["compact-row"]):
prompt_dropdown = gr.Dropdown(
choices=prompt_list,
value=default_prompt,
label="πŸ“Œ Prompt Examples",
scale=4
)
random_button = gr.Button(
"🎲 Random",
scale=1,
elem_classes=["secondary-btn", "slim-btn"]
)
n_responses = gr.Slider(
1, 7, value=3, step=1,
label="Number of Completions"
)
with gr.Accordion("βš™οΈ Advanced Settings", open=False):
max_tokens = gr.Slider(10, 140, value=55, step=5, label="Max Tokens")
temperature = gr.Slider(0.1, 2.0, value=1.25, step=0.05, label="Temperature")
top_p = gr.Slider(0.0, 1.0, value=0.90, step=0.05, label="Top-p")
top_k = gr.Slider(0, 128, value=40, step=1, label="Top-k")
repeat_penalty = gr.Slider(0.5, 2.0, value=1.35, step=0.05, label="Repeat Penalty")
with gr.Row(elem_classes=["btn-row"]):
generate_button = gr.Button(
"✨ Generate Prompt(s)",
elem_classes=["generate-btn", "slim-btn"]
)
reroll_button = gr.Button(
"πŸ”„ Reroll",
elem_classes=["secondary-btn", "slim-btn"]
)
clear_button = gr.Button(
"🧹 Clear",
elem_classes=["secondary-btn", "slim-btn"]
)
with gr.Column(scale=8, min_width=420, elem_classes=["right-stack"]):
with gr.Column(elem_classes=["panel", "output-panel"]):
output = gr.Textbox(
label="πŸ“„ Generated Completions",
lines=20,
max_lines=28,
show_copy_button=True,
placeholder="Your generated prompt continuations will appear here..."
)
gr.HTML('<div class="copy-note">Tip: V3 is more SDXL-like, V6/V7 are more natural and exploratory. Lower Max Tokens for tighter results.</div>')
prompt_dropdown.change(
set_prompt_from_dropdown,
[prompt_dropdown, n_responses],
[prompt_input, random_button, generate_button]
)
random_button.click(
set_random_prompt,
inputs=n_responses,
outputs=[prompt_input, prompt_dropdown, random_button, generate_button]
)
n_responses.change(
lambda n: (
f"🎲 Random Prompt{'s' if n > 1 else ''}",
f"✨ Generate Prompt{'s' if n > 1 else ''}"
),
inputs=n_responses,
outputs=[random_button, generate_button]
)
generate_button.click(
fn=generate_completions,
inputs=[prompt_input, n_responses, max_tokens, temperature, top_p, top_k, repeat_penalty],
outputs=output
)
reroll_button.click(
fn=generate_completions,
inputs=[prompt_input, n_responses, max_tokens, temperature, top_p, top_k, repeat_penalty],
outputs=output
)
model_selector.change(
on_model_change,
inputs=model_selector,
outputs=[model_status, model_hint]
)
clear_button.click(
clear_all,
inputs=n_responses,
outputs=[prompt_input, output, random_button, generate_button]
)
demo.queue().launch()