Marco310's picture
fix: Import .md
f899746
raw
history blame
6.29 kB
# ui/components/modals.py
import gradio as gr
from config import MODEL_OPTIONS, DEFAULT_PROVIDER, DEFAULT_MODEL, GROQ_FAST_MODEL_OPTIONS
from config import BASE_DIR
import re
def create_validated_input(label, placeholder, type="password"):
"""
Helper: 創建自動驗證的輸入框組件 (無按鈕版)
回傳: (textbox, status_markdown)
"""
with gr.Group():
key_input = gr.Textbox(
label=label,
placeholder=placeholder,
type=type,
elem_classes="modern-input"
)
# 狀態訊息預設為空,驗證後顯示
status_output = gr.Markdown(value="", elem_classes="api-status-msg")
return key_input, status_output
def create_settings_modal():
with gr.Group(visible=False, elem_classes="modal-overlay", elem_id="settings-modal") as modal:
with gr.Group(elem_classes="modal-box"):
with gr.Row(elem_classes="modal-header"):
gr.Markdown("### ⚙️ Hybrid System Configuration", elem_classes="modal-title")
with gr.Column(elem_classes="modal-content"):
with gr.Tabs():
# === 1. Services ===
with gr.TabItem("🌍 Services"):
gr.Markdown("External services for maps and weather.", elem_classes="tab-desc")
# 🔥 使用新 Helper (沒有按鈕了)
g_key, g_stat = create_validated_input("Google Maps Key", "AIza...")
w_key, w_stat = create_validated_input("OpenWeather Key", "Enter key...")
# === 2. Primary Brain ===
with gr.TabItem("🧠 Primary Brain"):
gr.Markdown("Select the main intelligence.", elem_classes="tab-desc")
# 這裡佈局稍微調整,把 Key 單獨放一行,比較乾淨
llm_provider = gr.Dropdown(
choices=list(MODEL_OPTIONS.keys()),
value=DEFAULT_PROVIDER,
label="Main Provider",
interactive=True,
elem_classes="modern-dropdown"
)
# 主模型 Key
main_key, main_stat = create_validated_input("Main Model API Key", "sk-...")
model_sel = gr.Dropdown(
choices=MODEL_OPTIONS[DEFAULT_PROVIDER],
value=DEFAULT_MODEL,
label="Main Model",
interactive=True,
elem_classes="modern-dropdown"
)
# === 3. Acceleration ===
with gr.TabItem("⚡ Acceleration"):
gr.Markdown("Configure Groq for speed.", elem_classes="tab-desc")
fast_mode_chk = gr.Checkbox(
label="Enable Fast Sub-Mode",
value=False,
elem_classes="modern-checkbox"
)
groq_model_sel = gr.Dropdown(
choices=GROQ_FAST_MODEL_OPTIONS,
value=GROQ_FAST_MODEL_OPTIONS[0][1],
label="Model",
elem_classes="modern-dropdown",
visible = False # <--- 預設隱藏
)
# Groq Key
groq_key, groq_stat = create_validated_input("Groq API Key", "gsk_...")
# 手動設定初始狀態為隱藏 (Gradio 小技巧: 定義後再 update)
groq_key.visible = False
# 全局狀態
set_stat = gr.Markdown(value="", visible=True)
with gr.Row(elem_classes="modal-footer"):
close_btn = gr.Button("Cancel", variant="secondary", elem_classes="btn-cancel")
save_btn = gr.Button("💾 Save", variant="primary", elem_id="btn-save-config")
# 🔥 回傳清單變短了 (少了 4 個按鈕)
return (modal,
g_key, g_stat,
w_key, w_stat,
llm_provider, main_key, main_stat, model_sel,
fast_mode_chk, groq_model_sel, groq_key, groq_stat,
close_btn, save_btn, set_stat)
def create_doc_modal():
"""
創建文檔模態框
功能:自動讀取 README.md 並【強力過濾】YAML Front Matter
"""
readme_path = BASE_DIR / "README.md"
doc_content = ""
try:
if readme_path.exists():
with open(readme_path, "r", encoding="utf-8") as f:
raw_content = f.read()
# 🔥🔥🔥 [Regex 強力修正] 🔥🔥🔥
# 說明:
# ^---\s*\n -> 匹配開頭的 --- (允許後面有空白) 和 換行
# .*? -> 非貪婪匹配中間的所有內容 (包含換行)
# \n---\s*\n? -> 匹配結尾的換行 + --- + 結尾可能有的換行
# re.DOTALL -> 讓 . 可以匹配換行符號
# re.MULTILINE-> 讓 ^ 可以匹配檔案開頭
yaml_pattern = r"^---\s*\n.*?\n---\s*\n?"
# 使用 sub 將匹配到的 YAML 區塊替換為空字串
clean_content = re.sub(yaml_pattern, "", raw_content, count=1, flags=re.DOTALL | re.MULTILINE)
doc_content = clean_content.strip()
else:
doc_content = "## ⚠️ Documentation Not Found"
except Exception as e:
doc_content = f"## ❌ Error Loading Documentation\n\n{str(e)}"
with gr.Group(visible=False, elem_classes="modal-overlay", elem_id="doc-modal") as doc_modal:
with gr.Group(elem_classes="modal-box"):
with gr.Row(elem_classes="modal-header"):
gr.Markdown("### 📖 Documentation", elem_classes="modal-title")
with gr.Column(elem_classes="modal-content"):
gr.Markdown(doc_content)
with gr.Row(elem_classes="modal-footer"):
close_doc_btn = gr.Button("Close", variant="secondary", elem_classes="btn-cancel")
return doc_modal, close_doc_btn