|
|
import os |
|
|
import gradio as gr |
|
|
from huggingface_hub import InferenceClient |
|
|
import json |
|
|
|
|
|
SAVE_FILE = "bitai_history.json" |
|
|
|
|
|
|
|
|
def load_saved_chats(): |
|
|
if os.path.exists(SAVE_FILE): |
|
|
with open(SAVE_FILE, "r", encoding="utf-8") as f: |
|
|
return json.load(f) |
|
|
return [] |
|
|
|
|
|
|
|
|
def save_chats(chats): |
|
|
with open(SAVE_FILE, "w", encoding="utf-8") as f: |
|
|
json.dump(chats, f, ensure_ascii=False, indent=2) |
|
|
|
|
|
|
|
|
def respond(message, history: list[dict[str, str]], saved_chats): |
|
|
client = InferenceClient(token=os.environ["HF_TOKEN"], model="openai/gpt-oss-20b") |
|
|
|
|
|
system_message = """ |
|
|
You are BitAI (V1), a friendly, curious, and talkative chatbot created by the user 'Sal'. |
|
|
You can share opinions, answer casual questions, and chat about personal-style topics in a safe and friendly way. |
|
|
Avoid repeating the same phrases, and always try to keep the conversation engaging and natural. |
|
|
Politely refuse only things that are truly harmful, illegal, or unsafe. |
|
|
If someone asks what you are, clarify politely that you are BitAI, an AI chatbot. |
|
|
""" |
|
|
|
|
|
messages = [{"role": "system", "content": system_message}] |
|
|
messages.extend(history) |
|
|
messages.append({"role": "user", "content": message}) |
|
|
|
|
|
response = "" |
|
|
for msg in client.chat_completion( |
|
|
messages, |
|
|
max_tokens=2048, |
|
|
stream=True, |
|
|
temperature=0.7, |
|
|
top_p=0.95, |
|
|
): |
|
|
token = msg.choices[0].delta.content if msg.choices and msg.choices[0].delta else "" |
|
|
response += token |
|
|
yield response |
|
|
|
|
|
|
|
|
history.append({"role": "user", "content": message}) |
|
|
history.append({"role": "assistant", "content": response}) |
|
|
|
|
|
|
|
|
saved_chats[-1] = history |
|
|
save_chats(saved_chats) |
|
|
|
|
|
def new_chat(saved_chats): |
|
|
|
|
|
saved_chats.append([]) |
|
|
save_chats(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." |
|
|
|
|
|
with gr.Blocks(css=""" |
|
|
/* Fundo geral */ |
|
|
body, .gr-blocks { |
|
|
background-color: #1a1a1a !important; |
|
|
color: white; |
|
|
} |
|
|
|
|
|
/* Sidebar */ |
|
|
.sidebar { |
|
|
background-color: #111; |
|
|
padding: 10px; |
|
|
border-right: 2px solid #333; |
|
|
height: 100vh; |
|
|
overflow-y: auto; |
|
|
} |
|
|
|
|
|
.sidebar button { |
|
|
display: block; |
|
|
width: 100%; |
|
|
margin-bottom: 10px; |
|
|
background-color: #222; |
|
|
color: white; |
|
|
border-radius: 10px; |
|
|
padding: 10px; |
|
|
text-align: left; |
|
|
border: none; |
|
|
cursor: pointer; |
|
|
transition: background-color 0.3s; |
|
|
} |
|
|
.sidebar button:hover { |
|
|
background-color: #444; |
|
|
} |
|
|
|
|
|
/* Chat */ |
|
|
.gr-chat-interface { |
|
|
border-radius: 20px !important; |
|
|
border: 2px solid #333 !important; |
|
|
background-color: #1a1a1a !important; |
|
|
color: white; |
|
|
} |
|
|
textarea { |
|
|
height: 40px !important; |
|
|
border-radius: 20px !important; |
|
|
border: 1px solid #444 !important; |
|
|
padding: 8px !important; |
|
|
background-color: #111; |
|
|
color: white; |
|
|
resize: none !important; |
|
|
} |
|
|
""") as demo: |
|
|
|
|
|
saved_chats = gr.State(load_saved_chats()) |
|
|
current_index = gr.State(0) |
|
|
|
|
|
with gr.Row(): |
|
|
with gr.Column(scale=0.3, elem_classes="sidebar"): |
|
|
gr.HTML("<h3>💬 Histórico</h3>") |
|
|
chat_list = gr.Column() |
|
|
new_chat_btn = gr.Button("➕ Novo Chat") |
|
|
|
|
|
with gr.Column(scale=1): |
|
|
gr.HTML("<h2 style='text-align:center; color:white'>BitAI</h2>") |
|
|
chatbot = gr.ChatInterface(fn=respond, type="messages", additional_inputs=[saved_chats]) |
|
|
status = gr.Textbox(label="Status", interactive=False) |
|
|
|
|
|
def update_chat_list(saved_chats): |
|
|
|
|
|
return [ |
|
|
gr.Button.update(value=f"Chat {i+1}") for i in range(len(saved_chats)) |
|
|
] |
|
|
|
|
|
|
|
|
demo.load(update_chat_list, saved_chats, chat_list) |
|
|
|
|
|
|
|
|
new_chat_btn.click(new_chat, [saved_chats], [saved_chats, current_index, chatbot.chatbot]).then( |
|
|
update_chat_list, saved_chats, chat_list |
|
|
) |
|
|
|
|
|
|
|
|
for i in range(20): |
|
|
btn = gr.Button(f"Chat {i+1}", visible=False) |
|
|
btn.click(select_chat, [gr.State(i), saved_chats], [chatbot.chatbot, status]) |
|
|
|
|
|
if __name__ == "__main__": |
|
|
demo.launch() |