Spaces:
Sleeping
Sleeping
quyk67uet
commited on
Commit
·
b15b3d8
1
Parent(s):
d9b1e6c
Update 100
Browse files- app.py +64 -44
- pages/multiagent_system.py +0 -62
app.py
CHANGED
@@ -18,7 +18,6 @@ from sympy import Rem
|
|
18 |
from PIL import Image
|
19 |
import io
|
20 |
from faster_whisper import WhisperModel
|
21 |
-
from st_audiorec import st_audiorec
|
22 |
import tempfile
|
23 |
|
24 |
load_dotenv()
|
@@ -376,28 +375,31 @@ def load_resources():
|
|
376 |
**NHIỆM VỤ:**
|
377 |
Dựa trên **chủ đề yếu** của học sinh và **danh sách video** được cung cấp, hãy thực hiện 2 việc:
|
378 |
|
379 |
-
1.
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
2.
|
384 |
-
|
385 |
|
386 |
**THÔNG TIN ĐẦU VÀO:**
|
387 |
-
-
|
388 |
-
-
|
389 |
|
390 |
**YÊU CẦU OUTPUT:**
|
391 |
-
|
392 |
|
393 |
-
|
394 |
-
1. **Bài 1:** [Nội dung câu hỏi bài tập 1]
|
395 |
-
2. **Bài 2:** [Nội dung câu hỏi bài tập 2]
|
396 |
|
|
|
|
|
|
|
|
|
|
|
397 |
|
398 |
-
### 📹 VIDEO ĐỀ XUẤT
|
399 |
**[Tên video]**
|
400 |
-
🎬 Link: https://www.youtube.com/playlist?list=PL5q2T2FxzK7XY4s9FqDi6KCFEpGr2LX2D
|
|
|
401 |
|
402 |
insight_template = """
|
403 |
Bạn là một chuyên gia phân tích giáo dục. Nhiệm vụ của bạn là đọc kỹ đoạn hội thoại và xác định chính xác những khái niệm toán học mà học sinh đang hiểu sai.
|
@@ -583,16 +585,19 @@ def load_resources():
|
|
583 |
"whisper_model": whisper_model
|
584 |
}
|
585 |
|
586 |
-
def transcribe_audio(
|
587 |
"""
|
588 |
-
Nhận
|
589 |
-
Phiên bản
|
590 |
"""
|
591 |
-
if not
|
592 |
return ""
|
593 |
|
594 |
tmp_file_path = ""
|
595 |
try:
|
|
|
|
|
|
|
596 |
with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as tmpfile:
|
597 |
tmpfile.write(audio_bytes)
|
598 |
tmp_file_path = tmpfile.name
|
@@ -1132,6 +1137,10 @@ def main():
|
|
1132 |
welcome_msg = "Xin chào! Tôi là gia sư AI của bạn 😊. Hôm nay chúng ta cùng học Toán nhé!"
|
1133 |
st.session_state.messages.append({"role": "assistant", "content": welcome_msg, "intent": "greeting_social"})
|
1134 |
|
|
|
|
|
|
|
|
|
1135 |
# Container để chứa các tin nhắn chat
|
1136 |
chat_placeholder = st.container()
|
1137 |
with chat_placeholder:
|
@@ -1140,13 +1149,17 @@ def main():
|
|
1140 |
# Sử dụng hàm render tùy chỉnh
|
1141 |
render_chat_message(msg_data["content"], is_user, key=f"msg_{i}")
|
1142 |
|
1143 |
-
|
1144 |
-
st.markdown("#### Hoặc
|
1145 |
-
|
1146 |
-
|
1147 |
-
|
1148 |
-
|
1149 |
-
|
|
|
|
|
|
|
|
|
1150 |
|
1151 |
# 2. Form Nhập liệu cho Text và Ảnh
|
1152 |
with st.form(key="chat_form", clear_on_submit=True):
|
@@ -1159,26 +1172,32 @@ def main():
|
|
1159 |
|
1160 |
submit_button = st.form_submit_button(label="Gửi")
|
1161 |
|
1162 |
-
|
1163 |
final_user_text = ""
|
1164 |
final_image_data = None
|
1165 |
|
1166 |
-
|
1167 |
-
|
1168 |
-
|
1169 |
-
|
1170 |
-
|
1171 |
-
|
1172 |
-
|
1173 |
-
|
1174 |
-
|
1175 |
-
|
1176 |
-
|
1177 |
-
|
1178 |
-
|
1179 |
-
|
1180 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
1181 |
|
|
|
1182 |
elif submit_button:
|
1183 |
final_user_text = user_text
|
1184 |
if uploaded_image:
|
@@ -1286,7 +1305,6 @@ def main():
|
|
1286 |
print(f"ERROR: [Proactive Flow] Đã xảy ra lỗi: {str(e)}")
|
1287 |
proactive_typing_placeholder.empty()
|
1288 |
|
1289 |
-
|
1290 |
# Rerun để cập nhật giao diện
|
1291 |
st.rerun()
|
1292 |
|
@@ -1298,7 +1316,7 @@ def main():
|
|
1298 |
if st.button("Đăng xuất", use_container_width=True):
|
1299 |
supabase.auth.sign_out()
|
1300 |
# Xóa các session state liên quan đến user
|
1301 |
-
keys_to_delete = ["user", "messages"]
|
1302 |
for key in keys_to_delete:
|
1303 |
if key in st.session_state:
|
1304 |
del st.session_state[key]
|
@@ -1308,6 +1326,8 @@ def main():
|
|
1308 |
|
1309 |
if st.button("🗑️ Xóa lịch sử chat", use_container_width=True):
|
1310 |
st.session_state.messages = []
|
|
|
|
|
1311 |
st.rerun()
|
1312 |
|
1313 |
if __name__ == "__main__":
|
|
|
18 |
from PIL import Image
|
19 |
import io
|
20 |
from faster_whisper import WhisperModel
|
|
|
21 |
import tempfile
|
22 |
|
23 |
load_dotenv()
|
|
|
375 |
**NHIỆM VỤ:**
|
376 |
Dựa trên **chủ đề yếu** của học sinh và **danh sách video** được cung cấp, hãy thực hiện 2 việc:
|
377 |
|
378 |
+
1. **Tạo 2 Bài tập Mới:**
|
379 |
+
- Các bài tập phải liên quan trực tiếp đến chủ đề yếu.
|
380 |
+
- Độ khó tương đương chương trình lớp 9.
|
381 |
+
- Bài tập phải hoàn toàn mới, không được trùng lặp với các ví dụ phổ biến.
|
382 |
+
2. **Đề xuất 1 Video Phù hợp nhất:**
|
383 |
+
- Chọn ra MỘT video từ danh sách có nội dung liên quan chặt chẽ nhất đến chủ đề yếu.
|
384 |
|
385 |
**THÔNG TIN ĐẦU VÀO:**
|
386 |
+
- **Chủ đề yếu của học sinh:** '{{ student_weakness }}'
|
387 |
+
- **Danh sách video có sẵn (JSON):** {{ video_cheatsheet_json }}
|
388 |
|
389 |
**YÊU CẦU OUTPUT:**
|
390 |
+
Trả lời theo định dạng sau (không thêm lời dẫn):
|
391 |
|
392 |
+
🎯 **BÀI TẬP CỦNG CỐ**
|
|
|
|
|
393 |
|
394 |
+
**Bài 1:** [Nội dung câu hỏi bài tập 1]
|
395 |
+
|
396 |
+
**Bài 2:** [Nội dung câu hỏi bài tập 2]
|
397 |
+
|
398 |
+
📹 **VIDEO ĐỀ XUẤT**
|
399 |
|
|
|
400 |
**[Tên video]**
|
401 |
+
🎬 Link: https://www.youtube.com/playlist?list=PL5q2T2FxzK7XY4s9FqDi6KCFEpGr2LX2D
|
402 |
+
"""
|
403 |
|
404 |
insight_template = """
|
405 |
Bạn là một chuyên gia phân tích giáo dục. Nhiệm vụ của bạn là đọc kỹ đoạn hội thoại và xác định chính xác những khái niệm toán học mà học sinh đang hiểu sai.
|
|
|
585 |
"whisper_model": whisper_model
|
586 |
}
|
587 |
|
588 |
+
def transcribe_audio(audio_file, whisper_model: WhisperModel) -> str:
|
589 |
"""
|
590 |
+
Nhận audio file từ st.audio_input và chuyển đổi thành văn bản bằng Faster Whisper.
|
591 |
+
Phiên bản được cập nhật cho môi trường deployment.
|
592 |
"""
|
593 |
+
if not audio_file:
|
594 |
return ""
|
595 |
|
596 |
tmp_file_path = ""
|
597 |
try:
|
598 |
+
# Đọc audio file từ st.audio_input (UploadedFile object)
|
599 |
+
audio_bytes = audio_file.read()
|
600 |
+
|
601 |
with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as tmpfile:
|
602 |
tmpfile.write(audio_bytes)
|
603 |
tmp_file_path = tmpfile.name
|
|
|
1137 |
welcome_msg = "Xin chào! Tôi là gia sư AI của bạn 😊. Hôm nay chúng ta cùng học Toán nhé!"
|
1138 |
st.session_state.messages.append({"role": "assistant", "content": welcome_msg, "intent": "greeting_social"})
|
1139 |
|
1140 |
+
# Khởi tạo session state để theo dõi audio đã xử lý
|
1141 |
+
if "processed_audio_ids" not in st.session_state:
|
1142 |
+
st.session_state.processed_audio_ids = set()
|
1143 |
+
|
1144 |
# Container để chứa các tin nhắn chat
|
1145 |
chat_placeholder = st.container()
|
1146 |
with chat_placeholder:
|
|
|
1149 |
# Sử dụng hàm render tùy chỉnh
|
1150 |
render_chat_message(msg_data["content"], is_user, key=f"msg_{i}")
|
1151 |
|
1152 |
+
# Audio input section with better error handling
|
1153 |
+
st.markdown("#### Hoặc ghi âm giọng nói:")
|
1154 |
+
|
1155 |
+
# Check if running in secure context for microphone access
|
1156 |
+
audio_input = None
|
1157 |
+
try:
|
1158 |
+
# Use Streamlit's built-in audio_input which is more stable
|
1159 |
+
audio_input = st.audio_input("🎤 Nhấn để ghi âm", help="Ghi âm câu hỏi của bạn bằng tiếng Việt")
|
1160 |
+
except Exception as e:
|
1161 |
+
st.warning("⚠️ Không thể truy cập microphone. Vui lòng sử dụng form nhập text bên dưới.")
|
1162 |
+
print(f"DEBUG: Audio input error: {e}")
|
1163 |
|
1164 |
# 2. Form Nhập liệu cho Text và Ảnh
|
1165 |
with st.form(key="chat_form", clear_on_submit=True):
|
|
|
1172 |
|
1173 |
submit_button = st.form_submit_button(label="Gửi")
|
1174 |
|
|
|
1175 |
final_user_text = ""
|
1176 |
final_image_data = None
|
1177 |
|
1178 |
+
# Handle audio input if available - với logic tránh xử lý lặp lại
|
1179 |
+
if audio_input is not None:
|
1180 |
+
# Tạo unique ID cho audio file dựa trên file_id và size
|
1181 |
+
audio_id = f"{audio_input.file_id}_{audio_input.size}" if hasattr(audio_input, 'file_id') and hasattr(audio_input, 'size') else f"{id(audio_input)}_{len(audio_input.getvalue())}"
|
1182 |
+
|
1183 |
+
# Chỉ xử lý nếu audio này chưa được xử lý
|
1184 |
+
if audio_id not in st.session_state.processed_audio_ids:
|
1185 |
+
with st.spinner("🎧 Đang xử lý giọng nói..."):
|
1186 |
+
transcribed_text = transcribe_audio(audio_input, resources["whisper_model"])
|
1187 |
+
if transcribed_text and transcribed_text.strip() and len(transcribed_text.strip()) > 1:
|
1188 |
+
final_user_text = transcribed_text
|
1189 |
+
st.success(f"✅ Đã nhận diện: {transcribed_text}")
|
1190 |
+
# Đánh dấu audio này đã được xử lý
|
1191 |
+
st.session_state.processed_audio_ids.add(audio_id)
|
1192 |
+
else:
|
1193 |
+
st.warning("⚠️ Không nhận diện được nội dung. Vui lòng thử lại hoặc sử dụng text input.")
|
1194 |
+
# Vẫn đánh dấu để tránh xử lý lại
|
1195 |
+
st.session_state.processed_audio_ids.add(audio_id)
|
1196 |
+
else:
|
1197 |
+
# Audio đã được xử lý, không làm gì cả
|
1198 |
+
print(f"DEBUG: Audio {audio_id} đã được xử lý trước đó, bỏ qua.")
|
1199 |
|
1200 |
+
# Handle form submission
|
1201 |
elif submit_button:
|
1202 |
final_user_text = user_text
|
1203 |
if uploaded_image:
|
|
|
1305 |
print(f"ERROR: [Proactive Flow] Đã xảy ra lỗi: {str(e)}")
|
1306 |
proactive_typing_placeholder.empty()
|
1307 |
|
|
|
1308 |
# Rerun để cập nhật giao diện
|
1309 |
st.rerun()
|
1310 |
|
|
|
1316 |
if st.button("Đăng xuất", use_container_width=True):
|
1317 |
supabase.auth.sign_out()
|
1318 |
# Xóa các session state liên quan đến user
|
1319 |
+
keys_to_delete = ["user", "messages", "processed_audio_ids"]
|
1320 |
for key in keys_to_delete:
|
1321 |
if key in st.session_state:
|
1322 |
del st.session_state[key]
|
|
|
1326 |
|
1327 |
if st.button("🗑️ Xóa lịch sử chat", use_container_width=True):
|
1328 |
st.session_state.messages = []
|
1329 |
+
# Cũng xóa audio đã xử lý để có thể ghi âm lại
|
1330 |
+
st.session_state.processed_audio_ids = set()
|
1331 |
st.rerun()
|
1332 |
|
1333 |
if __name__ == "__main__":
|
pages/multiagent_system.py
CHANGED
@@ -3,7 +3,6 @@ import os
|
|
3 |
from supabase import create_client, Client
|
4 |
from datetime import datetime
|
5 |
import json
|
6 |
-
import time
|
7 |
|
8 |
# Thiết lập page config
|
9 |
st.set_page_config(
|
@@ -12,52 +11,6 @@ st.set_page_config(
|
|
12 |
layout="wide"
|
13 |
)
|
14 |
|
15 |
-
# Trick để fix layout issue khi deploy
|
16 |
-
def fix_layout_trick():
|
17 |
-
"""
|
18 |
-
Trick để fix layout issue trên Hugging Face Spaces
|
19 |
-
"""
|
20 |
-
# Thêm JavaScript để force reflow sau khi page load
|
21 |
-
st.markdown("""
|
22 |
-
<script>
|
23 |
-
// Force reflow after page loads
|
24 |
-
setTimeout(function() {
|
25 |
-
window.dispatchEvent(new Event('resize'));
|
26 |
-
document.body.style.display = 'none';
|
27 |
-
document.body.offsetHeight; // trigger reflow
|
28 |
-
document.body.style.display = '';
|
29 |
-
}, 100);
|
30 |
-
|
31 |
-
// Additional reflow after 500ms
|
32 |
-
setTimeout(function() {
|
33 |
-
window.dispatchEvent(new Event('resize'));
|
34 |
-
}, 500);
|
35 |
-
</script>
|
36 |
-
""", unsafe_allow_html=True)
|
37 |
-
|
38 |
-
# CSS để đảm bảo smooth loading
|
39 |
-
st.markdown("""
|
40 |
-
<style>
|
41 |
-
/* Ensure smooth loading */
|
42 |
-
.main .block-container {
|
43 |
-
opacity: 0;
|
44 |
-
animation: fadeIn 0.5s ease-in-out forwards;
|
45 |
-
animation-delay: 0.1s;
|
46 |
-
}
|
47 |
-
|
48 |
-
@keyframes fadeIn {
|
49 |
-
from { opacity: 0; }
|
50 |
-
to { opacity: 1; }
|
51 |
-
}
|
52 |
-
|
53 |
-
/* Force proper rendering */
|
54 |
-
.stApp {
|
55 |
-
transform: translateZ(0);
|
56 |
-
backface-visibility: hidden;
|
57 |
-
}
|
58 |
-
</style>
|
59 |
-
""", unsafe_allow_html=True)
|
60 |
-
|
61 |
def init_supabase_client() -> Client:
|
62 |
"""
|
63 |
Khởi tạo Supabase client
|
@@ -125,8 +78,6 @@ def display_agents():
|
|
125 |
margin-bottom: 2rem;
|
126 |
overflow: hidden;
|
127 |
border: 1px solid rgba(0,0,0,0.05);
|
128 |
-
transform: translateZ(0);
|
129 |
-
will-change: transform;
|
130 |
}
|
131 |
|
132 |
.agent-header {
|
@@ -731,19 +682,6 @@ def main():
|
|
731 |
"""
|
732 |
Hàm chính của trang Multi-Agent System
|
733 |
"""
|
734 |
-
# Áp dụng trick fix layout ngay đầu
|
735 |
-
fix_layout_trick()
|
736 |
-
|
737 |
-
# Thêm một sidebar trick để trigger re-render
|
738 |
-
with st.sidebar:
|
739 |
-
st.markdown("""
|
740 |
-
<div style="position: absolute; left: -9999px; opacity: 0;">
|
741 |
-
<button id="layout-trigger" onclick="window.dispatchEvent(new Event('resize'));">
|
742 |
-
Trigger Layout
|
743 |
-
</button>
|
744 |
-
</div>
|
745 |
-
""", unsafe_allow_html=True)
|
746 |
-
|
747 |
# Hiển thị kiến trúc hệ thống
|
748 |
display_system_architecture()
|
749 |
|
|
|
3 |
from supabase import create_client, Client
|
4 |
from datetime import datetime
|
5 |
import json
|
|
|
6 |
|
7 |
# Thiết lập page config
|
8 |
st.set_page_config(
|
|
|
11 |
layout="wide"
|
12 |
)
|
13 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
def init_supabase_client() -> Client:
|
15 |
"""
|
16 |
Khởi tạo Supabase client
|
|
|
78 |
margin-bottom: 2rem;
|
79 |
overflow: hidden;
|
80 |
border: 1px solid rgba(0,0,0,0.05);
|
|
|
|
|
81 |
}
|
82 |
|
83 |
.agent-header {
|
|
|
682 |
"""
|
683 |
Hàm chính của trang Multi-Agent System
|
684 |
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
685 |
# Hiển thị kiến trúc hệ thống
|
686 |
display_system_architecture()
|
687 |
|