Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -4,14 +4,13 @@ import os
|
|
| 4 |
import uuid
|
| 5 |
import json
|
| 6 |
|
| 7 |
-
# Thư viện
|
| 8 |
try: from duckduckgo_search import DDGS
|
| 9 |
except: DDGS = None
|
| 10 |
try: from gtts import gTTS
|
| 11 |
except: gTTS = None
|
| 12 |
|
| 13 |
# 1. CẤU HÌNH & MODEL
|
| 14 |
-
# Lưu ý: Bạn cần cấp quyền 'Read' cho HF Token trong Settings của Space
|
| 15 |
HF_TOKEN = os.getenv("HUGGINGFACE_HUB_TOKEN")
|
| 16 |
client = InferenceClient(model="Qwen/Qwen2.5-7B-Instruct", token=HF_TOKEN)
|
| 17 |
DB_FILE = "nodeai_genesis_final.json"
|
|
@@ -27,7 +26,7 @@ def save_db(data):
|
|
| 27 |
with open(DB_FILE, "w", encoding="utf-8") as f:
|
| 28 |
json.dump(data, f, ensure_ascii=False, indent=4)
|
| 29 |
|
| 30 |
-
# 2. GUI DESIGN (
|
| 31 |
custom_css = """
|
| 32 |
@import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@700&family=Plus+Jakarta+Sans:wght@400;600&display=swap');
|
| 33 |
|
|
@@ -55,6 +54,14 @@ custom_css = """
|
|
| 55 |
font-size: 24px; text-align: center; margin-bottom: 30px;
|
| 56 |
}
|
| 57 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 58 |
/* Chat Area */
|
| 59 |
.chat-main {
|
| 60 |
margin-left: 260px !important;
|
|
@@ -67,10 +74,10 @@ custom_css = """
|
|
| 67 |
background: transparent !important;
|
| 68 |
border: none !important;
|
| 69 |
height: 75vh !important;
|
| 70 |
-
margin-bottom:
|
| 71 |
}
|
| 72 |
|
| 73 |
-
/* Thanh nhập liệu cố định
|
| 74 |
.input-fixed-bottom {
|
| 75 |
position: fixed !important;
|
| 76 |
bottom: 25px !important;
|
|
@@ -81,14 +88,6 @@ custom_css = """
|
|
| 81 |
border-radius: 16px !important;
|
| 82 |
padding: 10px !important;
|
| 83 |
z-index: 2000 !important;
|
| 84 |
-
box-shadow: 0 -10px 30px rgba(0,0,0,0.5) !important;
|
| 85 |
-
}
|
| 86 |
-
|
| 87 |
-
.hist-btn {
|
| 88 |
-
background: rgba(255, 255, 255, 0.03) !important;
|
| 89 |
-
border-radius: 10px !important;
|
| 90 |
-
margin-bottom: 8px !important;
|
| 91 |
-
text-align: left !important;
|
| 92 |
}
|
| 93 |
|
| 94 |
footer { display: none !important; }
|
|
@@ -106,7 +105,6 @@ def chat_fn(message, history, session_id, store):
|
|
| 106 |
|
| 107 |
api_messages = [{"role": "system", "content": "Bạn là NodeAI Genesis. Master: Trần Đình Phúc."}]
|
| 108 |
for msg in history: api_messages.append({"role": msg["role"], "content": msg["content"]})
|
| 109 |
-
|
| 110 |
api_messages.append({"role": "user", "content": user_text if user_text else "Gửi file"})
|
| 111 |
|
| 112 |
try:
|
|
@@ -137,23 +135,22 @@ with gr.Blocks(title="NodeAI Genesis") as demo:
|
|
| 137 |
chat_store = gr.State(load_db())
|
| 138 |
session_id = gr.State(str(uuid.uuid4()))
|
| 139 |
|
| 140 |
-
# Sidebar
|
| 141 |
with gr.Column(elem_classes="sidebar-node"):
|
| 142 |
gr.HTML("<div class='logo-text'>NODEAI</div>")
|
| 143 |
-
|
|
|
|
| 144 |
with gr.Column():
|
| 145 |
@gr.render(inputs=chat_store)
|
| 146 |
def render_history(store):
|
| 147 |
for sid in reversed(list(store.keys())):
|
| 148 |
-
btn = gr.Button(f"◈ {store[sid]['title']}",
|
| 149 |
btn.click(lambda s=sid: (store[s]["history"], s), None, [chatbot, session_id])
|
| 150 |
|
| 151 |
-
# Main area
|
| 152 |
with gr.Column(elem_classes="chat-main"):
|
| 153 |
-
|
|
|
|
| 154 |
audio_out = gr.Audio(autoplay=True, visible=False)
|
| 155 |
|
| 156 |
-
# Thanh nhập liệu (Bỏ Mic, Full chiều ngang)
|
| 157 |
with gr.Row(elem_classes="input-fixed-bottom"):
|
| 158 |
msg_input = gr.MultimodalTextbox(
|
| 159 |
show_label=False,
|
|
@@ -168,6 +165,5 @@ with gr.Blocks(title="NodeAI Genesis") as demo:
|
|
| 168 |
new_btn.click(lambda: ([], str(uuid.uuid4())), None, [chatbot, session_id])
|
| 169 |
|
| 170 |
if __name__ == "__main__":
|
| 171 |
-
#
|
| 172 |
-
# Khi chạy, Space sẽ tự động yêu cầu người dùng Login bằng tài khoản HF
|
| 173 |
demo.launch(auth=None, login_button=True, css=custom_css)
|
|
|
|
| 4 |
import uuid
|
| 5 |
import json
|
| 6 |
|
| 7 |
+
# Thư viện bổ trợ
|
| 8 |
try: from duckduckgo_search import DDGS
|
| 9 |
except: DDGS = None
|
| 10 |
try: from gtts import gTTS
|
| 11 |
except: gTTS = None
|
| 12 |
|
| 13 |
# 1. CẤU HÌNH & MODEL
|
|
|
|
| 14 |
HF_TOKEN = os.getenv("HUGGINGFACE_HUB_TOKEN")
|
| 15 |
client = InferenceClient(model="Qwen/Qwen2.5-7B-Instruct", token=HF_TOKEN)
|
| 16 |
DB_FILE = "nodeai_genesis_final.json"
|
|
|
|
| 26 |
with open(DB_FILE, "w", encoding="utf-8") as f:
|
| 27 |
json.dump(data, f, ensure_ascii=False, indent=4)
|
| 28 |
|
| 29 |
+
# 2. GUI DESIGN (Fix Layout & Orange Button)
|
| 30 |
custom_css = """
|
| 31 |
@import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@700&family=Plus+Jakarta+Sans:wght@400;600&display=swap');
|
| 32 |
|
|
|
|
| 54 |
font-size: 24px; text-align: center; margin-bottom: 30px;
|
| 55 |
}
|
| 56 |
|
| 57 |
+
/* Nút New Workspace Màu Cam */
|
| 58 |
+
.orange-btn {
|
| 59 |
+
background: linear-gradient(90deg, #ff7e5f, #feb47b) !important;
|
| 60 |
+
border: none !important;
|
| 61 |
+
color: white !important;
|
| 62 |
+
font-weight: bold !important;
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
/* Chat Area */
|
| 66 |
.chat-main {
|
| 67 |
margin-left: 260px !important;
|
|
|
|
| 74 |
background: transparent !important;
|
| 75 |
border: none !important;
|
| 76 |
height: 75vh !important;
|
| 77 |
+
margin-bottom: 110px !important;
|
| 78 |
}
|
| 79 |
|
| 80 |
+
/* Thanh nhập liệu cố định */
|
| 81 |
.input-fixed-bottom {
|
| 82 |
position: fixed !important;
|
| 83 |
bottom: 25px !important;
|
|
|
|
| 88 |
border-radius: 16px !important;
|
| 89 |
padding: 10px !important;
|
| 90 |
z-index: 2000 !important;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 91 |
}
|
| 92 |
|
| 93 |
footer { display: none !important; }
|
|
|
|
| 105 |
|
| 106 |
api_messages = [{"role": "system", "content": "Bạn là NodeAI Genesis. Master: Trần Đình Phúc."}]
|
| 107 |
for msg in history: api_messages.append({"role": msg["role"], "content": msg["content"]})
|
|
|
|
| 108 |
api_messages.append({"role": "user", "content": user_text if user_text else "Gửi file"})
|
| 109 |
|
| 110 |
try:
|
|
|
|
| 135 |
chat_store = gr.State(load_db())
|
| 136 |
session_id = gr.State(str(uuid.uuid4()))
|
| 137 |
|
|
|
|
| 138 |
with gr.Column(elem_classes="sidebar-node"):
|
| 139 |
gr.HTML("<div class='logo-text'>NODEAI</div>")
|
| 140 |
+
# Nút cam chuyên nghiệp
|
| 141 |
+
new_btn = gr.Button("+ NEW WORKSPACE", variant="primary", elem_classes="orange-btn")
|
| 142 |
with gr.Column():
|
| 143 |
@gr.render(inputs=chat_store)
|
| 144 |
def render_history(store):
|
| 145 |
for sid in reversed(list(store.keys())):
|
| 146 |
+
btn = gr.Button(f"◈ {store[sid]['title']}", variant="ghost")
|
| 147 |
btn.click(lambda s=sid: (store[s]["history"], s), None, [chatbot, session_id])
|
| 148 |
|
|
|
|
| 149 |
with gr.Column(elem_classes="chat-main"):
|
| 150 |
+
# Đã xóa bubble_full_width để fix lỗi
|
| 151 |
+
chatbot = gr.Chatbot(show_label=False)
|
| 152 |
audio_out = gr.Audio(autoplay=True, visible=False)
|
| 153 |
|
|
|
|
| 154 |
with gr.Row(elem_classes="input-fixed-bottom"):
|
| 155 |
msg_input = gr.MultimodalTextbox(
|
| 156 |
show_label=False,
|
|
|
|
| 165 |
new_btn.click(lambda: ([], str(uuid.uuid4())), None, [chatbot, session_id])
|
| 166 |
|
| 167 |
if __name__ == "__main__":
|
| 168 |
+
# Đăng nhập bằng Hugging Face (auth=None + login_button=True)
|
|
|
|
| 169 |
demo.launch(auth=None, login_button=True, css=custom_css)
|