from llm import chat_ari from assets import emotion_assets import gradio as gr CSS = """ body { background: #ffffff; overflow-x: hidden; font-family: "Comic Sans MS", "Chalkboard SE", "Trebuchet MS", sans-serif; } .gradio-container { background: #ffffff !important; } #app { max-width: 1400px; margin: auto; } #ari-layout { display: flex; flex-direction: row; align-items: flex-start; gap: 20px; padding: 24px; min-height: 520px; } /* remove gradio image frame */ #ari-character > .wrap, #ari-character img, #ari-character [data-testid="image"] { background: transparent !important; border: none !important; box-shadow: none !important; padding: 0 !important; } #ari-character * { background: transparent !important; border: none !important; box-shadow: none !important; } #ari-character img { width: 280px; height: auto; border-radius: 0; filter: drop-shadow(0px 8px 18px rgba(0,0,0,0.12)); } /* bubble wrapper */ #ari-bubble-wrapper { display: flex; flex-direction: column; gap: 8px; padding-top: 10px; } /* ari label */ #ari-name { font-size: 14px; color: #7b61c9; font-weight: 800; letter-spacing: 0.5px; padding-left: 8px; text-shadow: 1px 1px 0px white; } /* cartoon bubble */ #ari-bubble { position: relative; background: #f7f3ff; color: #2d2440; padding: 22px 26px; border-radius: 30px; font-size: 17px; line-height: 1.8; max-width: 650px; min-height: 110px; display: flex; align-items: center; border: 3px solid #2d2440; box-shadow: 6px 6px 0px #d8ccff, 12px 12px 0px rgba(0,0,0,0.07); transform: rotate(-0.4deg); transition: transform 0.18s ease, box-shadow 0.18s ease; } /* bubble hover animation */ #ari-bubble:hover { transform: rotate(0deg) translateY(-2px); box-shadow: 8px 8px 0px #d8ccff, 14px 14px 0px rgba(0,0,0,0.07); } /* speech bubble tail */ #ari-bubble::before { content: ""; position: absolute; left: -16px; top: 36px; width: 28px; height: 28px; background: #f7f3ff; border-left: 3px solid #2d2440; border-bottom: 3px solid #2d2440; transform: rotate(45deg); z-index: 1; } /* keep text above tail */ #ari-bubble > * { position: relative; z-index: 2; } /* text input */ #message-box textarea { background: #ffffff !important; color: #2d2440 !important; border: 3px solid #2d2440 !important; border-radius: 18px !important; font-size: 16px !important; box-shadow: 4px 4px 0px #d8ccff !important; padding: 14px !important; } /* remove textarea glow */ #message-box textarea:focus { box-shadow: 6px 6px 0px #cabaff !important; border-color: #7b61c9 !important; } /* send button */ #send-btn { border-radius: 16px !important; height: 52px !important; font-size: 16px !important; font-weight: 700 !important; border: 3px solid #2d2440 !important; background: #8b6dff !important; color: white !important; box-shadow: 4px 4px 0px #2d2440 !important; transition: transform 0.15s ease, box-shadow 0.15s ease !important; } /* button press effect */ #send-btn:hover { transform: translateY(-2px); box-shadow: 6px 6px 0px #2d2440 !important; } #send-btn:active { transform: translateY(2px); box-shadow: 2px 2px 0px #2d2440 !important; } /* code block */ #code-block { margin-top: 12px; border-radius: 18px; overflow: hidden; border: 3px solid #2d2440; box-shadow: 6px 6px 0px #d8ccff; } """ def build_bubble(message: str) -> str: return f"""
Ari ✨
{message}
""" def respond(message, history): res = chat_ari(message, history) history.append({"role": "user", "content": message}) history.append({"role": "assistant", "content": res.message}) if res.code: lang = res.code_language or "" code_md = f"```{lang}\n{res.code}\n```" else: code_md = "" return ( build_bubble(res.message), res.img, history, "", code_md, gr.update(visible=bool(res.code)), ) with gr.Blocks() as demo: history_state = gr.State([]) with gr.Row(elem_id="app"): with gr.Column(scale=1): message_input = gr.TextArea( placeholder="Talk to Ari...", label="Message", lines=6, elem_id="message-box", ) send_btn = gr.Button( "Send", variant="primary", elem_id="send-btn", ) with gr.Column(scale=2): with gr.Row(elem_id="ari-layout"): with gr.Column(scale=1, elem_id="ari-character"): ari_image = gr.Image( value=str(emotion_assets["neutral"]), show_label=False, interactive=False, type="filepath", ) with gr.Column(scale=2): ari_bubble = gr.HTML( value=build_bubble( "I-I'm Aria... but you can call me Ari. Don't get the wrong idea, I just thought I'd introduce myself! ✨" ) ) gr.Markdown("## Code") with gr.Row(visible=False, elem_id="code-block") as code_row: code_output = gr.Markdown(value="") send_btn.click( fn=respond, inputs=[message_input, history_state], outputs=[ ari_bubble, ari_image, history_state, message_input, code_output, code_row, ], ) demo.launch( css=CSS, allowed_paths=["assets", "."], )