ginipick commited on
Commit
d835c63
·
verified ·
1 Parent(s): 5f32e07

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +73 -19
app.py CHANGED
@@ -9,6 +9,7 @@ import markdown
9
  import tempfile
10
  import base64
11
  from datetime import datetime
 
12
 
13
  # 로깅 설정
14
  logging.basicConfig(
@@ -151,12 +152,52 @@ def extract_keywords(text: str, top_k: int = 5) -> str:
151
  2) 공백 기준 토큰 분리
152
  3) 최대 top_k개만
153
  """
154
- import re
155
  text = re.sub(r"[^a-zA-Z0-9가-힣\s]", "", text)
156
  tokens = text.split()
157
  key_tokens = tokens[:top_k]
158
  return " ".join(key_tokens)
159
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
  # 웹 검색 함수
161
  def do_web_search(query: str) -> str:
162
  """
@@ -171,9 +212,9 @@ def do_web_search(query: str) -> str:
171
  "q": query,
172
  "domain": "google.com",
173
  "serp_type": "web", # 기본 웹 검색
174
- "device": "desktop",
175
- "lang": "en",
176
- "num": "20" # 최대 20결과만 요청
177
  }
178
 
179
  headers = {
@@ -183,8 +224,13 @@ def do_web_search(query: str) -> str:
183
  logging.info(f"SerpHouse API 호출 중... 검색어: {query}")
184
  logging.info(f"요청 URL: {url} - 파라미터: {params}")
185
 
186
- # GET 요청 수행
187
- response = requests.get(url, headers=headers, params=params, timeout=60)
 
 
 
 
 
188
  response.raise_for_status()
189
 
190
  logging.info(f"SerpHouse API 응답 상태 코드: {response.status_code}")
@@ -209,13 +255,13 @@ def do_web_search(query: str) -> str:
209
 
210
  if not organic:
211
  logging.warning("응답에서 organic 결과를 찾을 수 없습니다.")
212
- logging.debug(f"응답 구조: {list(data.keys())}")
213
  if isinstance(results, dict):
214
  logging.debug(f"results 구조: {list(results.keys())}")
215
- return "No web search results found or unexpected API response structure."
216
 
217
  # 결과 수 제한 및 컨텍스트 길이 최적화
218
- max_results = min(20, len(organic))
219
  limited_organic = organic[:max_results]
220
 
221
  # 결과 형식 개선 - 마크다운 형식으로 출력하여 가독성 향상
@@ -248,9 +294,12 @@ def do_web_search(query: str) -> str:
248
  logging.info(f"검색 결과 {len(limited_organic)}개 처리 완료")
249
  return search_results
250
 
 
 
 
251
  except Exception as e:
252
  logging.error(f"Web search failed: {e}")
253
- return f"Web search failed: {str(e)}"
254
 
255
  def chatbot_interface():
256
  st.title("Ginigen Blog")
@@ -320,7 +369,6 @@ def chatbot_interface():
320
  latest_blog = msg["content"]
321
 
322
  # 타이틀 추출 시도 (첫 번째 제목 태그 사용)
323
- import re
324
  title_match = re.search(r'# (.*?)(\n|$)', latest_blog)
325
  if title_match:
326
  latest_blog_title = title_match.group(1).strip()
@@ -402,14 +450,20 @@ def chatbot_interface():
402
  system_prompt = get_system_prompt()
403
  if st.session_state.use_web_search:
404
  with st.spinner("웹에서 관련 정보를 검색 중..."):
405
- search_query = extract_keywords(prompt, top_k=5)
406
- search_results = do_web_search(search_query)
407
- if "search failed" not in search_results.lower():
408
- # 시스템 프롬프트에 검색 결과 추가
409
- system_prompt += f"\n\n검색 결과:\n{search_results}\n"
410
- st.success(f"검색 완료: '{search_query}'대한 정보를 수집했습니다.")
411
- else:
412
- st.error("검색 오류가 발생했습니다.")
 
 
 
 
 
 
413
 
414
  # API 호출
415
  with client.messages.stream(
 
9
  import tempfile
10
  import base64
11
  from datetime import datetime
12
+ import re
13
 
14
  # 로깅 설정
15
  logging.basicConfig(
 
152
  2) 공백 기준 토큰 분리
153
  3) 최대 top_k개만
154
  """
 
155
  text = re.sub(r"[^a-zA-Z0-9가-힣\s]", "", text)
156
  tokens = text.split()
157
  key_tokens = tokens[:top_k]
158
  return " ".join(key_tokens)
159
 
160
+ # Mock 검색 결과 생성 함수 추가 (API 키가 없거나 연결 실패 시 대체 사용)
161
+ def generate_mock_search_results(query):
162
+ """API 연결이 안될 때 사용할 가상 검색 결과 생성"""
163
+ current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
164
+ mock_results = [
165
+ {
166
+ "title": f"{query}에 관한 최신 정보",
167
+ "link": "https://example.com/article1",
168
+ "snippet": f"{query}에 관한 가상 검색 결과입니다. 이 결과는 API 연결 문제로 인해 생성된 가상 데이터입니다. 실제 검색 결과가 아님을 참고하세요. 생성 시간: {current_time}",
169
+ "displayed_link": "example.com/article1"
170
+ },
171
+ {
172
+ "title": f"{query} 관련 연구 동향",
173
+ "link": "https://example.org/research",
174
+ "snippet": "이것은 API 연결 문제로 인한 가상 검색 결과입니다. 실제 검색 결과를 보여드리지 못해 죄송합니다. 대신 AI의 기존 지식을 활용하여 답변드리겠습니다.",
175
+ "displayed_link": "example.org/research"
176
+ }
177
+ ]
178
+
179
+ summary_lines = []
180
+ for idx, item in enumerate(mock_results, start=1):
181
+ title = item.get("title", "No title")
182
+ link = item.get("link", "#")
183
+ snippet = item.get("snippet", "No description")
184
+ displayed_link = item.get("displayed_link", link)
185
+
186
+ summary_lines.append(
187
+ f"### Result {idx}: {title}\n\n"
188
+ f"{snippet}\n\n"
189
+ f"**출처**: [{displayed_link}]({link})\n\n"
190
+ f"---\n"
191
+ )
192
+
193
+ notice = """
194
+ # 가상 검색 결과 (API 연결 문제로 인해 생성됨)
195
+ 아래는 API 연결 문제로 인해 생성된 가상 검색 결과입니다. 실제 검색 결과가 아님을 참고하세요.
196
+ 대신 AI의 기존 지식을 활용하여 최대한 정확한 답변을 드리겠습니다.
197
+ """
198
+
199
+ return notice + "\n".join(summary_lines)
200
+
201
  # 웹 검색 함수
202
  def do_web_search(query: str) -> str:
203
  """
 
212
  "q": query,
213
  "domain": "google.com",
214
  "serp_type": "web", # 기본 웹 검색
215
+ "device": "desktop",
216
+ "lang": "ko", # 한국어 검색 결과를 위해 변경
217
+ "num": "10" # 결과 수를 10 줄임 (빠른 응답을 위해)
218
  }
