[STYLE] 로거 주석 처리
Browse files- client/app.py +4 -3
- client/services/analysis_service.py +8 -8
- client/services/database.py +3 -3
- client/services/voice_analyzer.py +17 -17
- gemini_adapter.py +2 -1
client/app.py
CHANGED
|
@@ -59,7 +59,8 @@ REFERENCE_AUDIO_DIR = os.path.join(PROJECT_ROOT, "reference_audio")
|
|
| 59 |
# print(f"[PATH DEBUG] DOCS_DIR: {DOCS_DIR}")
|
| 60 |
# print(f"[PATH DEBUG] DOCS_DIR exists: {os.path.exists(DOCS_DIR)}")
|
| 61 |
if os.path.exists(DOCS_DIR):
|
| 62 |
-
print(f"[PATH DEBUG] DOCS_DIR contents: {os.listdir(DOCS_DIR)}")
|
|
|
|
| 63 |
|
| 64 |
# 환경변수로 allowed_paths 설정 (Spaces 배포용)
|
| 65 |
os.environ["GRADIO_ALLOWED_PATHS"] = f"{UPLOAD_DIR},{DOCS_DIR},{IMAGES_DIR},{REFERENCE_AUDIO_DIR}"
|
|
@@ -176,7 +177,7 @@ class AudioValidationApp:
|
|
| 176 |
|
| 177 |
# API 오류 처리
|
| 178 |
if api_result.get("status") == "error":
|
| 179 |
-
print(f"[API ERROR] {api_result.get('message')}")
|
| 180 |
# 오류 시 기본 실패 처리
|
| 181 |
return (
|
| 182 |
HistoryDisplayComponent.render_failure_history(current_history),
|
|
@@ -357,7 +358,7 @@ class AudioValidationApp:
|
|
| 357 |
# print(f" - 승리 연속: {updated_game_state.get('stats', {}).get('winStreak', 0)}")
|
| 358 |
|
| 359 |
# 통계는 JavaScript에서 화면 표시 시 API 호출하여 업데이트
|
| 360 |
-
print(f"[SUCCESS] 성공 화면으로 전환 - JS가 통계 API 호출 예정")
|
| 361 |
|
| 362 |
# outputs 순서: history_html, failure_history, browser_history, game_state,
|
| 363 |
# failure_modal, main_screen, success_screen, success_content
|
|
|
|
| 59 |
# print(f"[PATH DEBUG] DOCS_DIR: {DOCS_DIR}")
|
| 60 |
# print(f"[PATH DEBUG] DOCS_DIR exists: {os.path.exists(DOCS_DIR)}")
|
| 61 |
if os.path.exists(DOCS_DIR):
|
| 62 |
+
# print(f"[PATH DEBUG] DOCS_DIR contents: {os.listdir(DOCS_DIR)}")
|
| 63 |
+
pass
|
| 64 |
|
| 65 |
# 환경변수로 allowed_paths 설정 (Spaces 배포용)
|
| 66 |
os.environ["GRADIO_ALLOWED_PATHS"] = f"{UPLOAD_DIR},{DOCS_DIR},{IMAGES_DIR},{REFERENCE_AUDIO_DIR}"
|
|
|
|
| 177 |
|
| 178 |
# API 오류 처리
|
| 179 |
if api_result.get("status") == "error":
|
| 180 |
+
# print(f"[API ERROR] {api_result.get('message')}")
|
| 181 |
# 오류 시 기본 실패 처리
|
| 182 |
return (
|
| 183 |
HistoryDisplayComponent.render_failure_history(current_history),
|
|
|
|
| 358 |
# print(f" - 승리 연속: {updated_game_state.get('stats', {}).get('winStreak', 0)}")
|
| 359 |
|
| 360 |
# 통계는 JavaScript에서 화면 표시 시 API 호출하여 업데이트
|
| 361 |
+
# print(f"[SUCCESS] 성공 화면으로 전환 - JS가 통계 API 호출 예정")
|
| 362 |
|
| 363 |
# outputs 순서: history_html, failure_history, browser_history, game_state,
|
| 364 |
# failure_modal, main_screen, success_screen, success_content
|
client/services/analysis_service.py
CHANGED
|
@@ -40,14 +40,14 @@ async def analyze_voice(audio_bytes: bytes, date: str, session_id: str) -> Dict:
|
|
| 40 |
Returns:
|
| 41 |
dict: Analysis results with scores
|
| 42 |
"""
|
| 43 |
-
logger.info(f"Received request: date={date}, session_id={session_id}")
|
| 44 |
|
| 45 |
# 1. Get puzzle for the date
|
| 46 |
puzzle = get_puzzle_by_date(date)
|
| 47 |
if not puzzle:
|
| 48 |
return {"status": "error", "message": f"No puzzle found for date: {date}"}
|
| 49 |
|
| 50 |
-
logger.info(f"Found puzzle: {puzzle['puzzle_number']} - {puzzle['category']}")
|
| 51 |
|
| 52 |
# 2. Call VoiceKit MCP for analysis
|
| 53 |
start_time = time.time()
|
|
@@ -76,8 +76,8 @@ async def analyze_voice(audio_bytes: bytes, date: str, session_id: str) -> Dict:
|
|
| 76 |
user_text = mcp_result.get("user_text", "")
|
| 77 |
attempt = mcp_result.get("attempt", 1)
|
| 78 |
|
| 79 |
-
logger.info(f"VoiceKit scores: pitch={pitch}, rhythm={rhythm}, energy={energy}, "
|
| 80 |
-
|
| 81 |
|
| 82 |
# 4. Get hint history for this session (to avoid repetition)
|
| 83 |
hint_history = get_hint_history(session_id)
|
|
@@ -99,8 +99,8 @@ async def analyze_voice(audio_bytes: bytes, date: str, session_id: str) -> Dict:
|
|
| 99 |
hint_history=hint_history
|
| 100 |
)
|
| 101 |
gemini_time = (time.time() - gemini_start) * 1000
|
| 102 |
-
logger.info(f"⏱️ Gemini hint generation: {gemini_time:.1f}ms")
|
| 103 |
-
logger.info(f"Generated hints: {hints_json}")
|
| 104 |
|
| 105 |
advice = extract_advice_text(hints_json)
|
| 106 |
# Require non-empty user_text AND score > 85 for correct answer
|
|
@@ -110,7 +110,7 @@ async def analyze_voice(audio_bytes: bytes, date: str, session_id: str) -> Dict:
|
|
| 110 |
add_hint_to_history(session_id, advice)
|
| 111 |
|
| 112 |
# 7. Save guess record to database
|
| 113 |
-
logger.info(f"[DB] Attempting to save guess record for session={session_id}, puzzle={puzzle['puzzle_number']}")
|
| 114 |
save_result = save_guess_record(
|
| 115 |
session_id=session_id,
|
| 116 |
puzzle_number=puzzle["puzzle_number"],
|
|
@@ -130,7 +130,7 @@ async def analyze_voice(audio_bytes: bytes, date: str, session_id: str) -> Dict:
|
|
| 130 |
logger.error(f"[DB] ❌ Failed to save guess record!")
|
| 131 |
|
| 132 |
total_time = (time.time() - start_time) * 1000
|
| 133 |
-
logger.info(f"⏱️ TOTAL REQUEST TIME: {total_time:.1f}ms")
|
| 134 |
logger.info(f"Analysis complete: category={puzzle['category']}, overall={overall}, correct={is_correct}")
|
| 135 |
|
| 136 |
result = {
|
|
|
|
| 40 |
Returns:
|
| 41 |
dict: Analysis results with scores
|
| 42 |
"""
|
| 43 |
+
# logger.info(f"Received request: date={date}, session_id={session_id}")
|
| 44 |
|
| 45 |
# 1. Get puzzle for the date
|
| 46 |
puzzle = get_puzzle_by_date(date)
|
| 47 |
if not puzzle:
|
| 48 |
return {"status": "error", "message": f"No puzzle found for date: {date}"}
|
| 49 |
|
| 50 |
+
# logger.info(f"Found puzzle: {puzzle['puzzle_number']} - {puzzle['category']}")
|
| 51 |
|
| 52 |
# 2. Call VoiceKit MCP for analysis
|
| 53 |
start_time = time.time()
|
|
|
|
| 76 |
user_text = mcp_result.get("user_text", "")
|
| 77 |
attempt = mcp_result.get("attempt", 1)
|
| 78 |
|
| 79 |
+
# logger.info(f"VoiceKit scores: pitch={pitch}, rhythm={rhythm}, energy={energy}, "
|
| 80 |
+
# f"pronunciation={pronunciation}, transcript={transcript}, overall={overall}")
|
| 81 |
|
| 82 |
# 4. Get hint history for this session (to avoid repetition)
|
| 83 |
hint_history = get_hint_history(session_id)
|
|
|
|
| 99 |
hint_history=hint_history
|
| 100 |
)
|
| 101 |
gemini_time = (time.time() - gemini_start) * 1000
|
| 102 |
+
# logger.info(f"⏱️ Gemini hint generation: {gemini_time:.1f}ms")
|
| 103 |
+
# logger.info(f"Generated hints: {hints_json}")
|
| 104 |
|
| 105 |
advice = extract_advice_text(hints_json)
|
| 106 |
# Require non-empty user_text AND score > 85 for correct answer
|
|
|
|
| 110 |
add_hint_to_history(session_id, advice)
|
| 111 |
|
| 112 |
# 7. Save guess record to database
|
| 113 |
+
# logger.info(f"[DB] Attempting to save guess record for session={session_id}, puzzle={puzzle['puzzle_number']}")
|
| 114 |
save_result = save_guess_record(
|
| 115 |
session_id=session_id,
|
| 116 |
puzzle_number=puzzle["puzzle_number"],
|
|
|
|
| 130 |
logger.error(f"[DB] ❌ Failed to save guess record!")
|
| 131 |
|
| 132 |
total_time = (time.time() - start_time) * 1000
|
| 133 |
+
# logger.info(f"⏱️ TOTAL REQUEST TIME: {total_time:.1f}ms")
|
| 134 |
logger.info(f"Analysis complete: category={puzzle['category']}, overall={overall}, correct={is_correct}")
|
| 135 |
|
| 136 |
result = {
|
client/services/database.py
CHANGED
|
@@ -151,9 +151,9 @@ def save_guess_record(
|
|
| 151 |
)
|
| 152 |
connection.commit()
|
| 153 |
|
| 154 |
-
logger.info(
|
| 155 |
-
|
| 156 |
-
)
|
| 157 |
return True
|
| 158 |
|
| 159 |
except Exception as e:
|
|
|
|
| 151 |
)
|
| 152 |
connection.commit()
|
| 153 |
|
| 154 |
+
# logger.info(
|
| 155 |
+
# f"Saved guess record: session={session_id}, puzzle={puzzle_number}, correct={is_correct}"
|
| 156 |
+
# )
|
| 157 |
return True
|
| 158 |
|
| 159 |
except Exception as e:
|
client/services/voice_analyzer.py
CHANGED
|
@@ -170,10 +170,10 @@ def compress_audio(audio_bytes: bytes, target_sample_rate: int = 16000) -> bytes
|
|
| 170 |
reduction = (1 - compressed_size / original_size) * 100
|
| 171 |
compress_time = (time.time() - compress_start) * 1000
|
| 172 |
|
| 173 |
-
logger.info(
|
| 174 |
-
|
| 175 |
-
|
| 176 |
-
)
|
| 177 |
|
| 178 |
return compressed_bytes
|
| 179 |
|
|
@@ -202,7 +202,7 @@ def load_reference_audio_with_fallback(reference_audio_path: str, puzzle_number:
|
|
| 202 |
"""
|
| 203 |
# Check cache first (if puzzle_number provided)
|
| 204 |
if puzzle_number is not None and puzzle_number in _reference_audio_cache:
|
| 205 |
-
logger.info(f"✓ Using cached reference audio for puzzle #{puzzle_number}")
|
| 206 |
return _reference_audio_cache[puzzle_number]
|
| 207 |
|
| 208 |
if not reference_audio_path:
|
|
@@ -219,7 +219,7 @@ def load_reference_audio_with_fallback(reference_audio_path: str, puzzle_number:
|
|
| 219 |
audio_b64 = base64.b64encode(f.read()).decode("utf-8")
|
| 220 |
if puzzle_number is not None:
|
| 221 |
_reference_audio_cache[puzzle_number] = audio_b64
|
| 222 |
-
logger.info(f"✓ Loaded reference audio: {base_path}")
|
| 223 |
return audio_b64
|
| 224 |
|
| 225 |
# Try alternative formats (priority: .wav for VoiceKit, then others)
|
|
@@ -230,7 +230,7 @@ def load_reference_audio_with_fallback(reference_audio_path: str, puzzle_number:
|
|
| 230 |
audio_b64 = base64.b64encode(f.read()).decode("utf-8")
|
| 231 |
if puzzle_number is not None:
|
| 232 |
_reference_audio_cache[puzzle_number] = audio_b64
|
| 233 |
-
logger.info(f"✓ Loaded reference audio (alternative format): {alt_path}")
|
| 234 |
return audio_b64
|
| 235 |
|
| 236 |
logger.warning(f"⚠ No reference audio found for: {reference_audio_path}")
|
|
@@ -303,12 +303,12 @@ async def analyze_voice_with_mcp(
|
|
| 303 |
|
| 304 |
# Convert audio bytes to base64
|
| 305 |
user_b64 = base64.b64encode(compressed_audio).decode("utf-8")
|
| 306 |
-
logger.info(f"⏱️ Base64 encoding: {(time.time() - start_time)*1000:.1f}ms")
|
| 307 |
|
| 308 |
# Load reference audio (ground truth) with format fallback and caching
|
| 309 |
ref_start = time.time()
|
| 310 |
reference_b64 = load_reference_audio_with_fallback(reference_audio_path, puzzle_number)
|
| 311 |
-
logger.info(f"⏱️ Reference audio load: {(time.time() - ref_start)*1000:.1f}ms")
|
| 312 |
|
| 313 |
if reference_b64 is None:
|
| 314 |
# Fallback: use user audio as reference if GT not available
|
|
@@ -317,7 +317,7 @@ async def analyze_voice_with_mcp(
|
|
| 317 |
|
| 318 |
# Track attempt count
|
| 319 |
attempt = get_attempt_count(session_id)
|
| 320 |
-
logger.info(f"Session {session_id}: Attempt {attempt}/6")
|
| 321 |
|
| 322 |
# Call VoiceKit MCP for voice analysis with retry logic and timeout
|
| 323 |
max_retries = 3
|
|
@@ -342,16 +342,16 @@ async def analyze_voice_with_mcp(
|
|
| 342 |
)
|
| 343 |
voicekit_time = (time.time() - voicekit_start) * 1000
|
| 344 |
logger.info(f"✓ VoiceKit MCP call successful")
|
| 345 |
-
logger.info(f"⏱️ VoiceKit MCP call: {voicekit_time:.1f}ms")
|
| 346 |
-
logger.info(f"📦 VoiceKit raw result: {result}")
|
| 347 |
break # Success, exit retry loop
|
| 348 |
|
| 349 |
except asyncio.TimeoutError:
|
| 350 |
if retry < max_retries - 1:
|
| 351 |
retry_delay = 0.5 * (2 ** retry)
|
| 352 |
-
logger.warning(
|
| 353 |
-
|
| 354 |
-
)
|
| 355 |
await asyncio.sleep(retry_delay)
|
| 356 |
else:
|
| 357 |
logger.error(f"VoiceKit call timed out after {max_retries} attempts")
|
|
@@ -393,7 +393,7 @@ async def analyze_voice_with_mcp(
|
|
| 393 |
logger.error(f"VoiceKit returned empty text. Full result: {result}")
|
| 394 |
return {"error": "VoiceKit returned empty text"}
|
| 395 |
|
| 396 |
-
logger.debug(f"VoiceKit raw response: {scores_text[:500]}")
|
| 397 |
|
| 398 |
try:
|
| 399 |
scores = json.loads(scores_text)
|
|
@@ -405,7 +405,7 @@ async def analyze_voice_with_mcp(
|
|
| 405 |
|
| 406 |
# Total time
|
| 407 |
total_time = (time.time() - start_time) * 1000
|
| 408 |
-
logger.info(f"⏱️ TOTAL VoiceKit TIME: {total_time:.1f}ms")
|
| 409 |
|
| 410 |
return {
|
| 411 |
"pitch": scores.get("pitch", 0),
|
|
|
|
| 170 |
reduction = (1 - compressed_size / original_size) * 100
|
| 171 |
compress_time = (time.time() - compress_start) * 1000
|
| 172 |
|
| 173 |
+
# logger.info(
|
| 174 |
+
# f"🗜️ Audio compression: {original_size/1024:.1f}KB → {compressed_size/1024:.1f}KB "
|
| 175 |
+
# f"({reduction:.1f}% reduction) in {compress_time:.1f}ms"
|
| 176 |
+
# )
|
| 177 |
|
| 178 |
return compressed_bytes
|
| 179 |
|
|
|
|
| 202 |
"""
|
| 203 |
# Check cache first (if puzzle_number provided)
|
| 204 |
if puzzle_number is not None and puzzle_number in _reference_audio_cache:
|
| 205 |
+
# logger.info(f"✓ Using cached reference audio for puzzle #{puzzle_number}")
|
| 206 |
return _reference_audio_cache[puzzle_number]
|
| 207 |
|
| 208 |
if not reference_audio_path:
|
|
|
|
| 219 |
audio_b64 = base64.b64encode(f.read()).decode("utf-8")
|
| 220 |
if puzzle_number is not None:
|
| 221 |
_reference_audio_cache[puzzle_number] = audio_b64
|
| 222 |
+
# logger.info(f"✓ Loaded reference audio: {base_path}")
|
| 223 |
return audio_b64
|
| 224 |
|
| 225 |
# Try alternative formats (priority: .wav for VoiceKit, then others)
|
|
|
|
| 230 |
audio_b64 = base64.b64encode(f.read()).decode("utf-8")
|
| 231 |
if puzzle_number is not None:
|
| 232 |
_reference_audio_cache[puzzle_number] = audio_b64
|
| 233 |
+
# logger.info(f"✓ Loaded reference audio (alternative format): {alt_path}")
|
| 234 |
return audio_b64
|
| 235 |
|
| 236 |
logger.warning(f"⚠ No reference audio found for: {reference_audio_path}")
|
|
|
|
| 303 |
|
| 304 |
# Convert audio bytes to base64
|
| 305 |
user_b64 = base64.b64encode(compressed_audio).decode("utf-8")
|
| 306 |
+
# logger.info(f"⏱️ Base64 encoding: {(time.time() - start_time)*1000:.1f}ms")
|
| 307 |
|
| 308 |
# Load reference audio (ground truth) with format fallback and caching
|
| 309 |
ref_start = time.time()
|
| 310 |
reference_b64 = load_reference_audio_with_fallback(reference_audio_path, puzzle_number)
|
| 311 |
+
# logger.info(f"⏱️ Reference audio load: {(time.time() - ref_start)*1000:.1f}ms")
|
| 312 |
|
| 313 |
if reference_b64 is None:
|
| 314 |
# Fallback: use user audio as reference if GT not available
|
|
|
|
| 317 |
|
| 318 |
# Track attempt count
|
| 319 |
attempt = get_attempt_count(session_id)
|
| 320 |
+
# logger.info(f"Session {session_id}: Attempt {attempt}/6")
|
| 321 |
|
| 322 |
# Call VoiceKit MCP for voice analysis with retry logic and timeout
|
| 323 |
max_retries = 3
|
|
|
|
| 342 |
)
|
| 343 |
voicekit_time = (time.time() - voicekit_start) * 1000
|
| 344 |
logger.info(f"✓ VoiceKit MCP call successful")
|
| 345 |
+
# logger.info(f"⏱️ VoiceKit MCP call: {voicekit_time:.1f}ms")
|
| 346 |
+
# logger.info(f"📦 VoiceKit raw result: {result}")
|
| 347 |
break # Success, exit retry loop
|
| 348 |
|
| 349 |
except asyncio.TimeoutError:
|
| 350 |
if retry < max_retries - 1:
|
| 351 |
retry_delay = 0.5 * (2 ** retry)
|
| 352 |
+
# logger.warning(
|
| 353 |
+
# f"VoiceKit call timed out after {timeout_seconds}s (attempt {retry + 1}/{max_retries}), retrying in {retry_delay}s"
|
| 354 |
+
# )
|
| 355 |
await asyncio.sleep(retry_delay)
|
| 356 |
else:
|
| 357 |
logger.error(f"VoiceKit call timed out after {max_retries} attempts")
|
|
|
|
| 393 |
logger.error(f"VoiceKit returned empty text. Full result: {result}")
|
| 394 |
return {"error": "VoiceKit returned empty text"}
|
| 395 |
|
| 396 |
+
# logger.debug(f"VoiceKit raw response: {scores_text[:500]}")
|
| 397 |
|
| 398 |
try:
|
| 399 |
scores = json.loads(scores_text)
|
|
|
|
| 405 |
|
| 406 |
# Total time
|
| 407 |
total_time = (time.time() - start_time) * 1000
|
| 408 |
+
# logger.info(f"⏱️ TOTAL VoiceKit TIME: {total_time:.1f}ms")
|
| 409 |
|
| 410 |
return {
|
| 411 |
"pitch": scores.get("pitch", 0),
|
gemini_adapter.py
CHANGED
|
@@ -187,7 +187,8 @@ def call_gemini_with_tools(model_name, system_prompt, messages, tools, max_token
|
|
| 187 |
for i, part in enumerate(candidate.content.parts):
|
| 188 |
if hasattr(part, 'function_call') and part.function_call:
|
| 189 |
# print(f"DEBUG gemini_adapter: Part {i} has function_call: {part.function_call.name}")
|
| 190 |
-
print(f"DEBUG gemini_adapter: Function args: {dict(part.function_call.args) if part.function_call.args else {}}")
|
|
|
|
| 191 |
return response
|
| 192 |
|
| 193 |
except Exception as e:
|
|
|
|
| 187 |
for i, part in enumerate(candidate.content.parts):
|
| 188 |
if hasattr(part, 'function_call') and part.function_call:
|
| 189 |
# print(f"DEBUG gemini_adapter: Part {i} has function_call: {part.function_call.name}")
|
| 190 |
+
# print(f"DEBUG gemini_adapter: Function args: {dict(part.function_call.args) if part.function_call.args else {}}")
|
| 191 |
+
pass
|
| 192 |
return response
|
| 193 |
|
| 194 |
except Exception as e:
|