lamgamepro1 commited on
Commit
f5d5e96
·
verified ·
1 Parent(s): 5417d5b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +58 -57
app.py CHANGED
@@ -4,7 +4,7 @@ import os
4
  import uuid
5
  import json
6
 
7
- # Import an toàn
8
  try:
9
  from duckduckgo_search import DDGS
10
  except ImportError:
@@ -15,12 +15,11 @@ try:
15
  except ImportError:
16
  gTTS = None
17
 
18
- # 1. CẤU HÌNH (Đổi sang model ổn định nhất)
19
  USER_ID, USER_PASS = "admin", "123456"
20
  HF_TOKEN = os.getenv("HUGGINGFACE_HUB_TOKEN")
21
- # Sử dụng model Qwen2.5-7B-Instruct để đảm bảo chạy 100% trên mọi Server
22
  client = InferenceClient(model="Qwen/Qwen2.5-7B-Instruct", token=HF_TOKEN)
23
- DB_FILE = "nodeai_genesis_memory.json"
24
 
25
  def load_db():
26
  if os.path.exists(DB_FILE):
@@ -33,12 +32,12 @@ def save_db(data):
33
  with open(DB_FILE, "w", encoding="utf-8") as f:
34
  json.dump(data, f, ensure_ascii=False, indent=4)
35
 
36
- # 2. GUI DESIGN (Cyberpunk Neon)
37
  custom_css = """
38
  @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700&family=Plus+Jakarta+Sans:wght@300;400;600&display=swap');
39
 
40
  .gradio-container {
41
- background: radial-gradient(circle at top right, #1a1a2e, #0f0f1a, #050505) !important;
42
  font-family: 'Plus Jakarta Sans', sans-serif !important;
43
  }
44
 
@@ -46,52 +45,55 @@ custom_css = """
46
  position: fixed !important;
47
  left: 10px !important; top: 10px !important;
48
  width: 280px !important; height: calc(100vh - 20px) !important;
49
- background: rgba(15, 15, 26, 0.8) !important;
50
- backdrop-filter: blur(15px) !important;
51
- border: 1px solid rgba(255, 255, 255, 0.1) !important;
52
  border-radius: 20px !important;
53
  z-index: 999 !important;
54
- padding: 25px !important;
55
- overflow-y: auto !important;
56
  }
57
 
