lamgamepro1 commited on
Commit
b65decc
·
verified ·
1 Parent(s): 1065657

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +48 -40
app.py CHANGED
@@ -4,16 +4,16 @@ import os
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
  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"
17
 
18
  def load_db():
19
  if os.path.exists(DB_FILE):
@@ -26,16 +26,17 @@ def save_db(data):
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 Theme)
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
 
33
  .gradio-container {
34
  background: #08080c !important;
35
  font-family: 'Plus Jakarta Sans', sans-serif !important;
 
36
  }
37
 
38
- /* Sidebar */
39
  .sidebar-node {
40
  position: fixed !important;
41
  left: 0 !important; top: 0 !important;
@@ -51,44 +52,49 @@ custom_css = """
51
  background: linear-gradient(90deg, #00f2fe, #4facfe);
52
  -webkit-background-clip: text;
53
  -webkit-text-fill-color: transparent;
54
- font-size: 22px; text-align: center; margin-bottom: 20px;
55
  }
56
 
57
- /* Nút Cam Pro */
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
- margin-top: 10px !important;
64
  }
65
 
66
- /* Chat Area */
67
  .chat-main {
68
  margin-left: 260px !important;
69
  width: calc(100% - 260px) !important;
70
- height: 100vh !important;
71
- padding: 20px 40px !important;
 
72
  }
73
 
74
  .gr-chatbot {
75
  background: transparent !important;
76
  border: none !important;
77
  height: 75vh !important;
78
- margin-bottom: 100px !important;
79
  }
80
 
81
- /* Thanh nhập liệu cố định */
82
  .input-fixed-bottom {
83
  position: fixed !important;
84
- bottom: 25px !important;
85
- left: 285px !important;
86
- right: 25px !important;
87
  background: #16161e !important;
88
- border: 1px solid rgba(0, 242, 254, 0.2) !important;
89
- border-radius: 16px !important;
90
  padding: 5px 15px !important;
91
  z-index: 2000 !important;
 
 
 
 
 
 
 
 
92
  }
93
 
94
  footer { display: none !important; }
@@ -97,34 +103,36 @@ footer { display: none !important; }
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
- api_messages.append({"role": "user", "content": user_text if user_text else "Gửi file"})
110
 
111
  try:
112
  ans = ""
113
- new_h = history + [{"role": "user", "content": user_text if user_text else "📎 File"}]
114
  for token in client.chat_completion(messages=api_messages, max_tokens=2000, stream=True):
115
  if token.choices[0].delta.content:
116
  ans += token.choices[0].delta.content
117
- yield {"text": ""}, new_h + [{"role": "assistant", "content": ans}], session_id, store, None
 
118
 
119
  final_h = new_h + [{"role": "assistant", "content": ans}]
120
  store[session_id]["history"] = final_h
121
  save_db(store)
 
122
  yield {"text": ""}, final_h, session_id, store, ans
123
  except Exception as e:
124
- yield {"text": ""}, history + [{"role": "assistant", "content": f"Lỗi: {str(e)}"}], session_id, store, None
125
 
126
  def tts_engine(text):
127
- if not text or not gTTS: return None
128
  try:
129
  tts = gTTS(text=text[:300], lang='vi')
130
  tts.save("voice.mp3")
@@ -135,14 +143,11 @@ def tts_engine(text):
135
  with gr.Blocks(title="NodeAI Genesis") as demo:
136
  chat_store = gr.State(load_db())
137
  session_id = gr.State(str(uuid.uuid4()))
 
138
 
139
- # Sidebar
140
  with gr.Column(elem_classes="sidebar-node"):
141
  gr.HTML("<div class='logo-text'>NODEAI GENESIS</div>")
142
-
143
- # ĐĂNG NHẬP CHÍNH CHỦ HUGGING FACE
144
- gr.LoginButton(value="Đăng nhập HF")
145
-
146
  new_btn = gr.Button("+ NEW WORKSPACE", variant="primary", elem_classes="orange-btn")
147
 
148
  with gr.Column():
@@ -152,7 +157,6 @@ with gr.Blocks(title="NodeAI Genesis") as demo:
152
  btn = gr.Button(f"◈ {store[sid]['title']}", variant="ghost")
153
  btn.click(lambda s=sid: (store[s]["history"], s), None, [chatbot, session_id])
154
 
155
- # Main area
156
  with gr.Column(elem_classes="chat-main"):
157
  chatbot = gr.Chatbot(show_label=False)
158
  audio_out = gr.Audio(autoplay=True, visible=False)
@@ -160,16 +164,20 @@ with gr.Blocks(title="NodeAI Genesis") as demo:
160
  with gr.Row(elem_classes="input-fixed-bottom"):
161
  msg_input = gr.MultimodalTextbox(
162
  show_label=False,
163
- placeholder="Hỏi NodeAI bất cứ điều gì...",
164
  container=False
165
  )
166
 
 
167
  msg_input.submit(
168
- chat_fn, [msg_input, chatbot, session_id, chat_store], [msg_input, chatbot, session_id, chat_store, audio_out]
169
- ).then(tts_engine, audio_out, audio_out)
 
 
 
 
170
 
171
  new_btn.click(lambda: ([], str(uuid.uuid4())), None, [chatbot, session_id])
172
 
173
  if __name__ == "__main__":
174
- # Đã xóa login_button ở đây vì đã dùng gr.LoginButton() ở trên
175
  demo.launch(css=custom_css)
 
4
  import uuid
5
  import json
6
 
7
+ # Import an toà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
14
  HF_TOKEN = os.getenv("HUGGINGFACE_HUB_TOKEN")
15
  client = InferenceClient(model="Qwen/Qwen2.5-7B-Instruct", token=HF_TOKEN)
16
+ DB_FILE = "nodeai_platinum_v31.json"
17
 
18
  def load_db():
19
  if os.path.exists(DB_FILE):
 
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 TRÀN MÀN HÌNH)
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
 
33
  .gradio-container {
34
  background: #08080c !important;
35
  font-family: 'Plus Jakarta Sans', sans-serif !important;
36
+ overflow-x: hidden !important;
37
  }
38
 
39
+ /* Sidebar linh hoạt */
40
  .sidebar-node {
41
  position: fixed !important;
42
  left: 0 !important; top: 0 !important;
 
52
  background: linear-gradient(90deg, #00f2fe, #4facfe);
53
  -webkit-background-clip: text;
54
  -webkit-text-fill-color: transparent;
55
+ font-size: 20px; text-align: center; margin-bottom: 20px;
56
  }
57
 
 
58
  .orange-btn {
59
  background: linear-gradient(90deg, #ff7e5f, #feb47b) !important;
60
+ border: none !important; color: white !important; font-weight: bold !important;
 
 
 
61
  }
62
 
63
+ /* Chat Area - Sửa lỗi tràn màn hình */
64
  .chat-main {
65
  margin-left: 260px !important;
66
  width: calc(100% - 260px) !important;
67
+ min-height: 100vh !important;
68
+ padding: 10px 20px !important;
69
+ box-sizing: border-box !important;
70
  }
71
 
72
  .gr-chatbot {
73
  background: transparent !important;
74
  border: none !important;
75
  height: 75vh !important;
76
+ margin-bottom: 120px !important;
77
  }
78
 
79
+ /* Thanh nhập liệu - Tự động co giãn theo màn hình */
80
  .input-fixed-bottom {
81
  position: fixed !important;
82
+ bottom: 20px !important;
83
+ left: 280px !important; /* Cách sidebar */
84
+ right: 20px !important; /* Cách lề phải */
85
  background: #16161e !important;
86
+ border: 1px solid rgba(0, 242, 254, 0.3) !important;
87
+ border-radius: 15px !important;
88
  padding: 5px 15px !important;
89
  z-index: 2000 !important;
90
+ box-sizing: border-box !important;
91
+ }
92
+
93
+ /* Responsive cho điện thoại */
94
+ @media screen and (max-width: 768px) {
95
+ .sidebar-node { display: none !important; }
96
+ .chat-main { margin-left: 0 !important; width: 100% !important; }
97
+ .input-fixed-bottom { left: 15px !important; right: 15px !important; }
98
  }
99
 
100
  footer { display: none !important; }
 
103
  # 3. CORE LOGIC
104
  def chat_fn(message, history, session_id, store):
105
  user_text = message.get("text", "")
106
+ if not user_text and not message.get("files", []):
107
+ yield {"text": ""}, history, session_id, store, ""
108
+ return
109
 
110
  if session_id not in store:
111
+ store[session_id] = {"title": user_text[:20] if user_text else "New Workspace", "history": []}
112
 
113
  api_messages = [{"role": "system", "content": "Bạn là NodeAI Genesis. Master: Trần Đình Phúc."}]
114
  for msg in history: api_messages.append({"role": msg["role"], "content": msg["content"]})
115
+ api_messages.append({"role": "user", "content": user_text})
116
 
117
  try:
118
  ans = ""
119
+ new_h = history + [{"role": "user", "content": user_text}]
120
  for token in client.chat_completion(messages=api_messages, max_tokens=2000, stream=True):
121
  if token.choices[0].delta.content:
122
  ans += token.choices[0].delta.content
123
+ # Chỉ gửi text về chatbot, không gửi về audio_out ở đây
124
+ yield {"text": ""}, new_h + [{"role": "assistant", "content": ans}], session_id, store, ""
125
 
126
  final_h = new_h + [{"role": "assistant", "content": ans}]
127
  store[session_id]["history"] = final_h
128
  save_db(store)
129
+ # Khi xong hẳn, gửi văn bản cuối cùng vào tts_buffer (một Textbox ẩn)
130
  yield {"text": ""}, final_h, session_id, store, ans
131
  except Exception as e:
132
+ yield {"text": ""}, history + [{"role": "assistant", "content": str(e)}], session_id, store, ""
133
 
134
  def tts_engine(text):
135
+ if not text or len(text) < 2 or not gTTS: return None
136
  try:
137
  tts = gTTS(text=text[:300], lang='vi')
138
  tts.save("voice.mp3")
 
143
  with gr.Blocks(title="NodeAI Genesis") as demo:
144
  chat_store = gr.State(load_db())
145
  session_id = gr.State(str(uuid.uuid4()))
146
+ tts_buffer = gr.Textbox(visible=False) # Dùng làm trung gian để fix lỗi audio
147
 
 
148
  with gr.Column(elem_classes="sidebar-node"):
149
  gr.HTML("<div class='logo-text'>NODEAI GENESIS</div>")
150
+ gr.LoginButton(value="Đăng nhập")
 
 
 
151
  new_btn = gr.Button("+ NEW WORKSPACE", variant="primary", elem_classes="orange-btn")
152
 
153
  with gr.Column():
 
157
  btn = gr.Button(f"◈ {store[sid]['title']}", variant="ghost")
158
  btn.click(lambda s=sid: (store[s]["history"], s), None, [chatbot, session_id])
159
 
 
160
  with gr.Column(elem_classes="chat-main"):
161
  chatbot = gr.Chatbot(show_label=False)
162
  audio_out = gr.Audio(autoplay=True, visible=False)
 
164
  with gr.Row(elem_classes="input-fixed-bottom"):
165
  msg_input = gr.MultimodalTextbox(
166
  show_label=False,
167
+ placeholder="Hỏi Master Phúc bất cứ điều gì...",
168
  container=False
169
  )
170
 
171
+ # LUỒNG XỬ LÝ (QUAN TRỌNG ĐỂ FIX LỖI)
172
  msg_input.submit(
173
+ chat_fn,
174
+ [msg_input, chatbot, session_id, chat_store],
175
+ [msg_input, chatbot, session_id, chat_store, tts_buffer] # Trả kết quả TTS vào buffer
176
+ ).then(
177
+ tts_engine, tts_buffer, audio_out # TTS chỉ đọc từ buffer, không đọc từ Chatbot
178
+ )
179
 
180
  new_btn.click(lambda: ([], str(uuid.uuid4())), None, [chatbot, session_id])
181
 
182
  if __name__ == "__main__":
 
183
  demo.launch(css=custom_css)