Ronaldo1111 commited on
Commit
e311330
·
verified ·
1 Parent(s): b42cb10

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +103 -37
app.py CHANGED
@@ -116,29 +116,54 @@ def hybrid_retrieval(query, corpus_docs, faiss_index, embedding_model, k=3, kw_w
116
  return [doc for _, doc in scored_docs[:k]]
117
 
118
  # ========= Step 6: 聊天函数 =========
 
 
 
 
 
 
 
 
 
 
 
 
 
119
  def chat(user_input, history):
120
  history = history or []
121
- context_text = "\n".join([f"用户:{msg['content']}" if msg["role"] == "user" else f"sophia:{msg['content']}" for msg in history])
122
 
123
- # 检索合并后的 corpus knowledge 文档
 
 
 
 
 
 
 
 
 
 
 
 
124
  retrieved_docs = hybrid_retrieval(
125
- query=user_input,
126
- corpus_docs=all_docs, # 使用 all_docs(包括 knowledge)进行检索
127
  faiss_index=index,
128
  embedding_model=embedding_model,
129
  k=3
130
  )
131
  retrieved_context = "\n".join([doc.page_content for doc in retrieved_docs])
132
 
133
- # 从对话集中取风格示例
134
  example_pairs = dialog_data[:5]
135
  example_text = "\n".join([f"user:{pair['user']}\nsophia:{pair['sophia']}" for pair in example_pairs])
136
 
 
137
  prompt = prompt_template.format(
138
  system=system_prompt,
139
  examples=example_text,
140
  context=retrieved_context + "\n" + context_text,
141
- question=user_input
142
  )
143
 
144
  try:
@@ -146,12 +171,17 @@ def chat(user_input, history):
146
  except Exception as e:
147
  reply = f"哎呀出错了:{str(e)}"
148
 
 
149
  history.append({"role": "user", "content": user_input})
150
  history.append({"role": "assistant", "content": reply})
 
151
  return history, history
152
 
153
- import gradio as gr
154
 
 
 
 
 
155
  # === 背景图与音乐 URL ===
156
  background_images = [
157
  "https://huggingface.co/spaces/Ronaldo1111/Sophia/resolve/main/family.jpg",
@@ -168,7 +198,9 @@ background_images = [
168
  avatar_url = "https://huggingface.co/spaces/Ronaldo1111/Sophia/resolve/main/bean.jpg"
169
  music1 = "https://huggingface.co/spaces/Ronaldo1111/Sophia/resolve/main/FNG.mp3"
170
  music2 = "https://huggingface.co/spaces/Ronaldo1111/Sophia/resolve/main/PGY.mp3"
 
171
 
 
172
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
173
  gr.Markdown("# 🎀Horse And 7 Agent🎀")
174
  gr.Markdown("欢迎来到 **豌豆的家**,相信你也是马+7大家庭中的一员。我能在家里拉粑粑吗!💬")
@@ -178,64 +210,64 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
178
  state = gr.State([{"role": "assistant", "content": "勾巴,我是豌豆,你想聊啥?"}])
179
  btn = gr.Button("投喂")
180
 
181
- # 插入 CSS、背景图轮播、头像动画、聊天框美化、背景音乐播放
182
  gr.HTML(f"""
183
  <style>
184
  body {{
185
  margin: 0;
186
- animation: backgroundCycle 30s infinite;
187
  background-size: cover;
188
  background-position: center;
189
  transition: background-image 1s ease-in-out;
190
  }}
191
  @keyframes backgroundCycle {{
192
- 0% {{ background-image: url({background_images[0]}); }}
193
- 10% {{ background-image: url({background_images[1]}); }}
194
- 20% {{ background-image: url({background_images[2]}); }}
195
- 30% {{ background-image: url({background_images[3]}); }}
196
- 40% {{ background-image: url({background_images[4]}); }}
197
- 50% {{ background-image: url({background_images[5]}); }}
198
- 60% {{ background-image: url({background_images[6]}); }}
199
- 70% {{ background-image: url({background_images[7]}); }}
200
- 80% {{ background-image: url({background_images[8]}); }}
201
- 90% {{ background-image: url({background_images[9]}); }}
202
  }}
203
 
204
  .gr-chatbot {{
205
- background: linear-gradient(135deg, #fbd3e9, #bb377d);
206
- border-radius: 12px;
207
  padding: 10px;
208
  }}
209
 
210
  #sophia-avatar {{
211
  position: fixed;
212
- top: 10px;
213
- left: 10px;
214
- width: 60px;
215
- height: 60px;
216
  border-radius: 50%;
217
- animation: bounceSpin 4s infinite;
 
 
 
 
 
 
 
 
 
218
  z-index: 9999;
219
  }}
220
 
221
- @keyframes bounceSpin {{
222
- 0%, 100% {{ transform: translateY(0) rotate(0deg); }}
223
- 25% {{ transform: translateY(-10px) rotate(90deg); }}
224
- 50% {{ transform: translateY(0) rotate(180deg); }}
225
- 75% {{ transform: translateY(10px) rotate(270deg); }}
226
  }}
227
  </style>
228
 
229
  <img id="sophia-avatar" src="{avatar_url}" />
 
 
 
230
 
231
  <audio id="bg-music" autoplay loop>
232
  <source src="{music1}" type="audio/mpeg">
233
  <source src="{music2}" type="audio/mpeg">
234
- Your browser does not support the audio tag.
235
  </audio>
236
 
237
  <script>
238
- // 自动循环播放多首歌曲
239
  const musicList = ["{music1}", "{music2}"];
240
  let currentTrack = 0;
241
  const audio = document.getElementById("bg-music");
@@ -245,12 +277,46 @@ with gr.Blocks(theme=gr.themes.Soft()) as demo:
245
  audio.src = musicList[currentTrack];
246
  audio.play();
247
  }});
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
248
  </script>
249
  """)
250
-
251
- # 聊天逻辑按钮触发
252
- btn.click(chat, inputs=[msg, state], outputs=[chatbot, state])
253
- msg.submit(chat, inputs=[msg, state], outputs=[chatbot, state])
254
 
255
  demo.launch()
256
 
 
116
  return [doc for _, doc in scored_docs[:k]]
117
 
118
  # ========= Step 6: 聊天函数 =========
119
+ import random
120
+
121
+ # 新增:用于主动引导话题的 fallback 逻辑
122
+ def choose_fallback_topic(user_input, knowledge_docs):
123
+ if len(user_input.strip()) < 5:
124
+ candidates = [doc.page_content for doc in knowledge_docs if "?" in doc.page_content]
125
+ if not candidates:
126
+ candidates = [doc.page_content for doc in knowledge_docs]
127
+ if candidates:
128
+ return f"{user_input},{random.choice(candidates)}"
129
+ return user_input
130
+
131
+
132
  def chat(user_input, history):
133
  history = history or []
 
134
 
135
+ # 限制历史轮数,避免太长(最后 4 = 8 条 message)
136
+ history = history[-8:]
137
+
138
+ # ✅ 把用户输入和引导语拼起来
139
+ prompt_question = choose_fallback_topic(user_input, knowledge_docs)
140
+
141
+ # ✅ 格式化历史记录
142
+ context_text = "\n".join([
143
+ f"用户:{msg['content']}" if msg['role'] == "user" else f"sophia:{msg['content']}"
144
+ for msg in history
145
+ ])
146
+
147
+ # ✅ 语义+关键词混合检索,增强语境
148
  retrieved_docs = hybrid_retrieval(
149
+ query=prompt_question,
150
+ corpus_docs=all_docs,
151
  faiss_index=index,
152
  embedding_model=embedding_model,
153
  k=3
154
  )
155
  retrieved_context = "\n".join([doc.page_content for doc in retrieved_docs])
156
 
157
+ # ✅ 随机选几条风格示例拼到 Prompt
158
  example_pairs = dialog_data[:5]
159
  example_text = "\n".join([f"user:{pair['user']}\nsophia:{pair['sophia']}" for pair in example_pairs])
160
 
161
+ # ✅ 构造 Prompt
162
  prompt = prompt_template.format(
163
  system=system_prompt,
164
  examples=example_text,
165
  context=retrieved_context + "\n" + context_text,
166
+ question=prompt_question
167
  )
168
 
169
  try:
 
171
  except Exception as e:
172
  reply = f"哎呀出错了:{str(e)}"
173
 
174
+ # ✅ 更新对话历史(按 OpenAI 风格)
175
  history.append({"role": "user", "content": user_input})
176
  history.append({"role": "assistant", "content": reply})
177
+
178
  return history, history
179
 
 
180
 
181
+
182
+ import gradio as gr
183
+ import gradio as gr
184
+ import os
185
  # === 背景图与音乐 URL ===
186
  background_images = [
187
  "https://huggingface.co/spaces/Ronaldo1111/Sophia/resolve/main/family.jpg",
 
198
  avatar_url = "https://huggingface.co/spaces/Ronaldo1111/Sophia/resolve/main/bean.jpg"
199
  music1 = "https://huggingface.co/spaces/Ronaldo1111/Sophia/resolve/main/FNG.mp3"
200
  music2 = "https://huggingface.co/spaces/Ronaldo1111/Sophia/resolve/main/PGY.mp3"
201
+ cake_url = "https://huggingface.co/spaces/Ronaldo1111/Sophia/resolve/main/birthday.jpg"
202
 
203
+ # ==== Gradio 页面 ====
204
  with gr.Blocks(theme=gr.themes.Soft()) as demo:
205
  gr.Markdown("# 🎀Horse And 7 Agent🎀")
206
  gr.Markdown("欢迎来到 **豌豆的家**,相信你也是马+7大家庭中的一员。我能在家里拉粑粑吗!💬")
 
210
  state = gr.State([{"role": "assistant", "content": "勾巴,我是豌豆,你想聊啥?"}])
211
  btn = gr.Button("投喂")
212
 
213
+ # === 页面美化部分 ===
214
  gr.HTML(f"""
215
  <style>
216
  body {{
217
  margin: 0;
218
+ animation: backgroundCycle 60s infinite;
219
  background-size: cover;
220
  background-position: center;
221
  transition: background-image 1s ease-in-out;
222
  }}
223
  @keyframes backgroundCycle {{
224
+ {''.join([f"{i*10}% {{ background-image: url({img}); }}\n" for i, img in enumerate(background_images)])}
 
 
 
 
 
 
 
 
 
225
  }}
226
 
227
  .gr-chatbot {{
228
+ background: rgba(255, 255, 255, 0.5); /* 半透明 */
229
+ border-radius: 16px;
230
  padding: 10px;
231
  }}
232
 
233
  #sophia-avatar {{
234
  position: fixed;
235
+ top: 60px;
236
+ left: 30px;
237
+ width: 80px;
238
+ height: 80px;
239
  border-radius: 50%;
240
+ z-index: 9999;
241
+ cursor: move;
242
+ }}
243
+
244
+ #birthday-cake {{
245
+ position: fixed;
246
+ bottom: 10px;
247
+ right: 10px;
248
+ width: 80px;
249
+ animation: bounce 2s infinite ease-in-out alternate;
250
  z-index: 9999;
251
  }}
252
 
253
+ @keyframes bounce {{
254
+ 0% {{ transform: translateY(0px); }}
255
+ 100% {{ transform: translateY(-20px); }}
 
 
256
  }}
257
  </style>
258
 
259
  <img id="sophia-avatar" src="{avatar_url}" />
260
+ <img id="birthday-cake" src="{cake_url}" />
261
+
262
+ <canvas id="fireworks" style="position:fixed; top:0; left:0; width:100vw; height:100vh; pointer-events:none; z-index:999;"></canvas>
263
 
264
  <audio id="bg-music" autoplay loop>
265
  <source src="{music1}" type="audio/mpeg">
266
  <source src="{music2}" type="audio/mpeg">
 
267
  </audio>
268
 
269
  <script>
270
+ // 音乐自动切换
271
  const musicList = ["{music1}", "{music2}"];
272
  let currentTrack = 0;
273
  const audio = document.getElementById("bg-music");
 
277
  audio.src = musicList[currentTrack];
278
  audio.play();
279
  }});
280
+
281
+ // 拖动头像
282
+ const avatar = document.getElementById("sophia-avatar");
283
+ avatar.onmousedown = function(e) {{
284
+ const offsetX = e.clientX - avatar.offsetLeft;
285
+ const offsetY = e.clientY - avatar.offsetTop;
286
+ function move(e) {{
287
+ avatar.style.left = (e.clientX - offsetX) + 'px';
288
+ avatar.style.top = (e.clientY - offsetY) + 'px';
289
+ }}
290
+ document.addEventListener('mousemove', move);
291
+ document.addEventListener('mouseup', () => {{
292
+ document.removeEventListener('mousemove', move);
293
+ }}, {{ once: true }});
294
+ }};
295
+
296
+ // 简易烟花(伪特效)
297
+ const canvas = document.getElementById("fireworks");
298
+ const ctx = canvas.getContext("2d");
299
+ canvas.width = window.innerWidth;
300
+ canvas.height = window.innerHeight;
301
+
302
+ function firework() {{
303
+ const x = Math.random() * canvas.width;
304
+ const y = Math.random() * canvas.height;
305
+ for (let i = 0; i < 30; i++) {{
306
+ setTimeout(() => {{
307
+ ctx.beginPath();
308
+ ctx.arc(x, y, Math.random() * 3 + 2, 0, Math.PI * 2);
309
+ ctx.fillStyle = `hsl(${Math.random() * 360}, 100%, 60%)`;
310
+ ctx.fill();
311
+ }}, i * 20);
312
+ }}
313
+ }}
314
+ setInterval(firework, 1500);
315
  </script>
316
  """)
317
+ # === 按钮绑定 ===
318
+ btn.click(chat_with_log, inputs=[msg, state], outputs=[chatbot, state])
319
+ msg.submit(chat_with_log, inputs=[msg, state], outputs=[chatbot, state])
 
320
 
321
  demo.launch()
322