lamgamepro1 commited on
Commit
c479e65
·
verified ·
1 Parent(s): 8b0e257

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +62 -82
app.py CHANGED
@@ -4,17 +4,17 @@ import os
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
14
- USER_ID, USER_PASS = "admin", "123456"
15
  HF_TOKEN = os.getenv("HUGGINGFACE_HUB_TOKEN")
16
  client = InferenceClient(model="Qwen/Qwen2.5-7B-Instruct", token=HF_TOKEN)
17
- DB_FILE = "nodeai_ultimate_memory.json"
18
 
19
  def load_db():
20
  if os.path.exists(DB_FILE):
@@ -27,107 +27,91 @@ 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 (FIX TOÀN DIỆN)
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
 
34
- /* Nền chủ đạo */
35
  .gradio-container {
36
- background: #050505 !important;
37
  font-family: 'Plus Jakarta Sans', sans-serif !important;
38
  }
39
 
40
- /* Sidebar Pro */
41
- .sidebar-pro {
42
  position: fixed !important;
43
  left: 0 !important; top: 0 !important;
44
  width: 260px !important; height: 100vh !important;
45
- background: #0a0a0f !important;
46
- border-right: 1px solid #1a1a20 !important;
47
  z-index: 1000 !important;
48
- padding: 20px !important;
49
  }
50
 
51
- .nodeai-logo {
52
  font-family: 'Orbitron', sans-serif !important;
53
- color: #00f2fe; font-size: 24px; text-align: center; margin-bottom: 30px;
 
 
 
54
  }
55
 
56
- /* Vùng Chat */
57
- .chat-col {
58
  margin-left: 260px !important;
59
  width: calc(100% - 260px) !important;
60
  height: 100vh !important;
61
- padding: 20px 40px !important;
62
  }
63
 
64
  .gr-chatbot {
65
  background: transparent !important;
66
  border: none !important;
67
- height: 70vh !important;
68
- margin-bottom: 120px !important;
69
  }
70
 
71
- /* KHÓA CHẶT THANH ĐIỀU KHIỂN Ở DƯỚI ĐÁY */
72
- .input-area-fixed {
73
  position: fixed !important;
74
- bottom: 30px !important;
75
- left: 300px !important;
76
- right: 40px !important;
 
 
 
 
77
  z-index: 2000 !important;
78
- display: flex !important;
79
- align-items: flex-end !important;
80
- gap: 10px !important;
81
  }
82
 
83
- /* Ô nhập liệu */
84
- .input-container {
85
- flex: 1 !important;
86
- background: #121217 !important;
87
- border: 1px solid #2a2a35 !important;
88
- border-radius: 15px !important;
89
- padding: 5px !important;
90
  }
91
 
92
- /* Mic gọn gàng */
93
- .mic-box {
94
- width: 60px !important;
95
- min-width: 60px !important;
96
- height: 60px !important;
97
- background: #121217 !important;
98
- border: 1px solid #2a2a35 !important;
99
- border-radius: 15px !important;
100
- overflow: hidden !important;
101
- display: flex !important;
102
- justify-content: center !important;
103
- align-items: center !important;
104
- }
105
-
106
- /* Ẩn bớt các nhãn thừa để tránh nhảy layout */
107
- .mic-box label, .mic-box .gr-block-label { display: none !important; }
108
-
109
  footer { display: none !important; }