219
 
220
  headers = {
 
224
  logging.info(f"SerpHouse API 호출 중... 검색어: {query}")
225
  logging.info(f"요청 URL: {url} - 파라미터: {params}")
226
 
227
+ # Mock 응답 (실제 API 연결이 어려울 경우)
228
+ if not SERPHOUSE_API_KEY or "mock" in SERPHOUSE_API_KEY.lower():
229
+ logging.warning("API 키가 없거나 Mock 모드입니다. 모의 검색 결과를 반환합니다.")
230
+ return generate_mock_search_results(query)
231
+
232
+ # 타임아웃 줄임 (30초)
233
+ response = requests.get(url, headers=headers, params=params, timeout=30)
234
  response.raise_for_status()
235
 
236
  logging.info(f"SerpHouse API 응답 상태 코드: {response.status_code}")
 
255
 
256
  if not organic:
257
  logging.warning("응답에서 organic 결과를 찾을 수 없습니다.")
258
+ logging.debug(f"응답 구조: {list(data.keys()) if isinstance(data, dict) else 'not a dict'}")
259
  if isinstance(results, dict):
260
  logging.debug(f"results 구조: {list(results.keys())}")
261
+ return "검색 결과를 찾을 없습니다. 대신 기존 지식을 활용하여 답변하겠습니다."
262
 
263
  # 결과 수 제한 및 컨텍스트 길이 최적화
264
+ max_results = min(10, len(organic))
265
  limited_organic = organic[:max_results]
266
 
267
  # 결과 형식 개선 - 마크다운 형식으로 출력하여 가독성 향상
 
294
  logging.info(f"검색 결과 {len(limited_organic)}개 처리 완료")
295
  return search_results
296
 
297
+ except requests.exceptions.Timeout:
298
+ logging.error("Web search timed out")
299
+ return "Web search timed out. 검색 시간이 초과되었습니다. 기존 지식을 활용하여 답변하겠습니다."
300
  except Exception as e:
301
  logging.error(f"Web search failed: {e}")
302
+ return f"Web search failed: {str(e)}. 검색 중 오류가 발생했습니다. 기존 지식을 활용하여 답변하겠습니다."
303
 
304
  def chatbot_interface():
305
  st.title("Ginigen Blog")
 
369
  latest_blog = msg["content"]
370
 
371
  # 타이틀 추출 시도 (첫 번째 제목 태그 사용)
 
372
  title_match = re.search(r'# (.*?)(\n|$)', latest_blog)
373
  if title_match:
374
  latest_blog_title = title_match.group(1).strip()
 
450
  system_prompt = get_system_prompt()
451
  if st.session_state.use_web_search:
452
  with st.spinner("웹에서 관련 정보를 검색 중..."):
453
+ try:
454
+ search_query = extract_keywords(prompt, top_k=5)
455
+ search_results = do_web_search(search_query)
456
+
457
+ if "search failed" not in search_results.lower() and "timed out" not in search_results.lower():
458
+ # 시스템 프롬프트검색 결과 추가
459
+ system_prompt += f"\n\n검색 결과:\n{search_results}\n"
460
+ st.success(f"검색 완료: '{search_query}'에 대한 정보를 수집했습니다.")
461
+ else:
462
+ st.warning("웹 검색을 진행했으나 결과를 가져오는데 실패했습니다. 기존 지식을 활용하여 답변합니다.")
463
+ logging.warning(f"웹 검색 실패 또는 타임아웃: {search_results}")
464
+ except Exception as e:
465
+ st.error(f"웹 검색 중 오류가 발생했습니다: {str(e)}")
466
+ logging.error(f"웹 검색 오류: {str(e)}")
467
 
468
  # API 호출
469
  with client.messages.stream(