Song commited on
Commit
b3c381d
·
1 Parent(s): 841b5e8
Files changed (1) hide show
  1. app.py +35 -8
app.py CHANGED
@@ -82,7 +82,7 @@ def estimate_tokens(messages: List[Dict[str, str]]) -> int:
82
  total += len(msg["content"].split()) * 1.3
83
  return int(total)
84
 
85
- # ---------- 網路搜尋(已修復相似度 bug) ----------
86
  def perform_web_search(query: str, max_results: int = 5) -> str:
87
  print(f"開始網路搜尋:查詢詞 = '{query}'")
88
  try:
@@ -113,7 +113,7 @@ def perform_web_search(query: str, max_results: int = 5) -> str:
113
 
114
  for i, (score, result) in enumerate(relevant_with_scores[:5], 1):
115
  print(f"結果 {i}: 標題='{result['title']}',相似度={score:.2f},來源={result['url']}")
116
- search_summary += f"{i}. [{score:.2f}] {result['title']}\n {result['content'][:300]}...\n 來源: {result['url']}\n\n"
117
 
118
  return search_summary
119
 
@@ -135,7 +135,7 @@ class ChatPipeline:
135
  )
136
 
137
  @retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=4, max=10))
138
- def _llm_call(self, messages: List[Dict[str, str]]) -> str:
139
  token_est = estimate_tokens(messages)
140
  if token_est > 50000:
141
  raise ValueError("輸入過長")
@@ -143,13 +143,31 @@ class ChatPipeline:
143
  response = self.llm_client.chat.completions.create(
144
  model=LLM_MODEL_CONFIG["model"],
145
  messages=messages,
146
- max_tokens=LLM_MODEL_CONFIG["max_tokens"],
147
  temperature=LLM_MODEL_CONFIG["temperature"],
148
  seed=LLM_MODEL_CONFIG["seed"],
149
  timeout=30.0,
150
  )
151
  return response.choices[0].message.content or ""
152
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
153
  def get_conversation_history(self, user_id: str) -> List[Dict[str, str]]:
154
  return conversations.get(user_id, [])
155
 
@@ -165,23 +183,32 @@ class ChatPipeline:
165
  self.clear_conversation_history(user_id)
166
  return "對話紀錄已清除!現在開始新的對話。"
167
 
168
- search_results = perform_web_search(user_text)
169
-
170
  history = self.get_conversation_history(user_id)
 
 
 
 
 
 
 
 
 
171
  messages = [{"role": "system", "content": SYSTEM_PROMPT}]
172
  messages.extend(history)
173
  messages.append({"role": "user", "content": user_text})
174
 
175
- if "沒有找到" not in search_results:
176
- messages.append({"role": "system", "content": f"網路搜尋結果:{search_results}"})
177
 
178
  response = self._llm_call(messages)
179
  response = response.replace('*', '')
180
 
 
181
  history.append({"role": "user", "content": user_text})
182
  history.append({"role": "assistant", "content": response})
183
  self.update_conversation_history(user_id, history)
184
 
 
185
  chunks = split_text_for_line(response)
186
  if len(chunks) > 5:
187
  summary_prompt = [
 
82
  total += len(msg["content"].split()) * 1.3
83
  return int(total)
84
 
85
+ # ---------- 網路搜尋 ----------
86
  def perform_web_search(query: str, max_results: int = 5) -> str:
87
  print(f"開始網路搜尋:查詢詞 = '{query}'")
88
  try:
 
113
 
114
  for i, (score, result) in enumerate(relevant_with_scores[:5], 1):
115
  print(f"結果 {i}: 標題='{result['title']}',相似度={score:.2f},來源={result['url']}")
116
+ search_summary += f"{i}. [{score:.2f}] {result['title']}\n {result['content'][:400]}...\n 來源: {result['url']}\n\n"
117
 
118
  return search_summary
119
 
 
135
  )
136
 
137
  @retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=4, max=10))
138
+ def _llm_call(self, messages: List[Dict[str, str]], max_tokens: int = None) -> str:
139
  token_est = estimate_tokens(messages)
140
  if token_est > 50000:
141
  raise ValueError("輸入過長")
 
143
  response = self.llm_client.chat.completions.create(
144
  model=LLM_MODEL_CONFIG["model"],
145
  messages=messages,
146
+ max_tokens=max_tokens or LLM_MODEL_CONFIG["max_tokens"],
147
  temperature=LLM_MODEL_CONFIG["temperature"],
148
  seed=LLM_MODEL_CONFIG["seed"],
149
  timeout=30.0,
150
  )
151
  return response.choices[0].message.content or ""
152
 
153
+ def _needs_search(self, user_text: str, history: List[Dict[str, str]]) -> bool:
154
+ """輕量判斷是否需要網路搜尋"""
155
+ router_prompt = [
156
+ {"role": "system", "content": "你只需要判斷用戶問題是否需要最新的網路資訊來回答。"
157
+ "如果是永恆知識(如聖經、數學原理、哲學、歷史經典等),回答 no。"
158
+ "如果是時事、新聞、最新研究、實時數據、當前事件等,回答 yes。"
159
+ "只回覆單字:yes 或 no。不要解釋。"},
160
+ *history,
161
+ {"role": "user", "content": user_text}
162
+ ]
163
+ try:
164
+ decision = self._llm_call(router_prompt, max_tokens=10).strip().lower()
165
+ print(f"搜尋需求判斷:{decision}(問題:{user_text})")
166
+ return decision == "yes"
167
+ except Exception as e:
168
+ print(f"搜尋判斷失敗,預設不搜尋:{e}")
169
+ return False
170
+
171
  def get_conversation_history(self, user_id: str) -> List[Dict[str, str]]:
172
  return conversations.get(user_id, [])
173
 
 
183
  self.clear_conversation_history(user_id)
184
  return "對話紀錄已清除!現在開始新的對話。"
185
 
 
 
186
  history = self.get_conversation_history(user_id)
187
+
188
+ # ---- 新增:判斷是否需要搜尋 ----
189
+ needs_search = self._needs_search(user_text, history)
190
+
191
+ search_results = None
192
+ if needs_search:
193
+ search_results = perform_web_search(user_text)
194
+
195
+ # ---- 建構最終 prompt ----
196
  messages = [{"role": "system", "content": SYSTEM_PROMPT}]
197
  messages.extend(history)
198
  messages.append({"role": "user", "content": user_text})
199
 
200
+ if search_results and "沒有找到" not in search_results and "錯誤" not in search_results:
201
+ messages.append({"role": "system", "content": f"網路搜尋結果(僅在高度相關時使用):{search_results}"})
202
 
203
  response = self._llm_call(messages)
204
  response = response.replace('*', '')
205
 
206
+ # 更新歷史(包含最終回應)
207
  history.append({"role": "user", "content": user_text})
208
  history.append({"role": "assistant", "content": response})
209
  self.update_conversation_history(user_id, history)
210
 
211
+ # 長回應處理
212
  chunks = split_text_for_line(response)
213
  if len(chunks) > 5:
214
  summary_prompt = [