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"])