seawolf2357 commited on
Commit
a18eaea
Β·
verified Β·
1 Parent(s): 79b7afb

Update routes.py

Browse files
Files changed (1) hide show
  1. routes.py +36 -34
routes.py CHANGED
@@ -4,8 +4,6 @@ from pathlib import Path
4
  import shutil # For zipping the cache directory
5
  import json # For parsing streamed JSON data
6
  from werkzeug.utils import secure_filename
7
- import uuid
8
- import tempfile
9
 
10
  import os
11
  import config
@@ -57,6 +55,17 @@ def download_cache_zip():
57
  logger.error(f"μΊμ‹œ 디렉토리 μ••μΆ• 파일 생성 λ˜λŠ” 전솑 쀑 였λ₯˜ λ°œμƒ: {e}", exc_info=True)
58
  return jsonify({"error": f"μ••μΆ• 파일 생성 λ˜λŠ” 전솑 쀑 였λ₯˜ λ°œμƒ: {e}"}), 500
59
 
 
 
 
 
 
 
 
 
 
 
 
60
  @main_bp.route('/')
61
  def index():
62
  """메인 HTML νŽ˜μ΄μ§€λ₯Ό μ œκ³΅ν•©λ‹ˆλ‹€."""
@@ -188,7 +197,8 @@ def explain_sentence():
188
  }
189
  ]
190
 
191
- cache_key = f"explain::{report_name}::{selected_sentence}"
 
192
  cached_result = cache.get(cache_key)
193
  if cached_result:
194
  logger.info("μΊμ‹œλœ μ„€λͺ…을 λ°˜ν™˜ν•©λ‹ˆλ‹€.")
@@ -266,58 +276,45 @@ def upload_and_analyze():
266
  additional_context = request.form.get('context', '')
267
 
268
  try:
269
- # μž„μ‹œ 파일둜 μ €μž₯
270
- with tempfile.NamedTemporaryFile(delete=False, suffix=os.path.splitext(file.filename)[1]) as tmp_file:
271
- file.save(tmp_file.name)
272
- temp_filepath = tmp_file.name
273
-
274
- # Base64둜 인코딩
275
- base64_image_data_url = utils.image_to_base64_data_url(temp_filepath)
276
-
277
- # μž„μ‹œ 파일 μ‚­μ œ
278
- os.unlink(temp_filepath)
279
 
280
- if not base64_image_data_url:
281
- logger.error("이미지λ₯Ό base64둜 μΈμ½”λ”©ν•˜λŠ”λ° μ‹€νŒ¨ν–ˆμŠ΅λ‹ˆλ‹€.")
282
- return jsonify({"error": "이미지 인코딩에 μ‹€νŒ¨ν–ˆμŠ΅λ‹ˆλ‹€."}), 500
283
-
284
- # μ‹œμŠ€ν…œ ν”„λ‘¬ν”„νŠΈ ꡬ성
285
  system_prompt = (
286
  "당신은 κ²½ν—˜μ΄ ν’λΆ€ν•œ 방사선과 μ „λ¬Έμ˜μž…λ‹ˆλ‹€. "
287
  "λ°˜λ“œμ‹œ ν•œκ΅­μ–΄λ‘œ μ‘λ‹΅ν•˜μ„Έμš”. "
288
- f"제곡된 {image_type_korean} μ˜μƒμ„ λΆ„μ„ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. "
289
- "μ˜μƒμ—μ„œ κ΄€μ°°λ˜λŠ” μ£Όμš” μ†Œκ²¬μ„ μ„€λͺ…ν•˜κ³ , κ°€λŠ₯ν•œ 진단을 μ œμ‹œν•˜μ„Έμš”. "
290
- "일반인이 이해할 수 μžˆλ„λ‘ μ‰¬μš΄ μš©μ–΄λ‘œ μ„€λͺ…ν•˜λ˜, μ˜ν•™μ  정확성을 μœ μ§€ν•˜μ„Έμš”. "
291
  "λ‹€μŒ ꡬ쑰둜 μ‘λ‹΅ν•˜μ„Έμš”:\n"
292
- "1. μ£Όμš” μ†Œκ²¬: μ˜μƒμ—μ„œ κ΄€μ°°λ˜λŠ” μ£Όμš” νŠΉμ§•λ“€\n"
293
- "2. κ°€λŠ₯ν•œ 진단: κ΄€μ°°λœ μ†Œκ²¬μ„ λ°”νƒ•μœΌλ‘œ ν•œ κ°€λŠ₯ν•œ 진단듀\n"
294
- "3. μΆ”κ°€ κΆŒκ³ μ‚¬ν•­: ν•„μš”ν•œ μΆ”κ°€ κ²€μ‚¬λ‚˜ μ‘°μΉ˜μ‚¬ν•­\n"
 
295
  "λͺ¨λ“  μ„€λͺ…은 λ°˜λ“œμ‹œ ν•œκ΅­μ–΄λ‘œ μž‘μ„±ν•˜μ„Έμš”."
296
  )
