BitAI / app.py
Salt40404's picture
Update app.py
f32ae54 verified
raw
history blame
6.24 kB
import gradio as gr
from huggingface_hub import InferenceClient
# Função principal do chatbot
def respond(message, history: list[dict[str, str]], hf_token: gr.OAuthToken):
client = InferenceClient(token=hf_token.token, model="openai/gpt-oss-20b")
system_message = """You are BitAI (or Bit for short), a friendly chatbot created by the user "Sal".
You respond politely, refuse inapropriate requests, and keep a friendly tone."""
messages = [{"role": "system", "content": system_message}]
messages.extend(history)
messages.append({"role": "user", "content": message})
response = ""
for chunk in client.chat_completion(messages, max_tokens=512, stream=True, temperature=0.7, top_p=0.95):
token = chunk.choices[0].delta.content if chunk.choices and chunk.choices[0].delta.content else ""
response += token
yield response
# JS para animações e ajustes visuais
fade_js = """
<script>
document.addEventListener("DOMContentLoaded", () => {
// Título animado
const grContainer = document.querySelector(".gradio-container");
if(grContainer && !document.querySelector(".chat-title")) {
const titleContainer = document.createElement("div");
titleContainer.className = "title-container";
titleContainer.innerHTML = `
<h1 class="chat-title">Talk with BitAI (W.I.P)</h1>
<p class="chat-subtitle">Still updating, might not know everything, filter slightly broken</p>
`;
grContainer.insertBefore(titleContainer, grContainer.firstChild);
setTimeout(()=>{titleContainer.style.opacity="1"; titleContainer.style.transform="translateY(0)";},100);
}
// Startup message
const chatContainer = document.querySelector(".chat-interface");
if(chatContainer && chatContainer.children.length===0){
const startupMsg = document.createElement("div");
startupMsg.className="startup-message";
startupMsg.innerHTML='<div class="startup-content"><div class="startup-icon">🤖</div><div class="startup-text"><div class="startup-title">BitAI</div><div class="startup-subtitle">How was your day? Good morning!</div><div class="startup-note">Entirely AI</div></div></div>';
chatContainer.appendChild(startupMsg);
setTimeout(()=>{startupMsg.style.opacity="1"; startupMsg.style.transform="translateY(0)";},100);
}
// Observador para animação de novas mensagens
const observer = new MutationObserver(mutations => {
mutations.forEach(m => {
m.addedNodes.forEach(node => {
if(node.classList?.contains('chat-message')){
const startupMsg = document.querySelector(".startup-message");
if(startupMsg){startupMsg.style.opacity="0"; startupMsg.style.transform="translateY(20px)"; setTimeout(()=>startupMsg.remove(),300);}
node.style.opacity=0; node.style.transform='translateY(20px) scale(0.95)';
node.style.transition='all 0.5s ease, box-shadow 0.3s ease';
requestAnimationFrame(()=>{node.style.opacity=1; node.style.transform='translateY(0) scale(1)'; setTimeout(()=>node.style.boxShadow='0 4px 15px rgba(0,0,0,0.2)',500);});
}
});
});
});
if(chatContainer) observer.observe(chatContainer, {childList:true, subtree:true});
// Button dentro do textarea
const btn = document.querySelector(".send-btn");
const txtCont = document.querySelector(".input-container");
if(btn && txtCont){txtCont.style.position="relative"; btn.style.position="absolute"; btn.style.right="8px"; btn.style.top="8px"; btn.style.width="40px"; btn.style.height="40px";}
// Função genérica de bounce
const bounce = el=>{
if(!el || el.hasAttribute("data-bounce-added")) return;
el.setAttribute("data-bounce-added","true");
el.addEventListener("click",()=>{el.style.transition="transform 0.5s cubic-bezier(0.68,-0.55,0.27,1.55)"; el.style.transform="scale(0.95)"; setTimeout(()=>el.style.transform="scale(1)",500);});
};
document.querySelectorAll("button, .chat-message, textarea, .gr-button.gr-login, .chat-title, .chat-subtitle, .startup-message, .gr-chatbot").forEach(bounce);
});
</script>
"""
# Gradio interface
with gr.Blocks(css="""
body{background:#000;margin:0;padding:0;font-family:'Inter','Manrope','Outfit',sans-serif;}
.gradio-container{border-radius:20px;padding:20px;max-width:700px;margin:30px auto;background:linear-gradient(145deg,#0f0f0f,#1a1a1a);box-shadow:0 10px 30px rgba(0,0,0,0.4);transition:transform 0.3s;}
.title-container{opacity:0;transform:translateY(-20px);transition:0.5s;}
.chat-title{font-size:32px;color:#fff;margin-bottom:10px;cursor:pointer;transition:0.3s;}
.chat-subtitle{font-size:14px;color:#aaa;cursor:pointer;transition:0.3s;}
textarea{border:none;border-radius:25px;padding:14px 20px 14px 20px;background:#1a1a1a;color:#fff;font-size:16px;width:100%;height:56px;transition:0.3s;}
.send-btn{border:none;border-radius:20px;background:linear-gradient(145deg,#555,#444);color:#fff;width:40px;height:40px;position:absolute;right:8px;top:8px;cursor:pointer;transition:0.3s;}
.chat-message{border-radius:20px;padding:16px;margin:12px 0;opacity:0;transition:0.5s;box-shadow:0 4px 10px rgba(0,0,0,0.15);}
.chat-message.user{background:linear-gradient(145deg,#252525,#1f1f1f);color:#fff;align-items:flex-end;margin-left:40px;}
.chat-message.bot{background:linear-gradient(145deg,#2e2e2e,#252525);color:#fff;align-items:flex-start;margin-right:40px;}
.startup-message{opacity:0;transform:translateY(20px);transition:0.5s;margin:20px 0;display:flex;justify-content:center;cursor:pointer;}
.startup-content{display:flex;align-items:center;background:linear-gradient(145deg,#2e2e2e,#252525);padding:20px;border-radius:20px;box-shadow:0 4px 15px rgba(0,0,0,0.2);}
.startup-icon{font-size:32px;margin-right:15px;}
.startup-title{font-weight:600;font-size:18px;color:#fff;}
.startup-subtitle{font-size:16px;color:#eee;}
.startup-note{font-size:12px;color:#aaa;font-style:italic;}
""") as demo:
gr.LoginButton()
gr.ChatInterface(respond, type="messages")
gr.HTML(fade_js)
if __name__ == "__main__":
demo.launch()