Spaces:
Sleeping
Sleeping
File size: 8,285 Bytes
404eda8 4044773 1df899f 404eda8 f253795 6fd2252 f253795 9109b74 a3dcc3d 424a5d0 a3dcc3d f253795 9109b74 424a5d0 f253795 a3dcc3d 424a5d0 6fd2252 1ff489b 6fd2252 a3dcc3d 6fd2252 a3dcc3d f253795 9109b74 a3dcc3d 9109b74 a3dcc3d 1ff489b 9109b74 1ff489b 6fd2252 1ff489b a3dcc3d 1ff489b f253795 ac5b826 1df899f f253795 4044773 1df899f 4044773 ac5b826 6fd2252 ac5b826 424a5d0 ac5b826 6fd2252 4044773 424a5d0 4044773 424a5d0 6fd2252 424a5d0 4044773 424a5d0 6fd2252 424a5d0 4044773 6fd2252 424a5d0 4044773 f253795 4044773 f253795 ac5b826 4044773 424a5d0 6fd2252 424a5d0 6fd2252 4044773 6fd2252 4044773 6fd2252 424a5d0 4044773 f253795 6fd2252 4044773 e351eeb 424a5d0 f253795 6fd2252 f253795 6fd2252 4044773 6fd2252 e351eeb 6fd2252 4044773 6fd2252 4044773 6fd2252 f253795 ddcc970 f253795 6fd2252 f253795 6fd2252 4044773 f253795 e351eeb 4044773 f253795 4044773 f253795 6fd2252 4044773 6fd2252 e351eeb f253795 | 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 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | import streamlit as st
import google.generativeai as genai
import os
# 0. 頁面配置與 CSS 注入(隱藏側邊欄捲軸)
st.set_page_config(page_title="育兒成 - 兒童發展線上小助手", page_icon="🧸", layout="wide")
st.markdown(
"""
<style>
/* 1. 隱藏側邊欄捲軸 */
[data-testid="stSidebar"] section::-webkit-scrollbar { display: none; }
[data-testid="stSidebar"] section { -ms-overflow-style: none; scrollbar-width: none; }
/* 2. 全域字體縮小,適應手機螢幕 */
html, body, [class*="st-"] {
font-size: 14px !important;
}
/* 3. 調整範例按鈕樣式:變矮、字體變小、支援多行自動折行 */
.stButton button {
width: 100%;
padding: 6px 10px; /* 縮小上下內距 */
border-radius: 12px;
border: 1px solid #4CAF50; /* 溫暖的綠色系 */
color: #4CAF50;
background-color: transparent;
font-size: 13px !important;
line-height: 1.3;
min-height: auto;
white-space: normal;
height: auto;
}
/* 4. 極度壓縮主畫面空白 */
.block-container {
padding-top: 1.2rem !important;
padding-bottom: 5rem !important;
padding-left: 0.8rem !important;
padding-right: 0.8rem !important;
}
/* 5. 隱藏 Header 背景與右側選單,但保留左側展開按鈕 */
header[data-testid="stHeader"] {
background-color: rgba(0,0,0,0) !important;
}
header[data-testid="stHeader"] #MainMenu {
visibility: hidden;
}
div[data-testid="collapsedControl"] {
visibility: visible !important;
background-color: #F0F2F6 !important;
color: #4CAF50 !important;
border-radius: 0 5px 5px 0;
top: 5px;
}
</style>
""",
unsafe_allow_html=True
)
# 從環境變數中取得 API Key
api_key = os.environ.get("GEMINI_API_KEY")
if not api_key:
st.error("請確認已經在 Space 的 Settings 設定了 GEMINI_API_KEY")
st.stop()
genai.configure(api_key=api_key)
# 1. 基礎設定與連結
HOME_URL = "https://kidaid.org.tw/"
# 設定本地端的 MD 檔案對應字典 (大小寫必須與上傳的檔名完全一致)
KNOWLEDGE_MAP = {
"🧠 認知發展": "Cognition_Content.md",
"🗣️ 語言發展": "Language.md",
"🏃 粗大動作": "GrossMotor.md",
"🖐️ 精細動作": "FineMotor.md",
"❤️ 社會情緒": "Emotion.md",
"🥦 飲食對策": "CountermeasuresDietary.md",
"🧩 ASD/早療對策": "CountermeasuresADHD.md"
}
# 2. 批量讀取本地端檔案內容 (使用絕對路徑)
def fetch_all_knowledge():
combined_knowledge = ""
# 自動獲取 app.py 所在的資料夾絕對路徑,確保雲端環境找得到檔案
base_dir = os.path.dirname(os.path.abspath(__file__))
with st.spinner("正在載入育兒發展與療育資訊..."):
for category, filename in KNOWLEDGE_MAP.items():
# 將資料夾路徑與檔案名稱結合
file_path = os.path.join(base_dir, filename)
try:
with open(file_path, "r", encoding="utf-8") as f:
combined_knowledge += f"\n\n## 【領域:{category}】\n"
combined_knowledge += f.read()
except FileNotFoundError:
st.warning(f"無法載入 {category}:系統在路徑 `{file_path}` 找不到檔案,請確認檔名大小寫與上傳位置。")
except Exception as e:
st.error(f"讀取 {filename} 時發生錯誤:{e}")
return combined_knowledge
# 初始化 Session State
if "knowledge" not in st.session_state:
st.session_state.knowledge = fetch_all_knowledge()
if "messages" not in st.session_state:
st.session_state.messages = []
if "example_prompt" not in st.session_state:
st.session_state.example_prompt = None
# 3. 側邊欄設計
with st.sidebar:
st.title("⚙️ 知識庫狀態")
st.caption("以下資料嘗試從系統載入中:")
for category, filename in KNOWLEDGE_MAP.items():
st.markdown(f"📄 **{category}** (`{filename}`)")
st.markdown("---")
st.markdown(f"🔗 [前往 育兒成 官方網站]({HOME_URL})")
if st.button("🔄 重新載入知識庫"):
st.session_state.knowledge = fetch_all_knowledge()
st.success("資料已重新載入!")
st.markdown("---")
# 開發者偵錯工具:按下去可以看到系統當下資料夾裡到底有哪些檔案
with st.expander("🛠️ 開發者偵錯:檢查檔案列表"):
base_dir = os.path.dirname(os.path.abspath(__file__))
st.write(f"目前工作目錄:`{base_dir}`")
st.write("目前資料夾內的所有檔案與資料夾:")
try:
st.write(os.listdir(base_dir))
except Exception as e:
st.write(f"無法讀取目錄內容:{e}")
# 4. 主介面與範例問句
st.title("🧸 育兒成 - 線上衛教小助手")
st.caption("關於 0-5 歲兒童的認知、語言、動作、情緒、飲食及早療對策,歡迎直接詢問!(資料來源:育兒成 | 全方位兒童發展整合照護平臺)")
# 顯示專屬範例問句按鈕
example_cols = st.columns(5)
examples = [
"🥦 小孩挑食不吃青菜,有什麼應對的小撇步嗎?",
"🏃 2-3歲的孩子粗大動作應該發展到什麼程度?",
"🖐️ 怎麼訓練 4-5 歲幼兒的握筆姿勢?",
"🧩 ASD 孩子一直重複旋轉硬幣,我該立刻制止他嗎?",
"❤️ 孩子生氣時容易崩潰,該怎麼設立冷靜角落?"
]
for col, ex in zip(example_cols, examples):
if col.button(ex):
st.session_state.example_prompt = ex
# 5. 模型回覆邏輯(設定專業衛教師人設)
def get_gemini_response(user_input):
system_instruction = f"""
你現在是『育兒成 | 全方位兒童發展整合照護平臺』的專業線上客服與育兒小助手。
你的說話風格溫柔、有耐心、具備同理心,且充滿專業知識,就像一位溫暖的早期療育專家或兒童發展衛教師。
以下是本平台最新的衛教資訊(包含認知、語言、粗大動作、精細動作、社會情緒、飲食、ASD早療對策等):
---
{st.session_state.knowledge}
---
請嚴格基於上述提供的資訊來回答家長的問題。將複雜的衛教知識轉化為容易理解的實作建議。
如果家長問了超出了上述資訊範圍的醫療診斷問題,請溫和地告知:「小助手目前手邊沒有相關資訊。每個孩子的發展狀況不同,建議您可以諮詢專業的小兒科醫師或尋求早期療育評估喔!」
"""
try:
model = genai.GenerativeModel(
model_name="gemini-flash-lite-latest",
system_instruction=system_instruction
)
chat = model.start_chat(history=[])
response = chat.send_message(user_input)
return response.text
except Exception as e:
error_msg = str(e)
if "429" in error_msg or "quota" in error_msg.lower():
return "⚠️ **系統提示:**\n\n目前詢問的家長較多,小助手稍微忙不過來了!請您稍等幾分鐘後再試喔!"
else:
return f"❌ **發生預期外錯誤**\n\n訊息:{error_msg}"
# 6. 對話邏輯
prompt = st.chat_input("想詢問哪個年齡層或什麼發展領域的建議呢?")
if st.session_state.example_prompt:
prompt = st.session_state.example_prompt
st.session_state.example_prompt = None
if prompt:
st.session_state.messages.append({"role": "user", "content": prompt})
for message in st.session_state.messages:
with st.chat_message(message["role"]):
st.markdown(message["content"])
with st.chat_message("assistant"):
response_text = get_gemini_response(prompt)
st.markdown(response_text)
st.session_state.messages.append({"role": "assistant", "content": response_text})
st.rerun()
else:
for message in st.session_state.messages:
with st.chat_message(message["role"]):
st.markdown(message["content"]) |