bichnhan2701 commited on
Commit
557b80a
·
1 Parent(s): 1e5dfc2

fix error 503

Browse files
app/api/transcribe.py CHANGED
@@ -10,7 +10,6 @@ import time
10
  from app.core.audio_utils import save_upload_file, get_audio_info, ensure_wav_16k_mono, make_temp_path, download_file_from_url
11
  from app.core.asr_engine import load_model, transcribe_file, transcribe_file_chunks
12
  from app.config import settings
13
- from app.services.text_normalizer import normalize_text
14
  from app.services.nlp_postprocess import normalize_and_extract
15
  # Summary and mindmap generation moved to Note Service; do not import here
16
  from app.services.note_client import NoteServiceClient
 
10
  from app.core.audio_utils import save_upload_file, get_audio_info, ensure_wav_16k_mono, make_temp_path, download_file_from_url
11
  from app.core.asr_engine import load_model, transcribe_file, transcribe_file_chunks
12
  from app.config import settings
 
13
  from app.services.nlp_postprocess import normalize_and_extract
14
  # Summary and mindmap generation moved to Note Service; do not import here
15
  from app.services.note_client import NoteServiceClient
app/services/nlp_postprocess.py CHANGED
@@ -1,6 +1,8 @@
1
  import asyncio
2
  import json
3
  import logging
 
 
4
 
5
  from app.infra.redis_client import redis_client
6
  from app.utils.hashing import sha256
@@ -17,6 +19,9 @@ except Exception:
17
  pass
18
 
19
  CACHE_TTL = 60 * 60 * 24 * 3 # 3 days
 
 
 
20
 
21
  # Tạo client Gemini nếu có API key
22
  _gemini_client = None
@@ -89,8 +94,43 @@ Cấu trúc JSON bắt buộc (chỉ trả JSON, không giải thích thêm):
89
  # resp.text là chuỗi model trả (có thể chứa code block)
90
  return resp.text
91
 
92
- try:
93
- text = await loop.run_in_executor(None, call)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  if text:
95
  # clean JSON
96
  start = text.find("{")
@@ -106,10 +146,6 @@ Cấu trúc JSON bắt buộc (chỉ trả JSON, không giải thích thêm):
106
  logging.warning(f"[nlp_postprocess] Failed to parse Gemini JSON, fallback to raw_text: {e}")
107
  else:
108
  logging.warning("[nlp_postprocess] Gemini response has no JSON block, fallback to raw_text")
109
- except GoogleAPIError as e:
110
- logging.error(f"[nlp_postprocess] Gemini API error: {e}")
111
- except Exception as e:
112
- logging.exception(f"[nlp_postprocess] Gemini call failed, fallback to raw_text: {e}")
113
 
114
  # 4) Try write back to Redis (best effort)
115
  try:
 
1
  import asyncio
2
  import json
3
  import logging
4
+ import random
5
+ import time
6
 
7
  from app.infra.redis_client import redis_client
8
  from app.utils.hashing import sha256
 
19
  pass
20
 
21
  CACHE_TTL = 60 * 60 * 24 * 3 # 3 days
22
+ # Retry settings for transient model errors (503 / UNAVAILABLE)
23
+ RETRY_MAX_ATTEMPTS = 3
24
+ RETRY_BASE_BACKOFF = 1.0
25
 
26
  # Tạo client Gemini nếu có API key
27
  _gemini_client = None
 
94
  # resp.text là chuỗi model trả (có thể chứa code block)
95
  return resp.text
96
 
97
+ # Try with a small exponential backoff for transient server errors
98
+ text = None
99
+ attempt = 0
100
+ while attempt < RETRY_MAX_ATTEMPTS:
101
+ attempt += 1
102
+ try:
103
+ text = await loop.run_in_executor(None, call)
104
+ break
105
+ except Exception as e:
106
+ # Try to detect transient server-side/genai errors (503 / UNAVAILABLE)
107
+ is_transient = False
108
+ try:
109
+ # try to import genai-specific ServerError if available
110
+ from google.genai import errors as _genai_errors # type: ignore
111
+ ServerError = getattr(_genai_errors, "ServerError", None)
112
+ except Exception:
113
+ ServerError = None
114
+
115
+ if ServerError is not None and isinstance(e, ServerError):
116
+ is_transient = True
117
+ else:
118
+ msg = str(e)
119
+ if "503" in msg or "UNAVAILABLE" in msg.upper() or "model is overloaded" in msg.lower():
120
+ is_transient = True
121
+
122
+ if is_transient and attempt < RETRY_MAX_ATTEMPTS:
123
+ backoff = RETRY_BASE_BACKOFF * (2 ** (attempt - 1)) + random.uniform(0, 0.5)
124
+ logging.warning(f"[nlp_postprocess] Gemini transient error (attempt {attempt}): {e}; retrying in {backoff:.1f}s")
125
+ # use asyncio.sleep to not block event loop
126
+ await asyncio.sleep(backoff)
127
+ continue
128
+ else:
129
+ logging.exception(f"[nlp_postprocess] Gemini call failed, fallback to raw_text: {e}")
130
+ text = None
131
+ break
132
+
133
+ if text:
134
  if text:
135
  # clean JSON
136
  start = text.find("{")
 
146
  logging.warning(f"[nlp_postprocess] Failed to parse Gemini JSON, fallback to raw_text: {e}")
147
  else:
148
  logging.warning("[nlp_postprocess] Gemini response has no JSON block, fallback to raw_text")
 
 
 
 
149
 
150
  # 4) Try write back to Redis (best effort)
151
  try: