lamgamepro1 commited on
Commit
c2b98de
·
verified ·
1 Parent(s): 010fa6c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +68 -94
app.py CHANGED
@@ -1,131 +1,105 @@
1
  import gradio as gr
2
  from huggingface_hub import InferenceClient
3
- from supabase import create_client, Client
4
  import os
5
  import uuid
6
 
7
- # 1. SETUP
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
- try:
13
- supabase: Client = create_client(URL, KEY) if URL and KEY else None
14
- except:
15
- supabase = None
16
-
17
  client = InferenceClient(model="Qwen/Qwen2.5-7B-Instruct", token=HF_TOKEN)
18
 
19
- # 2. JS & CSS (Xóa sạch Header/Footer)
20
- js_cleaner = """
21
- <img src="x" onerror="
22
- const observer = new MutationObserver(() => {
23
- ['footer', '.built-with', 'header', '#header', '.share-button'].forEach(s => {
24
- const el = document.querySelector(s);
25
- if (el) el.remove();
26
- });
27
- });
28
- observer.observe(document.body, { childList: true, subtree: true });
29
- " style="display:none;">
30
- """
31
-
32
- custom_css = """
33
- footer, .built-with, header, #header { display: none !important; }
34
- .gradio-container { max-width: 100% !important; padding: 0 !important; }
35
- .sidebar-node { background: rgba(15, 23, 42, 0.9) !important; border-right: 1px solid #38bdf833; padding: 20px; }
36
- .logo-area {
37
- font-family: 'Orbitron', sans-serif;
38
- background: linear-gradient(90deg, #38bdf8, #818cf8);
39
- -webkit-background-clip: text; -webkit-text-fill-color: transparent;
40
- font-size: 22px; text-align: center; font-weight: bold; margin-bottom: 20px;
41
- }
42
- .custom-warning { text-align: center; color: #94a3b8; font-size: 12px; margin: 8px 0; font-style: italic; }
43
- """
44
-
45
- # 3. DATABASE LOGIC
46
- def get_db_history(profile: gr.OAuthProfile | None):
47
- if not supabase or not profile: return []
48
- try:
49
- res = supabase.table("chats").select("*").eq("username", profile.username).order("last_updated", desc=True).execute()
50
- return res.data
51
- except: return []
52
-
53
- def load_selected_chat(evt: gr.SelectData, db_data):
54
- selected_item = db_data[evt.index]
55
- # Trả về lịch sử từ SQL và session_id tương ứng
56
- return selected_item['history'], selected_item['session_id']
57
-
58
- # 4. CHAT ENGINE (Đọc/Ghi Memory trực tiếp vào SQL)
59
- def chat_engine(message, history, session_id, profile: gr.OAuthProfile | None):
60
  text = message.get("text", "").strip()
61
- if not text: yield gr.update(value={"text": "", "files": []}), history, session_id; return
 
 
62
 
63
- # Cấu hình bối cảnh cho AI
64
- user_name = profile.username if profile else "Guest"
65
- system_msg = {"role": "system", "content": f"Bạn là NodeAI Genesis. Master: {user_name}."}
 
 
 
 
66
 
67
- # Tạo prompt từ lịch sử (Memory)
68
- messages = [system_msg] + history + [{"role": "user", "content": text}]
69
 
 
70
  new_history = history + [{"role": "user", "content": text}]
71
  ans = ""
72
 
73
- yield gr.update(value={"text": "", "files": []}), new_history + [{"role": "assistant", "content": "..."}], session_id
 
74
 
75
  try:
76
  for token in client.chat_completion(messages=messages, max_tokens=2048, stream=True):
77
  if token.choices[0].delta.content:
78
  ans += token.choices[0].delta.content
79
- yield gr.update(), new_history + [{"role": "assistant", "content": ans}], session_id
80
-
81
- # LƯU VÀO SQL (Memory thực thụ)
82
- if profile:
83
- final_history = new_history + [{"role": "assistant", "content": ans}]
84
- data = {
85
- "username": profile.username,
86
- "session_id": session_id,
87
- "title": text[:30],
88
- "history": final_history
89
- }
90
- supabase.table("chats").upsert(data, on_conflict="session_id").execute()
91
-
92
  except Exception as e:
