Spaces:
Running
Running
File size: 6,293 Bytes
1a2b0fa a3b49e8 684c8a3 f899746 4abc17c 1a2b0fa a3b49e8 1a2b0fa a3b49e8 1a2b0fa a3b49e8 1a2b0fa a3b49e8 1a2b0fa a3b49e8 1a2b0fa a3b49e8 1a2b0fa 684c8a3 1a2b0fa 684c8a3 1a2b0fa a3b49e8 1a2b0fa a3b49e8 1a2b0fa a3b49e8 1a2b0fa 4abc17c 684c8a3 f899746 684c8a3 f899746 684c8a3 f899746 684c8a3 4abc17c |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
# 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 |