Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
| 1 |
-
|
| 2 |
-
# app.py
|
| 3 |
-
from typing import List, Dict, Tuple, Optional
|
| 4 |
import gradio as gr
|
|
|
|
|
|
|
| 5 |
|
| 6 |
from config import (
|
| 7 |
DEFAULT_MODEL,
|
|
@@ -28,9 +27,10 @@ from rag_engine import (
|
|
| 28 |
from syllabus_utils import extract_course_topics_from_file
|
| 29 |
|
| 30 |
# ================== Assets (图片路径配置) ==================
|
|
|
|
| 31 |
HANBRIDGE_LOGO_PATH = "hanbridge_logo.png"
|
| 32 |
CLARE_LOGO_PATH = "clare_mascot.png"
|
| 33 |
-
CLARE_RUN_PATH = "Clare_Run.png"
|
| 34 |
|
| 35 |
# ================== CSS (样式调整) ==================
|
| 36 |
CUSTOM_CSS = """
|
|
@@ -44,6 +44,7 @@ CUSTOM_CSS = """
|
|
| 44 |
border-bottom: 2px solid #f3f4f6;
|
| 45 |
margin-bottom: 15px;
|
| 46 |
}
|
|
|
|
| 47 |
/* User Guide 链接样式 */
|
| 48 |
#user-guide-links button {
|
| 49 |
background: transparent !important; border: none !important; box-shadow: none !important;
|
|
@@ -51,13 +52,14 @@ CUSTOM_CSS = """
|
|
| 51 |
color: #004a99 !important; text-decoration: underline; font-size: 0.8rem;
|
| 52 |
}
|
| 53 |
#user-guide-links button:hover { color: #002b66 !important; }
|
|
|
|
| 54 |
/* Memory Line 区域样式 */
|
| 55 |
.memory-line-box {
|
| 56 |
border: 1px solid #e5e7eb;
|
| 57 |
padding: 12px;
|
| 58 |
border-radius: 8px;
|
| 59 |
background-color: #f9fafb;
|
| 60 |
-
height: 100%;
|
| 61 |
}
|
| 62 |
"""
|
| 63 |
|
|
@@ -80,6 +82,7 @@ def get_user_guide_section(section_key: str) -> str:
|
|
| 80 |
|
| 81 |
# ================== Gradio App ==================
|
| 82 |
|
|
|
|
| 83 |
with gr.Blocks(title="Clare – Hanbridge AI Teaching Assistant", css=CUSTOM_CSS) as demo:
|
| 84 |
|
| 85 |
# 状态变量
|
|
@@ -89,7 +92,6 @@ with gr.Blocks(title="Clare – Hanbridge AI Teaching Assistant", css=CUSTOM_CSS
|
|
| 89 |
rag_chunks_state = gr.State([])
|
| 90 |
|
| 91 |
# ============ 1. 顶部 Header (全宽布局) ============
|
| 92 |
-
# 包含 CLARE_LOGO_PATH (左) 和 HANBRIDGE_LOGO_PATH (右)
|
| 93 |
gr.HTML(
|
| 94 |
f"""
|
| 95 |
<div class="header-container">
|
|
@@ -105,6 +107,7 @@ with gr.Blocks(title="Clare – Hanbridge AI Teaching Assistant", css=CUSTOM_CSS
|
|
| 105 |
</div>
|
| 106 |
</div>
|
| 107 |
</div>
|
|
|
|
| 108 |
<div style="text-align: right;">
|
| 109 |
<img src="file/{HANBRIDGE_LOGO_PATH}" style="height: 55px; object-fit: contain; margin-bottom: 5px;">
|
| 110 |
<div style="font-size: 12px; color: #666;">
|
|
@@ -120,7 +123,6 @@ with gr.Blocks(title="Clare – Hanbridge AI Teaching Assistant", css=CUSTOM_CSS
|
|
| 120 |
|
| 121 |
# ============ [左侧] 控制面板 Sidebar ============
|
| 122 |
with gr.Column(scale=1, min_width=200):
|
| 123 |
-
# Reset 按钮
|
| 124 |
clear_btn = gr.Button("Reset Conversation", variant="stop")
|
| 125 |
|
| 126 |
gr.Markdown("### Model Settings")
|
|
@@ -184,6 +186,7 @@ with gr.Blocks(title="Clare – Hanbridge AI Teaching Assistant", css=CUSTOM_CSS
|
|
| 184 |
<div style="position: absolute; bottom: 5px; left: 0; width: 40%; height: 8px; background-color: #8B1A1A; border-radius: 4px 0 0 4px;"></div>
|
| 185 |
<img src="file/{CLARE_RUN_PATH}" style="position: absolute; left: 36%; bottom: 8px; height: 35px; z-index: 10;">
|
| 186 |
</div>
|
|
|
|
| 187 |
<div style="display:flex; justify-content:space-between; align-items:center; margin-top:8px;">
|
| 188 |
<div style="font-size: 12px; color: #666;">Next Review: T+7</div>
|
| 189 |
<div style="font-size: 12px; color: #004a99; text-decoration:underline; cursor:pointer;">
|
|
@@ -193,10 +196,8 @@ with gr.Blocks(title="Clare – Hanbridge AI Teaching Assistant", css=CUSTOM_CSS
|
|
| 193 |
</div>
|
| 194 |
"""
|
| 195 |
)
|
| 196 |
-
#
|
| 197 |
review_btn = gr.Button("Review Now", size="sm", variant="primary")
|
| 198 |
-
|
| 199 |
-
# 隐藏的 Session Status 用于逻辑传递
|
| 200 |
session_status = gr.Markdown(visible=False)
|
| 201 |
|
| 202 |
# --- Chat Interface ---
|
|
@@ -228,7 +229,6 @@ with gr.Blocks(title="Clare – Hanbridge AI Teaching Assistant", css=CUSTOM_CSS
|
|
| 228 |
# ============ [右侧] 功能栏 Right Sidebar ============
|
| 229 |
with gr.Column(scale=1, min_width=180):
|
| 230 |
gr.Markdown("### Actions")
|
| 231 |
-
|
| 232 |
export_btn = gr.Button("Export Conversation", size="sm")
|
| 233 |
quiz_btn = gr.Button("Let's Try (Micro-Quiz)", size="sm")
|
| 234 |
summary_btn = gr.Button("Summarization", size="sm")
|
|
@@ -243,7 +243,6 @@ with gr.Blocks(title="Clare – Hanbridge AI Teaching Assistant", css=CUSTOM_CSS
|
|
| 243 |
|
| 244 |
# ================== Logic Bindings ==================
|
| 245 |
|
| 246 |
-
# 1. File Upload Logic
|
| 247 |
def update_course_and_rag(file, doc_type_val):
|
| 248 |
topics = extract_course_topics_from_file(file, doc_type_val)
|
| 249 |
rag_chunks = build_rag_chunks_from_file(file, doc_type_val)
|
|
@@ -256,7 +255,6 @@ with gr.Blocks(title="Clare – Hanbridge AI Teaching Assistant", css=CUSTOM_CSS
|
|
| 256 |
outputs=[course_outline_state, rag_chunks_state, session_status],
|
| 257 |
)
|
| 258 |
|
| 259 |
-
# 2. Chat Logic
|
| 260 |
def respond(message, chat_history, course_outline, weaknesses, cognitive_state, rag_chunks, model, lang, mode, doc_type_val):
|
| 261 |
resolved_lang = detect_language(message or "", lang)
|
| 262 |
|
|
@@ -289,7 +287,6 @@ with gr.Blocks(title="Clare – Hanbridge AI Teaching Assistant", css=CUSTOM_CSS
|
|
| 289 |
[user_input, chatbot, weakness_state, cognitive_state_state, session_status]
|
| 290 |
)
|
| 291 |
|
| 292 |
-
# 3. Action Buttons Logic
|
| 293 |
def on_export(chat_history, course_outline, mode, weaknesses, cognitive_state):
|
| 294 |
return export_conversation(chat_history, course_outline, mode, weaknesses, cognitive_state)
|
| 295 |
|
|
@@ -317,7 +314,6 @@ with gr.Blocks(title="Clare – Hanbridge AI Teaching Assistant", css=CUSTOM_CSS
|
|
| 317 |
[result_display]
|
| 318 |
)
|
| 319 |
|
| 320 |
-
# 4. Reset Logic
|
| 321 |
def clear_all():
|
| 322 |
empty_state = {"confusion": 0, "mastery": 0}
|
| 323 |
default_status = render_session_status("Concept Explainer", [], empty_state)
|
|
@@ -330,7 +326,6 @@ with gr.Blocks(title="Clare – Hanbridge AI Teaching Assistant", css=CUSTOM_CSS
|
|
| 330 |
queue=False
|
| 331 |
)
|
| 332 |
|
| 333 |
-
# 5. User Guide Logic
|
| 334 |
def show_guide(section):
|
| 335 |
return get_user_guide_section(section)
|
| 336 |
|
|
@@ -340,4 +335,5 @@ with gr.Blocks(title="Clare – Hanbridge AI Teaching Assistant", css=CUSTOM_CSS
|
|
| 340 |
ug_memory_line.click(lambda: show_guide("memory_line"), outputs=result_display)
|
| 341 |
|
| 342 |
if __name__ == "__main__":
|
| 343 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import gradio as gr
|
| 2 |
+
import os
|
| 3 |
+
from typing import List, Dict, Tuple, Optional
|
| 4 |
|
| 5 |
from config import (
|
| 6 |
DEFAULT_MODEL,
|
|
|
|
| 27 |
from syllabus_utils import extract_course_topics_from_file
|
| 28 |
|
| 29 |
# ================== Assets (图片路径配置) ==================
|
| 30 |
+
# 确保文件名与你上传到 Hugging Face Space 的文件名完全一致
|
| 31 |
HANBRIDGE_LOGO_PATH = "hanbridge_logo.png"
|
| 32 |
CLARE_LOGO_PATH = "clare_mascot.png"
|
| 33 |
+
CLARE_RUN_PATH = "Clare_Run.png"
|
| 34 |
|
| 35 |
# ================== CSS (样式调整) ==================
|
| 36 |
CUSTOM_CSS = """
|
|
|
|
| 44 |
border-bottom: 2px solid #f3f4f6;
|
| 45 |
margin-bottom: 15px;
|
| 46 |
}
|
| 47 |
+
|
| 48 |
/* User Guide 链接样式 */
|
| 49 |
#user-guide-links button {
|
| 50 |
background: transparent !important; border: none !important; box-shadow: none !important;
|
|
|
|
| 52 |
color: #004a99 !important; text-decoration: underline; font-size: 0.8rem;
|
| 53 |
}
|
| 54 |
#user-guide-links button:hover { color: #002b66 !important; }
|
| 55 |
+
|
| 56 |
/* Memory Line 区域样式 */
|
| 57 |
.memory-line-box {
|
| 58 |
border: 1px solid #e5e7eb;
|
| 59 |
padding: 12px;
|
| 60 |
border-radius: 8px;
|
| 61 |
background-color: #f9fafb;
|
| 62 |
+
height: 100%;
|
| 63 |
}
|
| 64 |
"""
|
| 65 |
|
|
|
|
| 82 |
|
| 83 |
# ================== Gradio App ==================
|
| 84 |
|
| 85 |
+
# 【修正】:这里去掉了 allowed_paths=["."]
|
| 86 |
with gr.Blocks(title="Clare – Hanbridge AI Teaching Assistant", css=CUSTOM_CSS) as demo:
|
| 87 |
|
| 88 |
# 状态变量
|
|
|
|
| 92 |
rag_chunks_state = gr.State([])
|
| 93 |
|
| 94 |
# ============ 1. 顶部 Header (全宽布局) ============
|
|
|
|
| 95 |
gr.HTML(
|
| 96 |
f"""
|
| 97 |
<div class="header-container">
|
|
|
|
| 107 |
</div>
|
| 108 |
</div>
|
| 109 |
</div>
|
| 110 |
+
|
| 111 |
<div style="text-align: right;">
|
| 112 |
<img src="file/{HANBRIDGE_LOGO_PATH}" style="height: 55px; object-fit: contain; margin-bottom: 5px;">
|
| 113 |
<div style="font-size: 12px; color: #666;">
|
|
|
|
| 123 |
|
| 124 |
# ============ [左侧] 控制面板 Sidebar ============
|
| 125 |
with gr.Column(scale=1, min_width=200):
|
|
|
|
| 126 |
clear_btn = gr.Button("Reset Conversation", variant="stop")
|
| 127 |
|
| 128 |
gr.Markdown("### Model Settings")
|
|
|
|
| 186 |
<div style="position: absolute; bottom: 5px; left: 0; width: 40%; height: 8px; background-color: #8B1A1A; border-radius: 4px 0 0 4px;"></div>
|
| 187 |
<img src="file/{CLARE_RUN_PATH}" style="position: absolute; left: 36%; bottom: 8px; height: 35px; z-index: 10;">
|
| 188 |
</div>
|
| 189 |
+
|
| 190 |
<div style="display:flex; justify-content:space-between; align-items:center; margin-top:8px;">
|
| 191 |
<div style="font-size: 12px; color: #666;">Next Review: T+7</div>
|
| 192 |
<div style="font-size: 12px; color: #004a99; text-decoration:underline; cursor:pointer;">
|
|
|
|
| 196 |
</div>
|
| 197 |
"""
|
| 198 |
)
|
| 199 |
+
# Review 按钮放在 HTML 下方
|
| 200 |
review_btn = gr.Button("Review Now", size="sm", variant="primary")
|
|
|
|
|
|
|
| 201 |
session_status = gr.Markdown(visible=False)
|
| 202 |
|
| 203 |
# --- Chat Interface ---
|
|
|
|
| 229 |
# ============ [右侧] 功能栏 Right Sidebar ============
|
| 230 |
with gr.Column(scale=1, min_width=180):
|
| 231 |
gr.Markdown("### Actions")
|
|
|
|
| 232 |
export_btn = gr.Button("Export Conversation", size="sm")
|
| 233 |
quiz_btn = gr.Button("Let's Try (Micro-Quiz)", size="sm")
|
| 234 |
summary_btn = gr.Button("Summarization", size="sm")
|
|
|
|
| 243 |
|
| 244 |
# ================== Logic Bindings ==================
|
| 245 |
|
|
|
|
| 246 |
def update_course_and_rag(file, doc_type_val):
|
| 247 |
topics = extract_course_topics_from_file(file, doc_type_val)
|
| 248 |
rag_chunks = build_rag_chunks_from_file(file, doc_type_val)
|
|
|
|
| 255 |
outputs=[course_outline_state, rag_chunks_state, session_status],
|
| 256 |
)
|
| 257 |
|
|
|
|
| 258 |
def respond(message, chat_history, course_outline, weaknesses, cognitive_state, rag_chunks, model, lang, mode, doc_type_val):
|
| 259 |
resolved_lang = detect_language(message or "", lang)
|
| 260 |
|
|
|
|
| 287 |
[user_input, chatbot, weakness_state, cognitive_state_state, session_status]
|
| 288 |
)
|
| 289 |
|
|
|
|
| 290 |
def on_export(chat_history, course_outline, mode, weaknesses, cognitive_state):
|
| 291 |
return export_conversation(chat_history, course_outline, mode, weaknesses, cognitive_state)
|
| 292 |
|
|
|
|
| 314 |
[result_display]
|
| 315 |
)
|
| 316 |
|
|
|
|
| 317 |
def clear_all():
|
| 318 |
empty_state = {"confusion": 0, "mastery": 0}
|
| 319 |
default_status = render_session_status("Concept Explainer", [], empty_state)
|
|
|
|
| 326 |
queue=False
|
| 327 |
)
|
| 328 |
|
|
|
|
| 329 |
def show_guide(section):
|
| 330 |
return get_user_guide_section(section)
|
| 331 |
|
|
|
|
| 335 |
ug_memory_line.click(lambda: show_guide("memory_line"), outputs=result_display)
|
| 336 |
|
| 337 |
if __name__ == "__main__":
|
| 338 |
+
# 【修正】:allowed_paths 必须放在 launch() 中
|
| 339 |
+
demo.launch(allowed_paths=["."])
|