lamgamepro1 commited on
Commit
62f7f55
·
verified ·
1 Parent(s): 4fdb2af

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +80 -66
app.py CHANGED
@@ -3,45 +3,54 @@ from huggingface_hub import InferenceClient
3
  from supabase import create_client, Client
4
  import os
5
  import uuid
6
- import json
7
- import base64
8
 
9
- # 1. CẤU HÌNH CORE (Lấy từ Secrets của Hugging Face)
10
  URL = os.environ.get("SUPABASE_URL")
11
  KEY = os.environ.get("SUPABASE_KEY")
12
  HF_TOKEN = os.environ.get("HUGGINGFACE_HUB_TOKEN")
13
 
14
- # Khởi tạo siêu máy chủ
15
- supabase: Client = create_client(URL, KEY)
 
 
 
 
 
 
 
16
  client = InferenceClient(model="Qwen/Qwen2.5-7B-Instruct", token=HF_TOKEN)
17
 
18
- # 2. HÀM XỬ LÝ DATABASE (Supabase Vĩnh Cửu)
19
- def get_user_history(username):
 
20
  try:
21
- res = supabase.table("chats").select("*").eq("username", username).order("created_at", desc=True).execute()
22
  return res.data
23
- except: return []
 
 
24
 
25
- def save_to_db(username, session_id, title, history):
 
26
  try:
27
- data = {"username": username, "session_id": session_id, "title": title, "history": history}
28
  supabase.table("chats").upsert(data, on_conflict="session_id").execute()
29
- except Exception as e: print(f"DB Error: {e}")
 
30
 
31
- # 3. GIAO DIỆN SIÊU CẤP (GLASSMORPHISM PRO)
32
  custom_css = """
33
  @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@700&family=Plus+Jakarta+Sans:wght@400;600&display=swap');
34
  :root { --primary: #38bdf8; --accent: #f97316; }
35
- .gradio-container { background: radial-gradient(circle at 50% 0%, #0f172a 0%, #020617 100%) !important; color: #e2e8f0 !important; }
36
- .sidebar-node { background: rgba(15, 23, 42, 0.7) !important; backdrop-filter: blur(20px) !important; border-right: 1px solid rgba(56, 189, 248, 0.2) !important; height: 100vh !important; }
37
- .logo-area { font-family: 'Orbitron', sans-serif; background: linear-gradient(90deg, var(--primary), #818cf8); -webkit-background-clip: text; -webkit-text-fill-color: transparent; text-align: center; padding: 20px 0; }
38
- .chat-bubble { border-radius: 15px !important; border: 1px solid rgba(255,255,255,0.1) !important; }
39
- .input-area { background: rgba(30, 41, 59, 0.9) !important; border: 1px solid var(--primary) !important; border-radius: 20px !important; box-shadow: 0 0 20px rgba(56, 189, 248, 0.2) !important; }
40
- .orange-btn { background: linear-gradient(135deg, #f97316 0%, #fb923c 100%) !important; color: white !important; font-weight: bold !important; border: none !important; }
41
  footer { display: none !important; }
42
  """
43
 
44
- # 4. LOGIC XỬ LÝ ĐA PHƯƠNG TIỆN (Multimodal)
45
  def process_content(message):
46
  text = message.get("text", "")
47
  files = message.get("files", [])
@@ -52,92 +61,97 @@ def process_content(message):
52
  if f.lower().endswith(('.lua', '.py', '.txt', '.js', '.html', '.css')):
53
  try:
54
  with open(f, "r", encoding="utf-8") as file:
55
- combined_prompt += f"\n\n[FILE: {name}]\n{file.read()}"
56
  except: pass
57
  elif f.lower().endswith(('.png', '.jpg', '.jpeg')):
58
- combined_prompt += f"\n\n[ Master đã gửi 1 ảnh: {name} ]"
59
  return combined_prompt
60
 
61
- def chat_engine(message, history, session_id, profile: gr.OAuthProfile | None):
62
- username = profile.username if profile else "Master_Phuc"
63
  full_prompt = process_content(message)
 
 
 
 
 
 
64
 
65
- if not full_prompt.strip(): yield "", history, session_id, "" ; return
 
 
 
 
66
 