297
 
298
- user_prompt_text = f"이 {image_type_korean} μ˜μƒμ„ λΆ„μ„ν•΄μ£Όμ„Έμš”."
299
  if additional_context:
300
- user_prompt_text += f"\nμΆ”κ°€ 정보: {additional_context}"
301
 
302
  messages_for_api = [
303
  {"role": "system", "content": system_prompt},
304
  {
305
  "role": "user",
306
  "content": [
307
- {"type": "text", "text": user_prompt_text},
308
- {"type": "image_url", "image_url": {"url": base64_image_data_url}}
309
  ]
310
  }
311
  ]
312
 
313
  # μΊμ‹œ ν‚€ 생성 (파일λͺ…κ³Ό μ»¨ν…μŠ€νŠΈ 기반)
314
- cache_key = f"analyze::{secure_filename(file.filename)}::{image_type}::{additional_context[:50]}"
315
  cached_result = cache.get(cache_key)
316
  if cached_result:
317
- logger.info("μΊμ‹œλœ 뢄석 κ²°κ³Όλ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.")
318
  return jsonify({"analysis": cached_result})
319
 
320
- logger.info("이미지와 ν•¨κ»˜ LLM API(REST)둜 뢄석 μš”μ²­μ„ 전솑 쀑...")
321
  response = make_chat_completion_request(
322
  model="tgi",
323
  messages=messages_for_api,
@@ -353,9 +350,14 @@ def upload_and_analyze():
353
  if analysis:
354
  cache.set(cache_key, analysis, expire=None)
355
 
356
- logger.info("뢄석이 μ„±κ³΅μ μœΌλ‘œ μ™„μ„±λ˜μ—ˆμŠ΅λ‹ˆλ‹€." if analysis else "APIλ‘œλΆ€ν„° 빈 뢄석 κ²°κ³Όλ₯Ό λ°›μ•˜μŠ΅λ‹ˆλ‹€.")
 
 
 
 
 
357
  return jsonify({"analysis": analysis or "APIλ‘œλΆ€ν„° 뢄석 κ²°κ³Όλ₯Ό λ°›μ§€ λͺ»ν–ˆμŠ΅λ‹ˆλ‹€."})
358
 
359
  except Exception as e:
360
- logger.error(f"이미지 μ—…λ‘œλ“œ 및 뢄석 쀑 였λ₯˜ λ°œμƒ: {e}", exc_info=True)
361
- return jsonify({"error": "이미지 뢄석 쀑 였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€. μž μ‹œ ν›„ λ‹€μ‹œ μ‹œλ„ν•΄μ£Όμ„Έμš”."}), 500
 
4
  import shutil # For zipping the cache directory
5
  import json # For parsing streamed JSON data
6
  from werkzeug.utils import secure_filename
 
 
7
 
8
  import os
9
  import config
 
55
  logger.error(f"μΊμ‹œ 디렉토리 μ••μΆ• 파일 생성 λ˜λŠ” 전솑 쀑 였λ₯˜ λ°œμƒ: {e}", exc_info=True)
56
  return jsonify({"error": f"μ••μΆ• 파일 생성 λ˜λŠ” 전솑 쀑 였λ₯˜ λ°œμƒ: {e}"}), 500
57
 
58
+ @main_bp.route('/clear_cache', methods=['POST'])
59
+ def clear_cache():
60
+ """μΊμ‹œλ₯Ό μ΄ˆκΈ°ν™”ν•©λ‹ˆλ‹€."""
61
+ try:
62
+ cache.clear()
63
+ logger.info("μΊμ‹œκ°€ μ„±κ³΅μ μœΌλ‘œ μ΄ˆκΈ°ν™”λ˜μ—ˆμŠ΅λ‹ˆλ‹€.")
64
+ return jsonify({"message": "μΊμ‹œκ°€ μ΄ˆκΈ°ν™”λ˜μ—ˆμŠ΅λ‹ˆλ‹€.", "success": True})
65
+ except Exception as e:
66
+ logger.error(f"μΊμ‹œ μ΄ˆκΈ°ν™” 쀑 였λ₯˜ λ°œμƒ: {e}", exc_info=True)
67
+ return jsonify({"error": f"μΊμ‹œ μ΄ˆκΈ°ν™” 쀑 였λ₯˜ λ°œμƒ: {e}", "success": False}), 500
68
+
69
  @main_bp.route('/')
70
  def index():
71
  """메인 HTML νŽ˜μ΄μ§€λ₯Ό μ œκ³΅ν•©λ‹ˆλ‹€."""
 
197
  }
