lamgamepro1 commited on
Commit
548b447
·
verified ·
1 Parent(s): f5d5e96

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +55 -57
app.py CHANGED
@@ -5,21 +5,16 @@ import uuid
5
  import json
6
 
7
  # Import thư viện hỗ trợ
8
- try:
9
- from duckduckgo_search import DDGS
10
- except ImportError:
11
- DDGS = None
12
 
13
- try:
14
- from gtts import gTTS
15
- except ImportError:
16
- gTTS = None
17
-
18
- # 1. CẤU HÌNH HỆ THỐNG
19
  USER_ID, USER_PASS = "admin", "123456"
20
  HF_TOKEN = os.getenv("HUGGINGFACE_HUB_TOKEN")
21
  client = InferenceClient(model="Qwen/Qwen2.5-7B-Instruct", token=HF_TOKEN)
22
- DB_FILE = "nodeai_platinum_memory.json"
23
 
24
  def load_db():
25
  if os.path.exists(DB_FILE):
@@ -32,15 +27,16 @@ def save_db(data):
32
  with open(DB_FILE, "w", encoding="utf-8") as f:
33
  json.dump(data, f, ensure_ascii=False, indent=4)
34
 
35
- # 2. GUI DESIGN (PLATINUM CYBERPUNK)
36
  custom_css = """
37
- @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&family=Plus+Jakarta+Sans:wght@300;400;600&display=swap');
38
 
39
  .gradio-container {
40
  background: radial-gradient(circle at top right, #0d0d1a, #050505) !important;
41
  font-family: 'Plus Jakarta Sans', sans-serif !important;
42
  }
43
 
 
44
  .sidebar-pro {
45
  position: fixed !important;
46
  left: 10px !important; top: 10px !important;
@@ -49,7 +45,7 @@ custom_css = """
49
  backdrop-filter: blur(20px) !important;
50
  border: 1px solid rgba(0, 242, 254, 0.2) !important;
51
  border-radius: 20px !important;
52
- z-index: 999 !important;
53
  padding: 20px !important;
54
  }
55
 
@@ -59,36 +55,45 @@ custom_css = """
59
  -webkit-background-clip: text;
60
  -webkit-text-fill-color: transparent;
61
  font-size: 26px !important;
62
- font-weight: 800 !important;
63
- text-align: center;
64
- margin-bottom: 25px;
65
  }
66
 
 
67
  .chat-col {
68
- margin-left: 310px !important;
69
- width: calc(100% - 330px) !important;
70
  height: 100vh !important;
 
71
  }
72
 
73
- .gr-chatbot { background: transparent !important; border: none !important; }
 
 
 
 
74
 
75
- /* Control Panel cho Input */
76
- .control-panel {
77
- background: rgba(255, 255, 255, 0.03) !important;
78
- border: 1px solid rgba(255, 255, 255, 0.1) !important;
 
 
 
 
 
79
  border-radius: 25px !important;
80
- padding: 10px !important;
81
- margin-bottom: 20px !important;
 
 
 
 
82
  }
83
 
84
- .hist-btn {
85
- background: rgba(255, 255, 255, 0.03) !important;
86
- border: 1px solid rgba(0, 242, 254, 0.1) !important;
87
- border-radius: 12px !important;
88
- margin-bottom: 8px !important;
89
- transition: 0.3s;
90
- }
91
- .hist-btn:hover { border-color: #00f2fe !important; background: rgba(0, 242, 254, 0.1) !important; }
92
 
93
  footer { display: none !important; }
94
  """
@@ -109,14 +114,12 @@ def chat_fn(message, history, session_id, store):
109
  if not user_text and not files: return {"text": ""}, history, session_id, store, None
110
 
111
  if session_id not in store:
112
- store[session_id] = {"title": user_text[:20] if user_text else "Nova Task", "history": []}
113
 
114
  web_info = search_web(user_text) if any(x in user_text.lower() for x in ["tìm", "tra", "web", "giá"]) else ""
115
 
116
- api_messages = [{"role": "system", "content": f"Bạn là NodeAI Platinum. Master: Trần Đình Phúc. Web Context: {web_info}"}]
117
- for msg in history:
118
- api_messages.append({"role": msg["role"], "content": msg["content"]})
119
-
120
  api_messages.append({"role": "user", "content": user_text})
121
 
122
  try:
@@ -132,7 +135,7 @@ def chat_fn(message, history, session_id, store):
132
  save_db(store)
133
  yield {"text": ""}, final_h, session_id, store, ans