93
- yield gr.update(), new_history + [{"role": "assistant", "content": f"Lỗi: {str(e)}"}], session_id
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
 
95
- # 5. UI
96
  with gr.Blocks(css=custom_css) as demo:
97
  gr.HTML(js_cleaner, visible=False)
98
- session_id = gr.State(str(uuid.uuid4()))
99
- db_state = gr.State([])
100
-
101
  with gr.Row():
 
102
  with gr.Column(scale=1, elem_classes="sidebar-node"):
103
  gr.HTML("<div class='logo-area'>NODEAI GENESIS</div>")
104
  gr.LoginButton(value="Đăng nhập", size="sm")
105
- new_chat_btn = gr.Button("+ WORKSPACE MỚI", variant="primary")
106
- gr.Markdown("### 🗄️ SQL Memory")
107
- history_list = gr.Dataset(components=[gr.Textbox(visible=False)], samples=[], type="index")
108
 
 
109
  with gr.Column(scale=4):
110
- chatbot = gr.Chatbot(show_label=False, height="76vh")
 
 
111
  gr.HTML("<div class='custom-warning'>NodeAI không thể chắc chắn 100%, hãy rà soát lại khi bạn có chuyện gì quan trọng!</div>")
112
- msg_input = gr.MultimodalTextbox(show_label=False, placeholder="Hỏi NodeAI...", container=False)
113
-
114
- def refresh_data(profile: gr.OAuthProfile | None):
115
- if not profile: return [], gr.Dataset(samples=[])
116
- data = get_db_history(profile)
117
- return data, gr.Dataset(samples=[[item['title']] for item in data])
118
 
119
- demo.load(refresh_data, None, [db_state, history_list])
120
-
121
- # Khi nhấn vào lịch sử, Chatbot sẽ hiển thị Memory từ SQL
122
- history_list.select(fn=load_selected_chat, inputs=[db_state], outputs=[chatbot, session_id])
123
-
124
- msg_input.submit(chat_engine, [msg_input, chatbot, session_id], [msg_input, chatbot, session_id]).then(
125
- refresh_data, None, [db_state, history_list]
126
  )
127
 
128
- new_chat_btn.click(lambda: ([], str(uuid.uuid4())), None, [chatbot, session_id])
 
129
 
130
  if __name__ == "__main__":
131
  demo.queue().launch()
 
1
  import gradio as gr
2
  from huggingface_hub import InferenceClient
 
3
  import os
4
  import uuid
5
 
6
+ # 1. CẤU HÌNH AI
 
 
7
  HF_TOKEN = os.environ.get("HUGGINGFACE_HUB_TOKEN")
 
 
 
 
 
 
8
  client = InferenceClient(model="Qwen/Qwen2.5-7B-Instruct", token=HF_TOKEN)
9
 
10
+ # 2. MẢNG MEMORY TRONG SCRIPT (Biến cục bộ qua gr.State)
11
+ # Memory này sẽ tồn tại suốt phiên làm việc của Master
12
+ def chat_engine(message, history, profile: gr.OAuthProfile | None):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  text = message.get("text", "").strip()
14
+ if not text:
15
+ yield gr.update(value={"text": "", "files": []}), history
16
+ return
17
 
18
+ # Khởi tạo tin nhắn hệ thống
19
+ user_name = profile.name if profile else "Master"
20
+ messages = [{"role": "system", "content": f"Bạn là NodeAI Genesis. Master: {user_name}."}]
21
+
22
+ # Đổ mảng memory từ history vào tin nhắn gửi đi
23
+ for msg in history:
24
+ messages.append({"role": msg["role"], "content": msg["content"]})
25
 
26
+ messages.append({"role": "user", "content": text})
 
27
 
28
+ # Cập nhật mảng memory tạm thời (history)
29
  new_history = history + [{"role": "user", "content": text}]