198
  ]
199
 
200
+ # ν•œκΈ€ 응닡을 μœ„ν•΄ μΊμ‹œ 킀에 μ–Έμ–΄ 정보 μΆ”κ°€
201
+ cache_key = f"explain::ko::{report_name}::{selected_sentence}"
202
  cached_result = cache.get(cache_key)
203
  if cached_result:
204
  logger.info("μΊμ‹œλœ μ„€λͺ…을 λ°˜ν™˜ν•©λ‹ˆλ‹€.")
 
276
  additional_context = request.form.get('context', '')
277
 
278
  try:
279
+ # 파일λͺ… μ €μž₯ (뢄석에 참고용)
280
+ filename = secure_filename(file.filename)
 
 
 
 
 
 
 
 
281
 
282
+ # μ‹œμŠ€ν…œ ν”„λ‘¬ν”„νŠΈ ꡬ성 (이미지 직접 뢄석 λŒ€μ‹  일반적인 κ°€μ΄λ“œ 제곡)
 
 
 
 
283
  system_prompt = (
284
  "당신은 κ²½ν—˜μ΄ ν’λΆ€ν•œ 방사선과 μ „λ¬Έμ˜μž…λ‹ˆλ‹€. "
285
  "λ°˜λ“œμ‹œ ν•œκ΅­μ–΄λ‘œ μ‘λ‹΅ν•˜μ„Έμš”. "
286
+ f"μ‚¬μš©μžκ°€ {image_type_korean} μ˜μƒμ„ μ—…λ‘œλ“œν–ˆμŠ΅λ‹ˆλ‹€. "
287
+ "일반적인 μ˜μƒ νŒλ… κ°€μ΄λ“œλΌμΈκ³Ό μ£Όμ˜μ‚¬ν•­μ„ μ œκ³΅ν•˜μ„Έμš”. "
 
288
  "λ‹€μŒ ꡬ쑰둜 μ‘λ‹΅ν•˜μ„Έμš”:\n"
289
+ f"1. {image_type_korean} νŒλ… μ‹œ 확인해야 ν•  μ£Όμš” 사항\n"
290
+ "2. 일반적으둜 관찰될 수 μžˆλŠ” μ†Œκ²¬λ“€\n"
291
+ "3. μ •ν™•ν•œ 진단을 μœ„ν•œ κΆŒκ³ μ‚¬ν•­\n"
292
+ "4. μ£Όμ˜μ‚¬ν•­: μ‹€μ œ 진단은 의료 μ „λ¬Έκ°€μ˜ 직접적인 κ²€ν† κ°€ ν•„μš”ν•¨μ„ κ°•μ‘°\n"
293
  "λͺ¨λ“  μ„€λͺ…은 λ°˜λ“œμ‹œ ν•œκ΅­μ–΄λ‘œ μž‘μ„±ν•˜μ„Έμš”."
294
  )