134
  except Exception as e:
135
- yield {"text": ""}, history + [{"role": "assistant", "content": f"Neural Error: {str(e)}"}], session_id, store, None
136
 
137
  def tts_engine(text):
138
  if not text or not gTTS: return None
@@ -143,7 +146,7 @@ def tts_engine(text):
143
  except: return None
144
 
145
  # 4. INTERFACE
146
- with gr.Blocks(title="NodeAI Platinum") as demo:
147
  chat_store = gr.State(load_db())
148
  session_id = gr.State(str(uuid.uuid4()))
149
 
@@ -152,38 +155,33 @@ with gr.Blocks(title="NodeAI Platinum") as demo:
152
  with gr.Column(elem_classes="sidebar-pro"):
153
  gr.HTML("<div class='nodeai-logo'>NODEAI</div>")
154
  new_btn = gr.Button("+ NEW WORKSPACE", variant="primary")
155
- with gr.Column(elem_id="history-container"):
156
  @gr.render(inputs=chat_store)
157
  def render_history(store):
158
  for sid in reversed(list(store.keys())):
159
- btn = gr.Button(f"◈ {store[sid]['title']}", elem_classes="hist-btn")
160
  btn.click(lambda s=sid: (store[s]["history"], s), None, [chatbot, session_id])
161
 
162
  # MAIN CONTENT
163
  with gr.Column(elem_classes="chat-col"):
164
- chatbot = gr.Chatbot(show_label=False, height="72vh")
165
  audio_out = gr.Audio(autoplay=True, visible=False)
166
 
167
- with gr.Row(elem_classes="control-panel"):
 
168
  with gr.Column(scale=9):
169
  msg_input = gr.MultimodalTextbox(
170
- show_label=False, placeholder="Command NodeAI Genesis...", container=False
171
  )
172
- with gr.Column(scale=1, min_width=60):
173
- # Mic rời cực kỳ nhạy để trình duyệt nhận diện quyền
174
  mic_btn = gr.Audio(sources=["microphone"], type="filepath", label="Mic", show_label=False)
175
 
176
- gr.HTML("<p style='text-align:center; color:rgba(0, 242, 254, 0.2); font-size:11px;'>PLATINUM V30.5 • POWERED BY TRẦN ĐÌNH PHÚ</p>")
177
 
178
- # Xử lý nhập liệu
179
- msg_input.submit(
180
- chat_fn, [msg_input, chatbot, session_id, chat_store], [msg_input, chatbot, session_id, chat_store, audio_out]
181
- ).then(tts_engine, audio_out, audio_out)
182
-
183
- # Xử lý từ Mic (Khi thu âm xong tự động gửi)
184
- def process_mic(path):
185
- return {"text": "Dịch nội dung từ file âm thanh này và trả lời", "files": [path]}
186
 
 
187
  mic_btn.stop_recording(process_mic, mic_btn, msg_input)
188
 
189
  new_btn.click(lambda: ([], str(uuid.uuid4())), None, [chatbot, session_id])
 
5
  import json
6
 