110
  """
111
 
112
  # 3. CORE LOGIC
113
  def chat_fn(message, history, session_id, store):
114
- user_text = message.get("text", "") if isinstance(message, dict) else message
115
- files = message.get("files", []) if isinstance(message, dict) else []
116
 
117
  if not user_text and not files: return {"text": ""}, history, session_id, store, None
118
 
119
  if session_id not in store:
120
- store[session_id] = {"title": user_text[:20] if user_text else "New Workspace", "history": []}
121
 
122
  api_messages = [{"role": "system", "content": "Bạn là NodeAI Genesis. Master: Trần Đình Phúc."}]
123
  for msg in history: api_messages.append({"role": msg["role"], "content": msg["content"]})
124
 
125
- # Hỗ trợ g��i text hoặc file/audio
126
- api_messages.append({"role": "user", "content": user_text if user_text else "Phân tích nội dung này"})
127
 
128
  try:
129
  ans = ""
130
- new_h = history + [{"role": "user", "content": user_text if user_text else "📎 File/Audio"}]
131
  for token in client.chat_completion(messages=api_messages, max_tokens=2000, stream=True):
132
  if token.choices[0].delta.content:
133
  ans += token.choices[0].delta.content
@@ -154,40 +138,36 @@ with gr.Blocks(title="NodeAI Genesis") as demo:
154
  session_id = gr.State(str(uuid.uuid4()))
155
 
156
  # Sidebar
157
- with gr.Column(elem_classes="sidebar-pro"):
158
- gr.HTML("<div class='nodeai-logo'>NODEAI</div>")
159
- new_btn = gr.Button("+ NEW CHAT", variant="primary")
160
  with gr.Column():
161
  @gr.render(inputs=chat_store)
162
  def render_history(store):
163
  for sid in reversed(list(store.keys())):
164
- btn = gr.Button(f"💬 {store[sid]['title']}", variant="ghost")
165
  btn.click(lambda s=sid: (store[s]["history"], s), None, [chatbot, session_id])
166
 
167
- # Main Chat Area
168
- with gr.Column(elem_classes="chat-col"):
169
- chatbot = gr.Chatbot(show_label=False)
170
  audio_out = gr.Audio(autoplay=True, visible=False)
171
 
172
- # FIXED INPUT AREA (Chống nhảy layout)
173
- with gr.Row(elem_classes="input-area-fixed"):
174
- with gr.Column(elem_classes="input-container", scale=10):
175
- msg_input = gr.MultimodalTextbox(
176
- show_label=False,
177
- placeholder="Hỏi Phúc bất cứ điều gì...",
178
- container=False
179
- )
180
- with gr.Column(elem_classes="mic-box", scale=1):
181
- # Nút Mic thu nhỏ gọn gàng ở bên cạnh
182
- mic_btn = gr.Audio(sources=["microphone"], type="filepath", container=False)
183
-
184
- # Trình xử lý sự kiện
185
- msg_input.submit(chat_fn, [msg_input, chatbot, session_id, chat_store], [msg_input, chatbot, session_id, chat_store, audio_out]).then(tts_engine, audio_out, audio_out)
186
-
187
- def process_mic(path): return {"text": "Dịch âm thanh này", "files": [path]}
188
- mic_btn.stop_recording(process_mic, mic_btn, msg_input)
189
 
190
  new_btn.click(lambda: ([], str(uuid.uuid4())), None, [chatbot, session_id])
191
 
192
  if __name__ == "__main__":
193
- demo.launch(auth=(USER_ID, USER_PASS), css=custom_css)
 
 
 
4
  import uuid
5
  import json
6
 
7
+ # Thư viện hỗ 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
+ # 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"
18
 
19
  def load_db():
20
  if os.path.exists(DB_FILE):
 
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 (Sạch sẽ, Chuyên nghiệp)
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
 
 
34
  .gradio-container {
35
+ background: #08080c !important;
36
  font-family: 'Plus Jakarta Sans', sans-serif !important;
37
  }
38
 
39
+ /* Sidebar */
40
+ .sidebar-node {
41
  position: fixed !important;
42
  left: 0 !important; top: 0 !important;
43
  width: 260px !important; height: 100vh !important;
44
+ background: #0d0d12 !important;
45
+ border-right: 1px solid rgba(255, 255, 255, 0.05) !important;
46
  z-index: 1000 !important;
47
+ padding: 25px !important;
48
  }
49
 
50
+ .logo-text {
51
  font-family: 'Orbitron', sans-serif !important;
52
+ background: linear-gradient(90deg, #00f2fe, #4facfe);
53
+ -webkit-background-clip: text;
54
+ -webkit-text-fill-color: transparent;
55
+ font-size: 24px; text-align: center; margin-bottom: 30px;
56
  }
57
 
58
+ /* Chat Area */
59
+ .chat-main {
60
  margin-left: 260px !important;
61
  width: calc(100% - 260px) !important;
62
  height: 100vh !important;
63
+ padding: 20px 50px !important;
64
  }
65
 
66
  .gr-chatbot {
67
  background: transparent !important;
68
  border: none !important;
69
+ height: 75vh !important;
70
+ margin-bottom: 100px !important;
71
  }
72
 
73
+ /* Thanh nhập liệu cố định ở đáy */
74
+ .input-fixed-bottom {
75
  position: fixed !important;
76
+ bottom: 25px !important;
77
+ left: 285px !important;
78
+ right: 25px !important;
79
+ background: #16161e !important;
80
+ border: 1px solid rgba(0, 242, 254, 0.2) !important;
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; }
95
  """
96
 
97
  # 3. CORE LOGIC
98
  def chat_fn(message, history, session_id, store):
99
+ user_text = message.get("text", "")
100
+ files = message.get("files", [])
101
 
102
  if not user_text and not files: return {"text": ""}, history, session_id, store, None
103
 
104
  if session_id not in store:
105
+ store[session_id] = {"title": user_text[:20] if user_text else "Task AI", "history": []}
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:
113
  ans = ""
114
+ new_h = history + [{"role": "user", "content": user_text if user_text else "📎 File"}]
115
  for token in client.chat_completion(messages=api_messages, max_tokens=2000, stream=True):
116
  if token.choices[0].delta.content:
117
  ans += token.choices[0].delta.content
 
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
+ new_btn = gr.Button("+ NEW WORKSPACE", variant="primary")
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']}", elem_classes="hist-btn", variant="ghost")
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
+ chatbot = gr.Chatbot(show_label=False, bubble_full_width=False)
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,
160
+ placeholder="Message NodeAI Genesis...",
161
+ container=False
162
+ )
163
+
164
+ msg_input.submit(
165
+ chat_fn, [msg_input, chatbot, session_id, chat_store], [msg_input, chatbot, session_id, chat_store, audio_out]
166
+ ).then(tts_engine, audio_out, audio_out)
 
 
 
 
 
 
167
 
168
  new_btn.click(lambda: ([], str(uuid.uuid4())), None, [chatbot, session_id])
169
 
170
  if __name__ == "__main__":
171
+ # ĐĂNG NHẬP BẰNG HUGGING FACE
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)