295
 
296
+ user_prompt_text = f"{image_type_korean} μ˜μƒ '{filename}'이 μ—…λ‘œλ“œλ˜μ—ˆμŠ΅λ‹ˆλ‹€. μ΄λŸ¬ν•œ μœ ν˜•μ˜ μ˜μƒμ„ νŒλ…ν•  λ•Œ κ³ λ €ν•΄μ•Ό ν•  사항을 μ„€λͺ…ν•΄μ£Όμ„Έμš”."
297
  if additional_context:
298
+ user_prompt_text += f"\nν™˜μž/검사 정보: {additional_context}"
299
 
300
  messages_for_api = [
301
  {"role": "system", "content": system_prompt},
302
  {
303
  "role": "user",
304
  "content": [
305
+ {"type": "text", "text": user_prompt_text}
 
306
  ]
307
  }
308
  ]
309
 
310
  # μΊμ‹œ ν‚€ 생성 (파일λͺ…κ³Ό μ»¨ν…μŠ€νŠΈ 기반)
311
+ cache_key = f"analyze::ko::{image_type}::{additional_context[:50]}"
312
  cached_result = cache.get(cache_key)
313
  if cached_result:
314
+ logger.info("μΊμ‹œλœ 뢄석 κ°€μ΄λ“œλ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.")
315
  return jsonify({"analysis": cached_result})
316
 
317
+ logger.info("LLM API(REST)둜 뢄석 κ°€μ΄λ“œ μš”μ²­μ„ 전솑 쀑...")
318
  response = make_chat_completion_request(
319
  model="tgi",
320
  messages=messages_for_api,
 
350
  if analysis:
351
  cache.set(cache_key, analysis, expire=None)
352
 
353
+ logger.info("뢄석 κ°€μ΄λ“œκ°€ μ„±κ³΅μ μœΌλ‘œ μƒμ„±λ˜μ—ˆμŠ΅λ‹ˆλ‹€." if analysis else "APIλ‘œλΆ€ν„° 빈 뢄석 κ²°κ³Όλ₯Ό λ°›μ•˜μŠ΅λ‹ˆλ‹€.")
354
+
355
+ # μ£Όμ˜μ‚¬ν•­ μΆ”κ°€
356
+ if analysis:
357
+ analysis += "\n\n⚠️ **μ€‘μš”**: μ΄λŠ” 일반적인 κ°€μ΄λ“œλΌμΈμ΄λ©°, μ‹€μ œ μ˜μƒμ˜ μ •ν™•ν•œ νŒλ…κ³Ό 진단은 의료 μ „λ¬Έκ°€κ°€ 직접 μ˜μƒμ„ κ²€ν† ν•˜μ—¬ μˆ˜ν–‰ν•΄μ•Ό ν•©λ‹ˆλ‹€."
358
+
359
  return jsonify({"analysis": analysis or "APIλ‘œλΆ€ν„° 뢄석 κ²°κ³Όλ₯Ό λ°›μ§€ λͺ»ν–ˆμŠ΅λ‹ˆλ‹€."})
360
 
361
  except Exception as e:
362
+ logger.error(f"이미지 μ—…λ‘œλ“œ 및 뢄석 κ°€μ΄λ“œ 생성 쀑 였λ₯˜ λ°œμƒ: {e}", exc_info=True)
363
+ return jsonify({"error": "뢄석 κ°€μ΄λ“œ 생성 쀑 였λ₯˜κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€. μž μ‹œ ν›„ λ‹€μ‹œ μ‹œλ„ν•΄μ£Όμ„Έμš”."}), 500