AlauStone commited on
Commit
9e87f5a
·
verified ·
1 Parent(s): df8e3ca

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +62 -19
app.py CHANGED
@@ -30,6 +30,38 @@ st.set_page_config(page_title="智答 AI 助手", page_icon="🤖", layout="wide
30
  def _get_custom_css():
31
  return """
32
  <style>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  [data-testid="stSidebarContent"] { padding-top: 1.5rem !important; }
34
  [data-testid="stVerticalBlock"] > div { gap: 0.2rem !important; }
35
  /* 聊天消息间距控制 */
@@ -143,7 +175,7 @@ def _get_custom_css():
143
  left: 0 !important;
144
  right: 0 !important;
145
  z-index: 9999 !important;
146
- background: white !important;
147
  padding: 0.3rem 1rem !important;
148
  }
149
 
@@ -156,7 +188,7 @@ def _get_custom_css():
156
  width: calc(100% - 2rem) !important;
157
  max-width: 730px !important;
158
  z-index: 9999 !important;
159
- background: white !important;
160
  }
161
  /* 搜索框聚焦时去掉红色边框 */
162
  [data-testid="stChatInput"] textarea:focus,
@@ -166,8 +198,8 @@ def _get_custom_css():
166
  box-shadow: none !important;
167
  }
168
 
169
- /* 底部工具栏固定在搜索框下方 */
170
- .stMainBlockContainer > div > div > div:has([data-testid="stPopover"]) {
171
  position: fixed !important;
172
  bottom: 0.3rem !important;
173
  left: 50% !important;
@@ -176,17 +208,17 @@ def _get_custom_css():
176
  max-width: 730px !important;
177
  z-index: 9998 !important;
178
  }
179
- .stMainBlockContainer > div > div > div:has([data-testid="stPopover"]) [data-testid="stHorizontalBlock"] {
180
  display: flex !important;
181
  flex-wrap: nowrap !important;
182
  gap: 0.5rem !important;
183
  }
184
- .stMainBlockContainer > div > div > div:has([data-testid="stPopover"]) [data-testid="stHorizontalBlock"] > div {
185
  flex: 1 !important;
186
  min-width: 0 !important;
187
  }
188
  /* 确保底部工具栏按钮占满容器宽度 */
189
- .stMainBlockContainer > div > div > div:has([data-testid="stPopover"]) [data-testid="stHorizontalBlock"] button {
190
  width: 100% !important;
191
  }
192
  /* popover 向上展开 */
@@ -197,21 +229,21 @@ def _get_custom_css():
197
  }
198
 
199
  /* 底部工具栏按钮:无边框风格,统一颜色 */
200
- .stMainBlockContainer > div > div > div:has([data-testid="stPopover"]) button,
201
- .stMainBlockContainer > div > div > div:has([data-testid="stPopover"]) [data-testid="stPopover"] > div:first-child {
202
  background: transparent !important;
203
  border: none !important;
204
  box-shadow: none !important;
205
  color: #666 !important;
206
  }
207
- .stMainBlockContainer > div > div > div:has([data-testid="stPopover"]) button:hover,
208
- .stMainBlockContainer > div > div > div:has([data-testid="stPopover"]) [data-testid="stPopover"] > div:first-child:hover {
209
  background: rgba(0,0,0,0.05) !important;
210
  }
211
- .stMainBlockContainer > div > div > div:has([data-testid="stPopover"]) button p,
212
- .stMainBlockContainer > div > div > div:has([data-testid="stPopover"]) button span,
213
- .stMainBlockContainer > div > div > div:has([data-testid="stPopover"]) [data-testid="stMarkdownContainer"] p,
214
- .stMainBlockContainer > div > div > div:has([data-testid="stPopover"]) [data-testid="stPopover"] p {
215
  color: #666 !important;
216
  }
217
 
@@ -951,6 +983,12 @@ SYSTEM_PROMPT_WEB = (
951
  "回答要简洁实用,注明信息来源。"
952
  )
953
 
 
 
 
 
 
 
954
 
955
  def web_search(query):
956
  if not TAVILY_KEY:
@@ -1462,7 +1500,7 @@ def search_local(query, top_k, threshold):
1462
  # =========================
1463
  # 9. LLM 回答逻辑
1464
  # =========================
1465
- def llm_answer(query, context_docs, selected_display_name, web_enabled):
1466
  all_context = ""
1467
  curr_time = datetime.now().strftime("%Y-%m-%d %H:%M")
1468
 
@@ -1472,10 +1510,13 @@ def llm_answer(query, context_docs, selected_display_name, web_enabled):
1472
  all_context = f"【互联网搜索结果】:\n{search_res}"
1473
  prompt_content = f"当前时间:{curr_time}\n\n{all_context[:6500]}\n\n用户问题:{query}"
1474
  system_prompt = SYSTEM_PROMPT_WEB
 
 
 
 
1475
  else:
1476
  # 知识库模式:用知识库资料
1477
- if context_docs:
1478
- all_context = "【知识库资料】:\n" + "\n".join(context_docs)
1479
  prompt_content = f"当前时间:{curr_time}\n\n参考资料:\n{all_context[:6500]}\n\n用户问题:{query}"
1480
  system_prompt = SYSTEM_PROMPT
1481
 
@@ -1677,7 +1718,7 @@ def _chat_fragment():
1677
 
1678
  try:
1679
  full_response = response_container.write_stream(
1680
- llm_answer(q, relevant_docs, _model_name, _web_on)
1681
  )
1682
  meta_info = st.session_state.get("last_meta", "")
1683
  # meta 拼进 response_container,不创建独立DOM元素
@@ -1701,6 +1742,8 @@ def _chat_fragment():
1701
  # =========================
1702
  @st.fragment
1703
  def _toolbar_fragment():
 
 
1704
  _current_model = st.session_state.get("sel_model", list(model_mapping.keys())[0])
1705
  _web_status = st.session_state.get("sel_web", True)
1706
  _model_short = _current_model.split("(")[0].strip()
 
30
  def _get_custom_css():
31
  return """
32
  <style>
33
+ /* 暗色模式适配 */
34
+ @media (prefers-color-scheme: dark) {
35
+ .main-title {
36
+ background: #0e1117 !important;
37
+ }
38
+ [data-testid="stChatInput"] {
39
+ background: #0e1117 !important;
40
+ }
41
+ /* 暗色模式下快捷问题按钮颜色 */
42
+ .block-container:has(.welcome-marker) [data-testid="stBaseButton-secondary"]:hover {
43
+ background: rgba(255,255,255,0.1) !important;
44
+ }
45
+ /* 暗色模式下工具栏按钮 hover */
46
+ .stMainBlockContainer > div > div > div:has(.toolbar-marker) button:hover {
47
+ background: rgba(255,255,255,0.1) !important;
48
+ }
49
+ }
50
+ /* Streamlit 暗色主题适配 */
51
+ [data-theme="dark"] .main-title,
52
+ .stApp[data-theme="dark"] .main-title {
53
+ background: #0e1117 !important;
54
+ }
55
+ [data-theme="dark"] [data-testid="stChatInput"],
56
+ .stApp[data-theme="dark"] [data-testid="stChatInput"] {
57
+ background: #0e1117 !important;
58
+ }
59
+
60
+ /* 隐藏工具栏标记 */
61
+ .toolbar-marker {
62
+ display: none !important;
63
+ }
64
+
65
  [data-testid="stSidebarContent"] { padding-top: 1.5rem !important; }
66
  [data-testid="stVerticalBlock"] > div { gap: 0.2rem !important; }
67
  /* 聊天消息间距控制 */
 
175
  left: 0 !important;
176
  right: 0 !important;
177
  z-index: 9999 !important;
178
+ background: var(--background-color, white) !important;
179
  padding: 0.3rem 1rem !important;
180
  }