67
- # Build Prompt
68
- messages = [{"role": "system", "content": f"Bạn là NodeAI Genesis. Master: {username}. Bạn là chuyên gia Roblox và Web. Hãy phân tích kỹ code Master gửi."}]
69
- for msg in history: messages.append({"role": msg["role"], "content": msg["content"]})
70
  messages.append({"role": "user", "content": full_prompt})
71
-
 
 
72
  ans = ""
73
- # Cập nhật UI ngay lập tức
74
- display_history = history + [{"role": "user", "content": message.get("text") or "Gửi file"}]
75
 
76
  try:
 
 
 
77
  for token in client.chat_completion(messages=messages, max_tokens=2048, stream=True):
78
  if token.choices[0].delta.content:
79
  ans += token.choices[0].delta.content
80
- yield "", display_history + [{"role": "assistant", "content": ans}], session_id, ""
81
 
82
- # Lưu vào Supabase sau khi hoàn thành stream
83
  final_history = display_history + [{"role": "assistant", "content": ans}]
84
- title = message.get("text", "Workspace Analysis")[:25]
85
- save_to_db(username, session_id, title, final_history)
86
- yield "", final_history, session_id, ans
 
87
  except Exception as e:
88
- yield "", history + [{"role": "assistant", "content": f"⚠️ Lỗi: {str(e)}"}], session_id, ""
89
 
90
- # 5. DỰNG WEB APP
91
- with gr.Blocks(title="NodeAI Diamond Pro", css=custom_css) as demo:
92
  session_id = gr.State(str(uuid.uuid4()))
93
- tts_buffer = gr.Textbox(visible=False)
94
  db_state = gr.State([])
95
 
96
  with gr.Row():
97
- # Sidebar History
98
  with gr.Column(scale=1, elem_classes="sidebar-node"):
99
- gr.HTML("<div class='logo-area'><h1>NODEAI GENESIS</h1></div>")
100
- gr.LoginButton()
101
- new_chat = gr.Button("+ NEW WORKSPACE", elem_classes="orange-btn")
102
 
103
- gr.Markdown("### 🛠 Lịch sử Cloud")
104
  @gr.render(inputs=[db_state])
105
- def render_history(items, profile: gr.OAuthProfile | None):
106
  with gr.Column():
 
 
107
  for item in items:
108
  b = gr.Button(f"◈ {item['title']}", variant="ghost")
109
- b.click(lambda h=item['history'], s=item['session_id']: (h, s),
110
- None, [chatbot, session_id])
111
 
112
- # Main Chat Area
113
  with gr.Column(scale=4):
114
- chatbot = gr.Chatbot(show_label=False, bubble_full_width=False, height="75vh")
115
- audio_player = gr.Audio(autoplay=True, visible=False)
116
 
117
  with gr.Row(elem_classes="input-area"):
118
  msg_input = gr.MultimodalTextbox(
119
  show_label=False,
120
- placeholder="Dán script Roblox hoặc hỏi Master Phúc...",
121
- file_types=["image", ".lua", ".py", ".txt"],
122
  container=False
123
  )
124
 
125
- # Khởi tạo dữ liệu
126
- def refresh(profile: gr.OAuthProfile | None):
127
- user = profile.username if profile else "Master_Phuc"
128
- return get_user_history(user)
129
-
130
- demo.load(refresh, None, db_state)
131
 
132
- # Event Handlers
133
  msg_input.submit(
134
- chat_engine, [msg_input, chatbot, session_id], [msg_input, chatbot, session_id, tts_buffer]
135
- ).then(refresh, None, db_state).then(
136
- lambda x: f"https://translate.google.com/translate_tts?ie=UTF-8&tl=vi&client=tw-ob&q={x[:200]}" if x else None,
137
- tts_buffer, audio_player
138
- )
139
 
140
- new_chat.click(lambda: ([], str(uuid.uuid4())), None, [chatbot, session_id])
 
141
 
142
  if __name__ == "__main__":
143
  demo.launch()
 
3
  from supabase import create_client, Client
4
  import os
5
  import uuid
 
 
6
 
7
+ # 1. CẤU HÌNH CORE & SUPABASE
8
  URL = os.environ.get("SUPABASE_URL")
9
  KEY = os.environ.get("SUPABASE_KEY")
