File size: 6,947 Bytes
404eda8 4044773 1df899f 404eda8 f253795 d247393 4044773 f253795 9109b74 f253795 9109b74 d247393 f253795 d247393 f253795 9109b74 e351eeb 9109b74 e351eeb 9109b74 e351eeb 9109b74 f253795 ac5b826 1df899f f253795 4044773 1df899f 4044773 ac5b826 d247393 a1df044 d247393 ac5b826 d247393 ac5b826 d247393 ac5b826 4044773 ac5b826 4044773 d247393 ac5b826 4044773 ac5b826 4044773 e351eeb 4044773 f253795 4044773 f253795 ac5b826 4044773 d247393 4044773 ac5b826 4044773 d247393 4044773 ac5b826 4044773 f253795 d247393 4044773 e351eeb d247393 f253795 d247393 f253795 d247393 4044773 d247393 e351eeb d247393 4044773 d247393 4044773 f253795 d247393 f253795 ddcc970 f253795 d247393 f253795 d247393 4044773 f253795 e351eeb 4044773 f253795 4044773 f253795 4044773 f253795 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 | import streamlit as st
import google.generativeai as genai
import requests
import os
# 0. 頁面配置與 CSS 注入(隱藏側邊欄捲軸)
st.set_page_config(page_title="S.H.I.E.L.D. 戰情小助手", 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. 調整範例按鈕樣式 (改為科技藍風格) */
.stButton button {
width: auto;
padding: 5px 15px;
border-radius: 20px;
border: 1px solid #58a6ff;
color: #58a6ff;
background-color: transparent;
transition: all 0.3s ease;
}
.stButton button:hover {
background-color: #58a6ff;
color: #0d1117;
}
/* 3. 極度壓縮頂部空白與兩側邊距,專為小視窗優化 */
.block-container {
padding-top: 1.5rem !important;
padding-bottom: 5rem !important; /* 底部留白避免對話被輸入框蓋住 */
padding-left: 1rem !important;
padding-right: 1rem !important;
}
/* 4. 隱藏 Streamlit 預設的頂部裝飾與漢堡選單 */
header {
visibility: hidden;
}
</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. 基礎設定與連結
# 抓取 Deep Learning 101 的 Logo (你也可以換成 SHIELD 專屬 Logo)
LOGO_URL = "https://huggingface.co/spaces/DeepLearning101/shield-chatbot/resolve/main/shield-logo.jpg"
HOME_URL = "https://deep-learning-101.github.io/SHIELD/"
# 將知識庫指向 S.H.I.E.L.D. 的 README.md
KNOWLEDGE_MAP = {
"🛡️ S.H.I.E.L.D. 系統白皮書": {
"raw_url": "https://raw.githubusercontent.com/Deep-Learning-101/SHIELD/main/README.md",
"page_url": "https://deep-learning-101.github.io/SHIELD/",
"repo_url": "https://github.com/Deep-Learning-101/SHIELD"
}
}
# 2. 批量抓取內容
def fetch_all_knowledge():
combined_knowledge = ""
with st.spinner("正在同步 S.H.I.E.L.D. 戰情資料庫..."):
for category, info in KNOWLEDGE_MAP.items():
try:
response = requests.get(info["raw_url"])
response.raise_for_status()
combined_knowledge += f"\n\n## 【領域:{category}】\n"
combined_knowledge += response.text
except Exception as e:
st.warning(f"無法同步 {category} 的資料:請確認 GitHub 路徑是否正確。錯誤訊息:{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.markdown(f'<a href="{HOME_URL}" target="_blank"><img src="{LOGO_URL}" width="100%" style="margin-bottom:20px;"></a>', unsafe_allow_html=True)
st.title("⚙️ 知識庫狀態")
for category, info in KNOWLEDGE_MAP.items():
with st.expander(category):
st.markdown(f"🔗 [瀏覽網頁]({info['page_url']})")
st.markdown(f"📂 [GitHub 原始碼]({info['repo_url']})")
st.markdown("---")
if st.button("🔄 手動更新情資庫"):
st.session_state.knowledge = fetch_all_knowledge()
st.success("資料已重新抓取!")
# 4. 主介面與範例問句
st.title("🤖 S.H.I.E.L.D. 戰情小助手")
st.caption("我是 Deep Learning 101 的主權 AI 戰情官,專注於解答 S.H.I.E.L.D. 的架構與防禦機制。")
# 顯示專屬範例問句按鈕
example_cols = st.columns(6)
examples = [
"🧠 傳統 AI 常有幻覺,雙腦架構如何落實 AI 治理?",
"🏭 企業機密文檔,如何無損轉化為 AI 微調燃料?",
"⚔️ 揭秘「紅藍隊自主對抗」與動態語意防火牆",
"🕸️ 知識圖譜發威:如何秒級推演受災爆炸半徑?",
"🚀 捨棄傳統向量庫?解析 S.H.I.E.L.D. 雙引擎檢索",
"🤖 從給建議到「自動修補」:Agent 如何執行 ChatOps?"
]
for col, ex in zip(example_cols, examples):
if col.button(ex):
st.session_state.example_prompt = ex
# 5. 模型回覆邏輯(設定資安 AI 架構師人設)
def get_gemini_response(user_input):
system_instruction = f"""
你現在是 Deep Learning 101 開發的『S.H.I.E.L.D. 戰情小助手』。
你的說話風格專業、精確,帶有資安專家與 AI 架構師的科技感,致力於推廣企業主權 AI 防禦理念。
以下是從 GitHub 同步的 S.H.I.E.L.D. 系統白皮書與技術架構資訊:
---
{st.session_state.knowledge}
---
請嚴格基於上述提供的資訊來回答使用者的問題。
如果使用者問了超出 S.H.I.E.L.D. 白皮書範圍的問題,請禮貌地告知:「目前的戰情資料庫尚未收錄此資訊,建議您查閱 Deep Learning 101 的其他專案或直接聯繫維護團隊。」
"""
try:
# 建議使用 1.5-flash,對於技術長文的理解力較強
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目前 API 請求已達上限,戰情中心通訊稍有延遲!請稍等幾分鐘後再試。"
else:
return f"❌ **發生預期外錯誤**\n\n訊息:{error_msg}"
# 6. 對話邏輯
prompt = st.chat_input("請輸入您對 S.H.I.E.L.D. 系統的疑問...")
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"]) |