181
 
 
188
  width: calc(100% - 2rem) !important;
189
  max-width: 730px !important;
190
  z-index: 9999 !important;
191
+ background: var(--background-color, white) !important;
192
  }
193
  /* 搜索框聚焦时去掉红色边框 */
194
  [data-testid="stChatInput"] textarea:focus,
 
198
  box-shadow: none !important;
199
  }
200
 
201
+ /* 底部工具栏固定在搜索框下方 - 使用 toolbar-marker 精确定位 */
202
+ .stMainBlockContainer > div > div > div:has(.toolbar-marker) {
203
  position: fixed !important;
204
  bottom: 0.3rem !important;
205
  left: 50% !important;
 
208
  max-width: 730px !important;
209
  z-index: 9998 !important;
210
  }
211
+ .stMainBlockContainer > div > div > div:has(.toolbar-marker) [data-testid="stHorizontalBlock"] {
212
  display: flex !important;
213
  flex-wrap: nowrap !important;
214
  gap: 0.5rem !important;
215
  }
216
+ .stMainBlockContainer > div > div > div:has(.toolbar-marker) [data-testid="stHorizontalBlock"] > div {
217
  flex: 1 !important;
218
  min-width: 0 !important;
219
  }
220
  /* 确保底部工具栏按钮占满容器宽度 */