10
  HF_TOKEN = os.environ.get("HUGGINGFACE_HUB_TOKEN")
11
 
12
+ # Định danh mặc định
13
+ MASTER_ID = "lamgamepro"
14
+
15
+ # Khởi tạo Memory (Supabase) an toàn
16
+ try:
17
+ supabase: Client = create_client(URL, KEY) if URL and KEY else None
18
+ except:
19
+ supabase = None
20
+
21
  client = InferenceClient(model="Qwen/Qwen2.5-7B-Instruct", token=HF_TOKEN)
22
 
23
+ # 2. HỆ THỐNG MEMORY (Tích hợp sâu vào script)
24
+ def get_db_history():
25
+ if not supabase: return []
26
  try:
27
+ res = supabase.table("chats").select("*").eq("username", MASTER_ID).order("created_at", desc=True).execute()
28
  return res.data
29
+ except Exception as e:
30
+ print(f"Lỗi tải DB: {e}")
31
+ return []
32
 
33
+ def save_to_db(session_id, title, history):
34
+ if not supabase: return
35
  try:
36
+ data = {"username": MASTER_ID, "session_id": session_id, "title": title, "history": history}
37
  supabase.table("chats").upsert(data, on_conflict="session_id").execute()
38
+ except Exception as e:
39
+ print(f"Lỗi lưu DB: {e}")
40
 
41
+ # 3. GIAO DIỆN GLASSMORPHISM
42
  custom_css = """
43
  @import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@700&family=Plus+Jakarta+Sans:wght@400;600&display=swap');
44
  :root { --primary: #38bdf8; --accent: #f97316; }
45
+ .gradio-container { background: radial-gradient(circle at 50% 0%, #0f172a 0%, #020617 100%) !important; color: #e2e8f0 !important; font-family: 'Plus Jakarta Sans', sans-serif !important; }
46
+ .sidebar-node { background: rgba(15, 23, 42, 0.7) !important; backdrop-filter: blur(20px) !important; border-right: 1px solid rgba(56, 189, 248, 0.2) !important; height: 100vh !important; padding: 20px; overflow-y: auto; }
47
+ .logo-area { font-family: 'Orbitron', sans-serif; background: linear-gradient(90deg, var(--primary), #818cf8); -webkit-background-clip: text; -webkit-text-fill-color: transparent; text-align: center; padding: 10px 0 30px 0; font-size: 24px; }
48
+ .input-area { background: rgba(30, 41, 59, 0.9) !important; border: 1px solid var(--primary) !important; border-radius: 20px !important; box-shadow: 0 0 20px rgba(56, 189, 248, 0.2) !important; margin-top: 15px; }
49
+ .orange-btn { background: linear-gradient(135deg, #f97316 0%, #fb923c 100%) !important; color: white !important; font-weight: bold !important; border: none !important; border-radius: 12px !important; margin-bottom: 20px; }
 
50
  footer { display: none !important; }
51
  """
52
 
53
+ # 4. LOGIC PHÂN TÍCH ĐA PHƯƠNG TIỆN (Code/Text/Ảnh)
54
  def process_content(message):
55
  text = message.get("text", "")
56
  files = message.get("files", [])
 
61
  if f.lower().endswith(('.lua', '.py', '.txt', '.js', '.html', '.css')):
62
  try:
63
  with open(f, "r", encoding="utf-8") as file:
64
+ combined_prompt += f"\n\n[=== NỘI DUNG FILE: {name} ===]\n{file.read()}"
65
  except: pass
66
  elif f.lower().endswith(('.png', '.jpg', '.jpeg')):
67
+ combined_prompt += f"\n\n[Hệ thống: Master đã gửi kèm ảnh {name}]"
68
  return combined_prompt
69
 
70
+ def chat_engine(message, history, session_id):
 
71
  full_prompt = process_content(message)
72
+ if not full_prompt.strip():
73
+ yield gr.update(value={"text": "", "files": []}), history, session_id
74
+ return
75
+
76
+ # Chuẩn bị Prompt cho AI
77
+ messages = [{"role": "system", "content": f"Bạn là NodeAI Genesis. Master của bạn là {MASTER_ID}. Bạn là chuyên gia về Roblox Studio Lua, Three.js và Web Development."}]
78
 