7
  # Import 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
 
 
 
 
 
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_fix_memory.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 (FIXED LAYOUT - CHỐNG DỊCH CHUYỂ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
  .gradio-container {
35
  background: radial-gradient(circle at top right, #0d0d1a, #050505) !important;
36
  font-family: 'Plus Jakarta Sans', sans-serif !important;
37
  }
38
 
39
+ /* Sidebar giữ nguyên */
40
  .sidebar-pro {
41
  position: fixed !important;
42
  left: 10px !important; top: 10px !important;
 
45
  backdrop-filter: blur(20px) !important;
46
  border: 1px solid rgba(0, 242, 254, 0.2) !important;
47
  border-radius: 20px !important;
48
+ z-index: 1000 !important;
49
  padding: 20px !important;
50
  }
51
 
 
55
  -webkit-background-clip: text;
56
  -webkit-text-fill-color: transparent;
57
  font-size: 26px !important;
58
+ text-align: center; margin-bottom: 25px;
 
 
59
  }
60
 
61
+ /* Khu vực Chat - Không cho phép tràn ngang */
62
  .chat-col {
63
+ margin-left: 300px !important;
64
+ width: calc(100% - 320px) !important;
65
  height: 100vh !important;
66
+ position: relative !important;
67
  }
68
 
69
+ .gr-chatbot {
70
+ background: transparent !important;
71
+ border: none !important;
72
+ margin-bottom: 120px !important; /* Tạo khoảng trống cho input */
73
+ }
74
 
75
+ /* KHÓA CHẶT THANH NHẬP LIỆU Ở DƯỚI ĐÁY */
76
+ .control-panel-fixed {
77
+ position: fixed !important;
78
+ bottom: 20px !important;
79
+ left: 310px !important;
80
+ right: 20px !important;
81
+ background: rgba(20, 20, 30, 0.8) !important;
82
+ backdrop-filter: blur(10px) !important;
83
+ border: 1px solid rgba(0, 242, 254, 0.3) !important;
84
  border-radius: 25px !important;
85
+ padding: 10px 20px !important;
86
+ z-index: 9999 !important;
87
+ display: flex !important;
88
+ flex-direction: row !important;
89
+ align-items: center !important;
90
+ gap: 15px !important;
91
  }
92
 
93
+ .input-box { flex: 1 !important; border: none !important; background: transparent !important; }
94
+
95
+ /* Ẩn bớt giao diện thừa của Audio để không chiếm chỗ */
96
+ .mic-small audio { height: 35px !important; width: 100% !important; }
 
 
 
 
97
 
98
  footer { display: none !important; }
99
  """
 
114
  if not user_text and not files: return {"text": ""}, history, session_id, store, None
115
 
116
  if session_id not in store:
117
+ store[session_id] = {"title": user_text[:20] if user_text else "New Chat", "history": []}
118
 
119
  web_info = search_web(user_text) if any(x in user_text.lower() for x in ["tìm", "tra", "web", "giá"]) else ""
120
 
121
+ api_messages = [{"role": "system", "content": f"Bạn là NodeAI Genesis. Master: Trần Đình Phúc. Web: {web_info}"}]
122
+ for msg in history: api_messages.append({"role": msg["role"], "content": msg["content"]})
 
 
123
  api_messages.append({"role": "user", "content": user_text})
124
 
125
  try:
 
135
  save_db(store)
136
  yield {"text": ""}, final_h, session_id, store, ans
137
  except Exception as e:
138
+ yield {"text": ""}, history + [{"role": "assistant", "content": str(e)}], session_id, store, None
139
 
140
  def tts_engine(text):
141
  if not text or not gTTS: return None
 
146
  except: return None
147
 
148
  # 4. INTERFACE
149
+ with gr.Blocks(title="NodeAI Genesis") as demo:
150
  chat_store = gr.State(load_db())
151
  session_id = gr.State(str(uuid.uuid4()))
152
 
 
155
  with gr.Column(elem_classes="sidebar-pro"):
156
  gr.HTML("<div class='nodeai-logo'>NODEAI</div>")
157
  new_btn = gr.Button("+ NEW WORKSPACE", variant="primary")
158
+ with gr.Column():
159
  @gr.render(inputs=chat_store)
160
  def render_history(store):
161
  for sid in reversed(list(store.keys())):
162
+ btn = gr.Button(f"◈ {store[sid]['title']}", variant="ghost")
163
  btn.click(lambda s=sid: (store[s]["history"], s), None, [chatbot, session_id])
164
 
165
  # MAIN CONTENT
166
  with gr.Column(elem_classes="chat-col"):
167
+ chatbot = gr.Chatbot(show_label=False, height="78vh")
168
  audio_out = gr.Audio(autoplay=True, visible=False)
169
 
170
+ # THANH NHẬP LIỆU CỐ ĐỊNH (FIXED)
171
+ with gr.Row(elem_classes="control-panel-fixed"):
172
  with gr.Column(scale=9):
173
  msg_input = gr.MultimodalTextbox(
174
+ show_label=False, placeholder="Nhập lệnh tại đây...", container=False, elem_classes="input-box"
175
  )
176
+ with gr.Column(scale=2, min_width=100, elem_classes="mic-small"):
 
177
  mic_btn = gr.Audio(sources=["microphone"], type="filepath", label="Mic", show_label=False)
178
 
179
+ gr.HTML("<p style='text-align:center; color:rgba(0, 242, 254, 0.1); font-size:10px;'>NODEAI GENESIS V30.6 • BY PHÚC</p>")
180
 
181
+ # Logic liên kết
182
+ 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)
 
 
 
 
 
 
183
 
184
+ def process_mic(path): return {"text": "Phân tích âm thanh này", "files": [path]}
185
  mic_btn.stop_recording(process_mic, mic_btn, msg_input)
186
 
187
  new_btn.click(lambda: ([], str(uuid.uuid4())), None, [chatbot, session_id])