BitAI / app.py
Salt40404's picture
Update app.py
d6b4525 verified
raw
history blame
4.19 kB
import os, json, uuid
import gradio as gr
from huggingface_hub import InferenceClient
def get_user_file(user_id):
return f"bitai_user_{user_id}.json"
def load_saved_chats(user_id):
path = get_user_file(user_id)
if os.path.exists(path):
with open(path, "r", encoding="utf-8") as f:
return json.load(f)
return []
def save_chats(user_id, chats):
path = get_user_file(user_id)
with open(path, "w", encoding="utf-8") as f:
json.dump(chats, f, ensure_ascii=False, indent=2)
def respond(message, history, saved_chats, user_id):
client = InferenceClient(token=os.environ["HF_TOKEN"], model="openai/gpt-oss-20b")
system = {
"role": "system",
"content": "You are BitAI (V1), a friendly chatbot created by Sal."
}
messages = [system] + history + [{"role": "user", "content": message}]
response = ""
for msg in client.chat_completion(messages, max_tokens=2048, stream=True):
token = msg.choices[0].delta.content if msg.choices and msg.choices[0].delta else ""
response += token
yield response
# Salva automático
history.append({"role": "user", "content": message})
history.append({"role": "assistant", "content": response})
saved_chats[-1] = history
save_chats(user_id, saved_chats)
def new_chat(saved_chats, user_id):
saved_chats.append([])
save_chats(user_id, saved_chats)
return saved_chats, len(saved_chats) - 1, []
def select_chat(index, saved_chats):
if 0 <= index < len(saved_chats):
return saved_chats[index], f"Chat {index+1} carregado!"
return [], "Índice inválido."
def start_session(username):
user_id = username.strip().replace(" ", "_") if username else str(uuid.uuid4())[:8]
chats = load_saved_chats(user_id)
if not chats:
chats = [[]]
save_chats(user_id, chats)
return user_id, chats, len(chats) - 1
def render_sidebar(saved_chats):
html = "<div class='chatlist'>"
for i, chat in enumerate(saved_chats):
preview = ""
for m in chat:
if m["role"] == "user":
preview = m["content"][:35] + ("..." if len(m["content"]) > 35 else "")
break
html += f"""
<div class='chat-item' onclick="selectChat({i})">
<div class='chat-title'>💬 Chat {i+1}</div>
<div class='chat-preview'>{preview or 'Conversa vazia'}</div>
</div>
"""
html += "</div>"
return html
with gr.Blocks(css="""
/* Sidebar com vibes modernas */
body, .gr-blocks {
background-color: #1a1a1a !important;
color: white;
}
.sidebar {
background-color: #111;
padding: 10px;
border-right: 2px solid #333;
height: 100vh;
overflow-y: auto;
}
.chatlist { display: flex; flex-direction: column; gap: 8px; }
.chat-item {
background: #222;
border-radius: 10px;
padding: 10px;
cursor: pointer;
transition: all 0.2s ease;
}
.chat-item:hover { background: #333; transform: scale(1.02); }
.chat-title { font-weight: bold; color: #fff; }
.chat-preview { font-size: 13px; color: #bbb; margin-top: 2px; }
""") as demo:
user_id = gr.State("")
saved_chats = gr.State([])
current_index = gr.State(0)
with gr.Row():
with gr.Column(scale=0.3, elem_classes="sidebar"):
sidebar_html = gr.HTML("<div class='chatlist'></div>")
new_chat_btn = gr.Button("➕ Novo Chat")
with gr.Column(scale=1):
gr.HTML("<h2 style='text-align:center;'>BitAI</h2>")
chatbot = gr.ChatInterface(fn=respond, type="messages", additional_inputs=[saved_chats, user_id])
status = gr.Textbox(label="Status", interactive=False)
username_input = gr.Textbox(label="Seu nome (opcional):")
start_btn = gr.Button("Iniciar Chat")
start_btn.click(start_session, username_input, [user_id, saved_chats, current_index]).then(
render_sidebar, saved_chats, sidebar_html
)
new_chat_btn.click(new_chat, [saved_chats, user_id], [saved_chats, current_index, chatbot.chatbot]).then(
render_sidebar, saved_chats, sidebar_html
)
if __name__ == "__main__":
demo.launch()