30
  ans = ""
31
 
32
+ # Phản hồi streaming
33
+ yield gr.update(value={"text": "", "files": []}), new_history + [{"role": "assistant", "content": "..."}]
34
 
35
  try:
36
  for token in client.chat_completion(messages=messages, max_tokens=2048, stream=True):
37
  if token.choices[0].delta.content:
38
  ans += token.choices[0].delta.content
39
+ yield gr.update(), new_history + [{"role": "assistant", "content": ans}]
 
 
 
 
 
 
 
 
 
 
 
 
40
  except Exception as e:
41
+ yield gr.update(), new_history + [{"role": "assistant", "content": f"Lỗi: {str(e)}"}]
42
+
43
+ # 3. GIAO DIỆN & CSS (Giữ phong cách sạch sẽ)
44
+ custom_css = """
45
+ footer, .built-with, header, #header { display: none !important; }
46
+ .gradio-container { max-width: 100% !important; padding: 0 !important; }
47
+ .sidebar-node { background: rgba(15, 23, 42, 0.9) !important; border-right: 1px solid #38bdf833; padding: 20px; }
48
+ .logo-area {
49
+ font-family: 'Orbitron', sans-serif;
50
+ background: linear-gradient(90deg, #38bdf8, #818cf8);
51
+ -webkit-background-clip: text; -webkit-text-fill-color: transparent;
52
+ font-size: 22px; text-align: center; font-weight: bold; margin-bottom: 20px;
53
+ }
54
+ .custom-warning { text-align: center; color: #94a3b8; font-size: 12px; margin: 10px 0; font-style: italic; }
55
+ """
56
+
57
+ js_cleaner = """
58
+ <img src="x" onerror="
59
+ const observer = new MutationObserver(() => {
60
+ ['footer', '.built-with', 'header', '#header'].forEach(s => {
61
+ const el = document.querySelector(s); if (el) el.remove();
62
+ });
63
+ });
64
+ observer.observe(document.body, { childList: true, subtree: true });
65
+ " style="display:none;">
66
+ """
67
 
 
68
  with gr.Blocks(css=custom_css) as demo:
69
  gr.HTML(js_cleaner, visible=False)
70
+
 
 
71
  with gr.Row():
72
+ # Sidebar (Chỉ để trang trí hoặc bổ sung tính năng sau)
73
  with gr.Column(scale=1, elem_classes="sidebar-node"):
74
  gr.HTML("<div class='logo-area'>NODEAI GENESIS</div>")
75
  gr.LoginButton(value="Đăng nhập", size="sm")
76
+ new_chat_btn = gr.Button("+ CLEAR MEMORY", variant="stop")
77
+ gr.Markdown("---")
78
+ gr.Markdown("💡 **Script Memory**: Đang hoạt động cục bộ. Tốc độ cực nhanh nhưng sẽ reset khi tải lại trang.")
79
 
80
+ # Vùng Chat chính
81
  with gr.Column(scale=4):
82
+ # chatbot lưu trữ mảng history ngay trong component
83
+ chatbot = gr.Chatbot(show_label=False, height="78vh", type="messages")
84
+
85
  gr.HTML("<div class='custom-warning'>NodeAI không thể chắc chắn 100%, hãy rà soát lại khi bạn có chuyện gì quan trọng!</div>")
86
+
87
+ msg_input = gr.MultimodalTextbox(
88
+ show_label=False,
89
+ placeholder="Nhập nội dung tại đây...",
90
+ container=False
91
+ )
92
 
93
+ # Xử lý sự kiện
94
+ # Truyền chatbot trực tiếp vào làm history
95
+ msg_input.submit(
96
+ chat_engine,
97
+ [msg_input, chatbot],
98
+ [msg_input, chatbot]
 
99
  )
100
 
101
+ # Nút xóa sạch mảng memory trong script
102
+ new_chat_btn.click(lambda: [], None, chatbot)
103
 
104
  if __name__ == "__main__":
105
  demo.queue().launch()