79
+ # Đọc lịch sử (Chuẩn Gradio 6)
80
+ for msg in history:
81
+ content = msg["content"]
82
+ if isinstance(content, str):
83
+ messages.append({"role": msg["role"], "content": content})
84
 
 
 
 
85
  messages.append({"role": "user", "content": full_prompt})
86
+
87
+ # Hiển thị trên UI
88
+ display_history = history + [{"role": "user", "content": message.get("text") or f"Đã gửi {len(message.get('files', []))} file đính kèm"}]
89
  ans = ""
 
 
90
 
91
  try:
92
+ # Xóa thanh nhập liệu ngay khi bắt đầu xử lý
93
+ yield gr.update(value={"text": "", "files": []}), display_history + [{"role": "assistant", "content": "..."}], session_id
94
+
95
  for token in client.chat_completion(messages=messages, max_tokens=2048, stream=True):
96
  if token.choices[0].delta.content:
97
  ans += token.choices[0].delta.content
98
+ yield gr.update(), display_history + [{"role": "assistant", "content": ans}], session_id
99
 
100
+ # Lưu vào Supabase khi hoàn thành
101
  final_history = display_history + [{"role": "assistant", "content": ans}]
102
+ title = message.get("text", "Phân tích file")[:25] if message.get("text") else "Phân tích Code"
103
+ save_to_db(session_id, title, final_history)
104
+
105
+ yield gr.update(), final_history, session_id
106
  except Exception as e:
107
+ yield gr.update(), history + [{"role": "assistant", "content": f"⚠️ Lỗi kết nối AI: {str(e)}"}], session_id
108
 
109
+ # 5. XÂY DỰNG GIAO DIỆN CHÍNH
110
+ with gr.Blocks(title="NodeAI Genesis Pro", css=custom_css) as demo:
111
  session_id = gr.State(str(uuid.uuid4()))
 
112
  db_state = gr.State([])
113
 
114
  with gr.Row():
115
+ # Cột Sidebar: Lịch sử Memory
116
  with gr.Column(scale=1, elem_classes="sidebar-node"):
117
+ gr.HTML("<div class='logo-area'>NODEAI GENESIS</div>")
118
+ new_chat_btn = gr.Button("+ WORKSPACE MỚI", elem_classes="orange-btn")
119
+ gr.Markdown("### 🗄️ Database Memory")
120
 
 
121
  @gr.render(inputs=[db_state])
122
+ def render_history(items):
123
  with gr.Column():
124
+ if not items:
125
+ gr.Markdown("*Chưa có dữ liệu hoặc lỗi kết nối Supabase.*")
126
  for item in items:
127
  b = gr.Button(f"◈ {item['title']}", variant="ghost")
128
+ b.click(lambda h=item['history'], s=item['session_id']: (h, s), None, [chatbot, session_id])
 
129
 
130
+ # Cột Chatbot: Tương tác chính
131
  with gr.Column(scale=4):
132
+ chatbot = gr.Chatbot(type="messages", show_label=False, height="80vh")
 
133
 
134
  with gr.Row(elem_classes="input-area"):
135
  msg_input = gr.MultimodalTextbox(
136
  show_label=False,
137
+ placeholder="Dán mã Roblox Lua, tải ảnh hoặc hỏi đáp tại đây...",
138
+ file_types=["image", ".lua", ".py", ".txt", ".js", ".html", ".css"],
139
  container=False
140
  )
141
 
142
+ # Khởi động: Load dữ liệu từ Supabase
143
+ def refresh_db(): return get_db_history()
144
+ demo.load(refresh_db, None, db_state)
 
 
 
145
 
146
+ # Xử lý sự kiện gửi tin nhắn
147
  msg_input.submit(
148
+ chat_engine,
149
+ [msg_input, chatbot, session_id],
150
+ [msg_input, chatbot, session_id]
151
+ ).then(refresh_db, None, db_state) # Cập nhật lại danh sách bên trái
 
152
 
153
+ # Nút tạo Chat mới
154
+ new_chat_btn.click(lambda: ([], str(uuid.uuid4())), None, [chatbot, session_id])
155
 
156
  if __name__ == "__main__":
157
  demo.launch()