58
  .nodeai-logo {
59
  font-family: 'Orbitron', sans-serif !important;
60
- background: linear-gradient(90deg, #00f2fe, #4facfe);
61
  -webkit-background-clip: text;
62
  -webkit-text-fill-color: transparent;
63
- font-size: 28px !important;
64
  font-weight: 800 !important;
65
  text-align: center;
66
- margin-bottom: 20px;
67
  }
68
 
69
  .chat-col {
70
  margin-left: 310px !important;
71
  width: calc(100% - 330px) !important;
72
  height: 100vh !important;
73
- padding: 20px !important;
74
  }
75
 
76
  .gr-chatbot { background: transparent !important; border: none !important; }
77
 
78
- /* Làm đẹp khu vực nhập liệu và Mic */
79
- .input-row {
80
- display: flex !important;
81
- gap: 10px !important;
82
- align-items: center !important;
83
  background: rgba(255, 255, 255, 0.03) !important;
84
  border: 1px solid rgba(255, 255, 255, 0.1) !important;
85
- border-radius: 30px !important;
86
- padding: 5px 15px !important;
 
87
  }
88
 
89
- .input-box { flex: 1 !important; border: none !important; background: transparent !important; }
 
 
 
 
 
 
 
90
 
91
  footer { display: none !important; }
92
  """
93
 
94
- # 3. LOGIC XỬ LÝ
95
  def search_web(query):
96
  if not DDGS: return ""
97
  try:
@@ -101,22 +103,17 @@ def search_web(query):
101
  except: return ""
102
 
103
  def chat_fn(message, history, session_id, store):
104
- # Xử lý nếu message là text hoặc từ microphone
105
- user_text = ""
106
- files = []
107
-
108
- if isinstance(message, dict):
109
- user_text = message.get("text", "")
110
- files = message.get("files", [])
111
 
112
  if not user_text and not files: return {"text": ""}, history, session_id, store, None
113
 
114
  if session_id not in store:
115
- store[session_id] = {"title": user_text[:20] if user_text else "New Chat", "history": []}
116
 
117
- web_data = search_web(user_text) if any(x in user_text.lower() for x in ["tìm", "tra", "web", "giá"]) else ""
118
 
119
- api_messages = [{"role": "system", "content": f"Bạn là NodeAI Genesis. Master: Trần Đình Phúc. Web: {web_data}"}]
120
  for msg in history:
121
  api_messages.append({"role": msg["role"], "content": msg["content"]})
122
 
@@ -130,12 +127,12 @@ def chat_fn(message, history, session_id, store):
130
  ans += token.choices[0].delta.content
131
  yield {"text": ""}, new_h + [{"role": "assistant", "content": ans}], session_id, store, None
132
 
133
- final_history = new_h + [{"role": "assistant", "content": ans}]
134
- store[session_id]["history"] = final_history
135
  save_db(store)
136
- yield {"text": ""}, final_history, session_id, store, ans
137
  except Exception as e:
138
- yield {"text": ""}, history + [{"role": "assistant", "content": f"Lỗi: {str(e)}"}], session_id, store, None
139
 
140
  def tts_engine(text):
141
  if not text or not gTTS: return None
@@ -146,7 +143,7 @@ def tts_engine(text):
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
 
@@ -159,32 +156,36 @@ with gr.Blocks(title="NodeAI Genesis") as demo:
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 CHAT
166
  with gr.Column(elem_classes="chat-col"):
167
- chatbot = gr.Chatbot(show_label=False, height="75vh")
168
  audio_out = gr.Audio(autoplay=True, visible=False)
169
 
170
- # Khu vực nhập liệu có Mic
171
- with gr.Row(elem_classes="input-row"):
172
- msg_input = gr.MultimodalTextbox(
173
- show_label=False,
174
- placeholder="Command NodeAI hoặc dùng Mic...",
175
- container=False,
176
- elem_classes="input-box",
177
- sources=["upload", "microphone"] # Kích hoạt nút Mic
178
- )
179
-
180
- gr.HTML("<p style='text-align:center; color:rgba(255,255,255,0.1); font-size:11px; margin-top:10px;'>GENESIS V30.3 • BY TRẦN ĐÌNH PHÚ</p>")
181
-
182
  msg_input.submit(
183
- chat_fn,
184
- [msg_input, chatbot, session_id, chat_store],
185
- [msg_input, chatbot, session_id, chat_store, audio_out]
186
  ).then(tts_engine, audio_out, audio_out)
187
 
 
 
 
 
 
 
188
  new_btn.click(lambda: ([], str(uuid.uuid4())), None, [chatbot, session_id])
189
 
190
  if __name__ == "__main__":
 
4
  import uuid
5
  import json
6
 
7
+ # Import thư viện hỗ trợ
8
  try:
9
  from duckduckgo_search import DDGS
10
  except ImportError:
 
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
  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
 
 
45
  position: fixed !important;
46
  left: 10px !important; top: 10px !important;
47
  width: 280px !important; height: calc(100vh - 20px) !important;
48
+ background: rgba(10, 10, 15, 0.9) !important;
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
 
56
  .nodeai-logo {
57
  font-family: 'Orbitron', sans-serif !important;
58
+ background: linear-gradient(90deg, #00f2fe, #7ef2ff);
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
  """
95
 
96
+ # 3. CORE LOGIC
97
  def search_web(query):
98
  if not DDGS: return ""
99
  try:
 
103
  except: return ""
104
 
105
  def chat_fn(message, history, session_id, store):
106
+ user_text = message.get("text", "") if isinstance(message, dict) else message
107
+ files = message.get("files", []) if isinstance(message, dict) else []
 
 
 
 
 
108
 
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
 
 
127
  ans += token.choices[0].delta.content
128
  yield {"text": ""}, new_h + [{"role": "assistant", "content": ans}], session_id, store, None
129
 
130
+ final_h = new_h + [{"role": "assistant", "content": ans}]
131
+ store[session_id]["history"] = final_h
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
  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
 
 
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])
190
 
191
  if __name__ == "__main__":