Skip to content

Commit 750ed09

Browse files
committed
.
1 parent aff0476 commit 750ed09

File tree

4 files changed

+319
-70
lines changed

4 files changed

+319
-70
lines changed

src/core/llm_client.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44
from typing import Optional, Dict, Any
55

66
from src.config import API_ENDPOINT, DEFAULT_MODEL
7-
from src.core.llm_providers import create_llm_provider, LLMProvider
7+
from src.core.llm_providers import create_llm_provider, LLMProvider, ContextOverflowError
8+
9+
# Re-export for convenience
10+
__all__ = ['LLMClient', 'default_client', 'create_llm_client', 'ContextOverflowError']
811

912

1013
class LLMClient:

src/core/llm_providers.py

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -338,9 +338,22 @@ async def generate(self, prompt: str, timeout: int = REQUEST_TIMEOUT,
338338
continue
339339
return None
340340
except httpx.HTTPStatusError as e:
341-
print(f"OpenAI API HTTP Error (attempt {attempt + 1}/{MAX_TRANSLATION_ATTEMPTS}): {e}")
341+
error_message = str(e)
342+
error_body = ""
342343
if hasattr(e, 'response') and hasattr(e.response, 'text'):
343-
print(f"Response details: Status {e.response.status_code}, Body: {e.response.text[:500]}...")
344+
error_body = e.response.text[:500]
345+
error_message = f"{e} - {error_body}"
346+
347+
print(f"OpenAI API HTTP Error (attempt {attempt + 1}/{MAX_TRANSLATION_ATTEMPTS}): {e}")
348+
if error_body:
349+
print(f"Response details: Status {e.response.status_code}, Body: {error_body}...")
350+
351+
# Detect context overflow errors (OpenAI uses "context_length_exceeded" or similar)
352+
context_overflow_keywords = ["context_length", "maximum context", "token limit",
353+
"too many tokens", "reduce the length", "max_tokens"]
354+
if any(keyword in error_message.lower() for keyword in context_overflow_keywords):
355+
raise ContextOverflowError(f"OpenAI context overflow: {error_message}")
356+
344357
if attempt < MAX_TRANSLATION_ATTEMPTS - 1:
345358
await asyncio.sleep(RETRY_DELAY_SECONDS)
346359
continue
@@ -606,8 +619,10 @@ async def generate(self, prompt: str, timeout: int = REQUEST_TIMEOUT,
606619
return None
607620
except httpx.HTTPStatusError as e:
608621
error_body = ""
622+
error_message = str(e)
609623
if hasattr(e, 'response') and hasattr(e.response, 'text'):
610624
error_body = e.response.text[:500]
625+
error_message = f"{e} - {error_body}"
611626

612627
# Parse OpenRouter specific error messages
613628
if e.response.status_code == 404:
@@ -622,6 +637,13 @@ async def generate(self, prompt: str, timeout: int = REQUEST_TIMEOUT,
622637
print(f"OpenRouter API HTTP Error (attempt {attempt + 1}/{MAX_TRANSLATION_ATTEMPTS}): {e}")
623638
print(f"Response details: Status {e.response.status_code}, Body: {error_body}...")
624639

640+
# Detect context overflow errors
641+
context_overflow_keywords = ["context_length", "maximum context", "token limit",
642+
"too many tokens", "reduce the length", "max_tokens",
643+
"context window", "exceeds"]
644+
if any(keyword in error_message.lower() for keyword in context_overflow_keywords):
645+
raise ContextOverflowError(f"OpenRouter context overflow: {error_message}")
646+
625647
if attempt < MAX_TRANSLATION_ATTEMPTS - 1:
626648
await asyncio.sleep(RETRY_DELAY_SECONDS)
627649
continue
@@ -771,9 +793,22 @@ async def generate(self, prompt: str, timeout: int = REQUEST_TIMEOUT,
771793
continue
772794
return None
773795
except httpx.HTTPStatusError as e:
774-
print(f"Gemini API HTTP Error (attempt {attempt + 1}/{MAX_TRANSLATION_ATTEMPTS}): {e}")
796+
error_message = str(e)
797+
error_body = ""
775798
if hasattr(e, 'response') and hasattr(e.response, 'text'):
776-
print(f"Response details: Status {e.response.status_code}, Body: {e.response.text[:200]}...")
799+
error_body = e.response.text[:500]
800+
error_message = f"{e} - {error_body}"
801+
802+
print(f"Gemini API HTTP Error (attempt {attempt + 1}/{MAX_TRANSLATION_ATTEMPTS}): {e}")
803+
if error_body:
804+
print(f"Response details: Status {e.response.status_code}, Body: {error_body[:200]}...")
805+
806+
# Detect context overflow errors (Gemini uses "RESOURCE_EXHAUSTED" or token limits)
807+
context_overflow_keywords = ["resource_exhausted", "token limit", "input too long",
808+
"maximum input", "context length", "too many tokens"]
809+
if any(keyword in error_message.lower() for keyword in context_overflow_keywords):
810+
raise ContextOverflowError(f"Gemini context overflow: {error_message}")
811+
777812
if attempt < MAX_TRANSLATION_ATTEMPTS - 1:
778813
await asyncio.sleep(RETRY_DELAY_SECONDS)
779814
continue

src/core/subtitle_translator.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@ async def translate_subtitles(subtitles: List[Dict[str, str]], source_language:
9797
)
9898

9999
if translated_text is not None:
100-
translations[idx] = translated_text
100+
# Single point of cleaning for subtitles
101+
translations[idx] = clean_translated_text(translated_text)
101102
completed_count += 1
102103
else:
103104
# Keep original text if translation fails

0 commit comments

Comments
 (0)