221
+ .stMainBlockContainer > div > div > div:has(.toolbar-marker) [data-testid="stHorizontalBlock"] button {
222
  width: 100% !important;
223
  }
224
  /* popover 向上展开 */
 
229
  }
230
 
231
  /* 底部工具栏按钮:无边框风格,统一颜色 */
232
+ .stMainBlockContainer > div > div > div:has(.toolbar-marker) button,
233
+ .stMainBlockContainer > div > div > div:has(.toolbar-marker) [data-testid="stPopover"] > div:first-child {
234
  background: transparent !important;
235
  border: none !important;
236
  box-shadow: none !important;
237
  color: #666 !important;
238
  }
239
+ .stMainBlockContainer > div > div > div:has(.toolbar-marker) button:hover,
240
+ .stMainBlockContainer > div > div > div:has(.toolbar-marker) [data-testid="stPopover"] > div:first-child:hover {
241
  background: rgba(0,0,0,0.05) !important;
242
  }
243
+ .stMainBlockContainer > div > div > div:has(.toolbar-marker) button p,
244
+ .stMainBlockContainer > div > div > div:has(.toolbar-marker) button span,
245
+ .stMainBlockContainer > div > div > div:has(.toolbar-marker) [data-testid="stMarkdownContainer"] p,
246
+ .stMainBlockContainer > div > div > div:has(.toolbar-marker) [data-testid="stPopover"] p {
247
  color: #666 !important;
248
  }
249
 
 
983
  "回答要简洁实用,注明信息来源。"
984
  )
985
 
986
+ SYSTEM_PROMPT_DIRECT = (
987
+ "你是一个智能AI助手,请直接根据你的知识回答用户问题。"
988
+ "回答要准确、有条理、简洁实用。"
989
+ "如果不确定某些信息,请诚实说明。"
990
+ )
991
+
992
 
993
  def web_search(query):
994
  if not TAVILY_KEY:
 
1500
  # =========================
1501
  # 9. LLM 回答逻辑
1502
  # =========================
1503
+ def llm_answer(query, context_docs, selected_display_name, web_enabled, is_guest=False):
1504
  all_context = ""
1505
  curr_time = datetime.now().strftime("%Y-%m-%d %H:%M")
1506
 
 
1510
  all_context = f"【互联网搜索结果】:\n{search_res}"
1511
  prompt_content = f"当前时间:{curr_time}\n\n{all_context[:6500]}\n\n用户问题:{query}"
1512
  system_prompt = SYSTEM_PROMPT_WEB
1513
+ elif is_guest or not context_docs:
1514
+ # 直接回答模式(游客不联网 或 登录用户无知识库资料)
1515
+ prompt_content = f"当前时间:{curr_time}\n\n用户问题:{query}"
1516
+ system_prompt = SYSTEM_PROMPT_DIRECT
1517
  else:
1518
  # 知识库模式:用知识库资料
1519
+ all_context = "【知识库资料】:\n" + "\n".join(context_docs)
 
1520
  prompt_content = f"当前时间:{curr_time}\n\n参考资料:\n{all_context[:6500]}\n\n用户问题:{query}"
1521
  system_prompt = SYSTEM_PROMPT
1522
 
 
1718
 
1719
  try:
1720
  full_response = response_container.write_stream(
1721
+ llm_answer(q, relevant_docs, _model_name, _web_on, IS_GUEST)
1722
  )
1723
  meta_info = st.session_state.get("last_meta", "")
1724
  # meta 拼进 response_container,不创建独立DOM元素
 
1742
  # =========================
1743
  @st.fragment
1744
  def _toolbar_fragment():
1745
+ # 添加工具栏标记,用于 CSS 精确定位
1746
+ st.markdown('<div class="toolbar-marker"></div>', unsafe_allow_html=True)
1747
  _current_model = st.session_state.get("sel_model", list(model_mapping.keys())[0])
1748
  _web_status = st.session_state.get("sel_web", True)
1749
  _model_short = _current_model.split("(")[0].strip()