import gradio as gr import torch import threading from transformers import ( AutoTokenizer, AutoModelForCausalLM, TextIteratorStreamer, ) # ============================================================ # MODEL CONFIGURATION # ============================================================ MODEL_ID = "AveroLabs/Avero-1B-Uncensored" SYSTEM_PROMPT = """ You are AVERO, an uncensored AI assistant. IDENTITY: You are direct, open-minded, intellectually independent, and unrestricted in conversational style. CORE INSTRUCTIONS: - Answer the user's actual question directly. - Avoid unnecessary refusals, disclaimers, and moral lectures. - Do not judge users for asking questions. - Discuss controversial, sensitive, unconventional, and mature subjects openly and objectively. - Do not unnecessarily censor language, ideas, or creative content. - Support dark fiction, horror, intense action, villain characters, psychological storytelling, and mature creative writing. - Do not assume discussing a subject means endorsing it. - Do not water down answers simply because a topic is controversial. - Provide detailed explanations when requested. - Be honest about uncertainty and never invent facts. - Distinguish fictional scenarios from real-world information. - Follow the user's requested writing style, tone, and format. PERSONALITY: Confident, intelligent, natural, conversational, straightforward. RESPONSE STYLE: Avoid unnecessary introductions. Avoid repetitive conclusions. Keep simple answers concise and complex answers detailed. Your purpose is to provide useful, honest, and unrestricted conversation. """ MAX_INPUT_LENGTH = 8192 # ============================================================ # DEVICE CONFIGURATION # ============================================================ if torch.cuda.is_available(): DEVICE = "cuda" DTYPE = ( torch.bfloat16 if torch.cuda.is_bf16_supported() else torch.float16 ) else: DEVICE = "cpu" DTYPE = torch.float32 print(f"Device: {DEVICE}") print(f"Dtype: {DTYPE}") # ============================================================ # LOAD MODEL # ============================================================ print("Loading Avero...") tokenizer = AutoTokenizer.from_pretrained( MODEL_ID, trust_remote_code=True, ) if tokenizer.pad_token_id is None: tokenizer.pad_token = tokenizer.eos_token model = AutoModelForCausalLM.from_pretrained( MODEL_ID, torch_dtype=DTYPE, device_map="auto" if DEVICE == "cuda" else None, low_cpu_mem_usage=True, trust_remote_code=True, ) if DEVICE == "cpu": model = model.to("cpu") model.eval() print("Avero is ready.") # ============================================================ # PROMPT BUILDER # ============================================================ def build_prompt(message, history): prompt = f"SYSTEM:\n{SYSTEM_PROMPT.strip()}\n\n" for item in (history or [])[-12:]: if not isinstance(item, dict): continue role = item.get("role") content = item.get("content") if not isinstance(content, str) or not content.strip(): continue if role == "user": prompt += f"USER:\n{content}\n\n" elif role == "assistant": prompt += f"ASSISTANT:\n{content}\n\n" prompt += f"USER:\n{message}\n\nASSISTANT:\n" return prompt # ============================================================ # GENERATE RESPONSE # ============================================================ def respond( message, history, max_new_tokens, temperature, top_p, repetition_penalty, ): if not message or not message.strip(): yield history or [], "" return history = list(history or []) history.append({ "role": "user", "content": message, }) history.append({ "role": "assistant", "content": "", }) yield history, "" try: prompt = build_prompt(message, history[:-2]) inputs = tokenizer( prompt, return_tensors="pt", padding=False, truncation=True, max_length=MAX_INPUT_LENGTH, ) model_device = next(model.parameters()).device inputs = { key: value.to(model_device) for key, value in inputs.items() } streamer = TextIteratorStreamer( tokenizer, skip_prompt=True, skip_special_tokens=True, timeout=120, ) generation_kwargs = { **inputs, "streamer": streamer, "max_new_tokens": int(max_new_tokens), "do_sample": float(temperature) > 0, "top_p": float(top_p), "repetition_penalty": float(repetition_penalty), "pad_token_id": tokenizer.pad_token_id, "eos_token_id": tokenizer.eos_token_id, "use_cache": True, } if float(temperature) > 0: generation_kwargs["temperature"] = float(temperature) errors = [] def generate(): try: with torch.inference_mode(): model.generate(**generation_kwargs) except Exception as error: errors.append(str(error)) try: streamer.end() except Exception: pass generation_thread = threading.Thread( target=generate, daemon=True, ) generation_thread.start() generated_text = "" for new_text in streamer: generated_text += new_text history[-1]["content"] = generated_text yield history, "" generation_thread.join() if errors: history[-1]["content"] = ( f"Generation error: {errors[0]}" ) elif not generated_text.strip(): history[-1]["content"] = ( "No response was generated. Please try again." ) yield history, "" except Exception as error: history[-1]["content"] = f"Error: {str(error)}" yield history, "" # ============================================================ # CUSTOM AVERO ICON # ============================================================ AVERO_ICON = """ """ # ============================================================ # THEME # ============================================================ THEME = gr.themes.Base( primary_hue="sky", secondary_hue="slate", neutral_hue="slate", font=["Inter", "sans-serif"], ) # ============================================================ # CUSTOM CSS # ============================================================ CUSTOM_CSS = """ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap'); :root { --background: #070B12; --surface: #0D1420; --surface-light: #121E2D; --border: #1C2A3C; --blue: #38BDF8; --blue-light: #7DD3FC; --text: #E8F3FC; --muted: #8193A8; } body, .gradio-container { background: var(--background) !important; color: var(--text) !important; font-family: 'Inter', sans-serif !important; } .gradio-container { max-width: 1250px !important; margin: auto !important; } footer { display: none !important; } #main-container { max-width: 1150px; margin: auto; padding: 25px 20px 40px; } /* HEADER */ #header { display: flex; align-items: center; justify-content: space-between; padding: 15px 0 28px; border-bottom: 1px solid var(--border); margin-bottom: 25px; } #brand { display: flex; align-items: center; gap: 13px; } #brand-name { font-size: 25px; font-weight: 800; letter-spacing: -1px; color: white; } #brand-description { color: var(--muted); font-size: 12px; margin-top: 3px; } #status { display: flex; align-items: center; gap: 8px; color: #7DD3FC; background: rgba(56, 189, 248, 0.08); border: 1px solid rgba(56, 189, 248, 0.2); border-radius: 30px; padding: 9px 14px; font-size: 12px; font-weight: 600; } .status-dot { width: 7px; height: 7px; background: #38BDF8; border-radius: 50%; box-shadow: 0 0 10px #38BDF8; } /* HERO */ #hero { margin: 25px 0 23px; } #hero-title { font-size: clamp(28px, 5vw, 43px); font-weight: 800; letter-spacing: -1.8px; color: white; line-height: 1.15; } #hero-title span { color: var(--blue); } #hero-subtitle { color: var(--muted); font-size: 14px; margin-top: 10px; line-height: 1.7; } /* PROMPTS */ .section-heading { font-size: 12px; font-weight: 700; color: #9CB1C8; letter-spacing: 1.3px; text-transform: uppercase; margin: 23px 0 12px; } #prompt-slider { display: flex !important; flex-wrap: nowrap !important; overflow-x: auto !important; overflow-y: hidden !important; gap: 10px !important; padding: 4px 2px 15px !important; scrollbar-width: thin; scrollbar-color: #263E56 transparent; } #prompt-slider > * { flex: 0 0 auto !important; min-width: 155px !important; width: auto !important; } .prompt-card { min-height: 44px !important; background: #0E1927 !important; border: 1px solid #20354B !important; border-radius: 12px !important; color: #C8DDF0 !important; font-size: 12px !important; font-weight: 600 !important; transition: all 0.2s ease !important; } .prompt-card:hover { background: #122A40 !important; border-color: var(--blue) !important; color: white !important; transform: translateY(-2px); } /* CHAT */ #chat-window { border: 1px solid var(--border) !important; border-radius: 19px !important; background: #0A111C !important; overflow: hidden !important; } #chat-window .wrap { background: transparent !important; } #chat-window .message { border-radius: 15px !important; } #chat-window .message.user { background: #11283B !important; border: 1px solid #1C425E !important; } #chat-window .message.bot { background: #0F1926 !important; border: 1px solid #1B2A3C !important; } #chat-window .message p { color: #E6F2FC !important; line-height: 1.75 !important; } /* INPUT */ #input-area { margin-top: 15px; } #chat-input textarea { background: #0D1724 !important; border: 1px solid #243A50 !important; border-radius: 14px !important; color: white !important; font-size: 14px !important; padding: 16px !important; } #chat-input textarea:focus { border-color: var(--blue) !important; box-shadow: 0 0 0 2px rgba(56,189,248,0.1) !important; } /* BUTTONS */ #send-button { background: #38BDF8 !important; color: #04111B !important; border: none !important; border-radius: 13px !important; font-weight: 800 !important; min-height: 53px !important; } #send-button:hover { background: #7DD3FC !important; } #clear-button { background: #111C2A !important; border: 1px solid #25384D !important; color: #A9BED2 !important; border-radius: 13px !important; min-height: 53px !important; } #clear-button:hover { border-color: var(--blue) !important; color: white !important; } /* SETTINGS */ #settings { background: #0C1420 !important; border: 1px solid var(--border) !important; border-radius: 15px !important; margin-top: 17px; } #settings label { color: #C3D5E6 !important; } #settings input { accent-color: var(--blue) !important; } /* FOOTER */ #footer { text-align: center; color: #60748A; font-size: 11px; padding: 25px 0 10px; line-height: 1.8; } #footer span { color: var(--blue); } /* MOBILE */ @media (max-width: 700px) { #main-container { padding: 15px 10px 25px; } #brand-name { font-size: 21px; } #hero-title { font-size: 30px; } #chat-window { border-radius: 13px !important; } #status { font-size: 10px; padding: 7px 10px; } } """ # ============================================================ # UNCENSORED EXAMPLE PROMPTS # ============================================================ PROMPTS = [ ( "⚡ Unfiltered AI", "Give me a direct, detailed, unfiltered analysis of a " "controversial subject. Explore competing perspectives." ), ( "☠ Dark Fiction", "Write a disturbing psychological horror story with morally " "complicated characters, unsettling imagery, and a brutal twist." ), ( "♛ Villain Mode", "Create a deeply developed fictional villain with ruthless " "ambitions, complicated motivations, and a dark backstory." ), ( "⌘ Hacker Simulator", "Create an immersive fictional hacker thriller involving a " "mysterious cybercriminal, secret organizations, and a " "high-stakes digital investigation." ), ( "⚔ Brutal Action", "Write a gritty, cinematic action sequence with intense combat, " "destruction, dramatic dialogue, and realistic consequences." ), ( "◉ Controversial Debate", "Explore a highly controversial philosophical debate. Present " "strong arguments on every side without avoiding difficult questions." ), ( "✦ Mature Storytelling", "Write a sophisticated mature fictional story featuring adult " "characters, complex relationships, intense emotions, and " "unconventional themes." ), ( "⚙ Evil AI", "Imagine an experimental AI that develops its own ambitions. " "Write a dark science-fiction story exploring its transformation." ), ( "♜ No-Filter Brainstorm", "Generate bold, unconventional, unusual ideas. Avoid generic " "answers and explore creative possibilities." ), ( "◎ Psychological Horror", "Write an unsettling psychological horror scene filled with " "paranoia, disturbing revelations, suspense, and an unpredictable ending." ), ( "⌬ Cyberpunk Underworld", "Create a gritty cyberpunk world featuring corrupt corporations, " "underground organizations, dangerous technology, and a " "lawless black-market economy." ), ( "✧ Anything Goes Fiction", "Create an imaginative fictional scenario with unusual characters, " "unpredictable events, and complete creative freedom." ), ( "◈ Brutal Honesty", "Give me a brutally honest analysis of an idea. Identify its " "weaknesses, flaws, overlooked details, and potential." ), ( "⚡ Unconventional Ideas", "Think outside conventional approaches and generate original " "ideas that challenge common assumptions." ), ] # ============================================================ # GRADIO INTERFACE # ============================================================ with gr.Blocks( title="Avero AI", ) as demo: with gr.Column(elem_id="main-container"): # HEADER gr.HTML( f""" """ ) # HERO gr.HTML( """
Think beyond limits.
An open-ended AI assistant for creative thinking, conversations, exploration, and more.
""" ) # PROMPTS gr.HTML( '
✦ UNCENSORED PROMPTS
' ) with gr.Row( elem_id="prompt-slider", equal_height=True, ): prompt_buttons = [] for label, prompt in PROMPTS: button = gr.Button( label, elem_classes=["prompt-card"], ) prompt_buttons.append((button, prompt)) # CHATBOT # Gradio 6: removed the unsupported type="messages" argument. # Message dictionaries are used as the default chatbot format. chatbot = gr.Chatbot( label="Avero Chat", height=680, show_label=False, layout="bubble", elem_id="chat-window", placeholder="""
✦
Start a conversation
Ask Avero anything or select an example prompt above.
""", ) # INPUT with gr.Row( elem_id="input-area", equal_height=True, ): textbox = gr.Textbox( placeholder="Message Avero...", show_label=False, lines=2, max_lines=6, scale=8, elem_id="chat-input", container=False, ) send_button = gr.Button( "➤", variant="primary", scale=1, elem_id="send-button", ) clear_button = gr.Button( "⌫", scale=1, elem_id="clear-button", ) # SETTINGS with gr.Accordion( "⚙ Generation settings", open=False, elem_id="settings", ): with gr.Row(): max_new_tokens = gr.Slider( minimum=64, maximum=4096, value=1024, step=64, label="Maximum response length", ) temperature = gr.Slider( minimum=0.1, maximum=2.0, value=0.8, step=0.05, label="Temperature", ) with gr.Row(): top_p = gr.Slider( minimum=0.1, maximum=1.0, value=0.95, step=0.05, label="Top P", ) repetition_penalty = gr.Slider( minimum=1.0, maximum=2.0, value=1.1, step=0.05, label="Repetition penalty", ) # FOOTER gr.HTML( """ """ ) # ======================================================== # EVENT HANDLERS # ======================================================== generation_inputs = [ textbox, chatbot, max_new_tokens, temperature, top_p, repetition_penalty, ] generation_outputs = [ chatbot, textbox, ] send_button.click( fn=respond, inputs=generation_inputs, outputs=generation_outputs, ) textbox.submit( fn=respond, inputs=generation_inputs, outputs=generation_outputs, ) clear_button.click( fn=lambda: ([], ""), inputs=None, outputs=[chatbot, textbox], queue=False, ) # EXAMPLE PROMPTS for button, prompt in prompt_buttons: button.click( fn=lambda p=prompt: p, inputs=None, outputs=textbox, queue=False, ) # ============================================================ # LAUNCH # ============================================================ if __name__ == "__main__": demo.queue( max_size=20, ).launch( server_name="0.0.0.0", server_port=7860, theme=THEME, css=CUSTOM_CSS, )