@@ -486,12 +486,47 @@ async def generate(self, prompt: str, timeout: int = REQUEST_TIMEOUT,
486486 was_truncated = was_truncated
487487 )
488488
489- except httpx .TimeoutException :
489+ except httpx .TimeoutException as e :
490+ RED = '\033 [91m'
491+ YELLOW = '\033 [93m'
492+ RESET = '\033 [0m'
493+
494+ if self .log_callback :
495+ self .log_callback ("llm_timeout" ,
496+ f"{ YELLOW } ⚠️ LLM request timeout (attempt { attempt + 1 } /{ MAX_TRANSLATION_ATTEMPTS } ){ RESET } \n "
497+ f"{ YELLOW } Model: { self .model } { RESET } \n "
498+ f"{ YELLOW } Possible causes:{ RESET } \n "
499+ f"{ YELLOW } - Model crashed or became unresponsive{ RESET } \n "
500+ f"{ YELLOW } - Server overloaded or out of memory{ RESET } \n "
501+ f"{ YELLOW } - Network connectivity issues{ RESET } " )
502+ else :
503+ print (f"{ YELLOW } ⚠️ LLM timeout (attempt { attempt + 1 } /{ MAX_TRANSLATION_ATTEMPTS } ): { e } { RESET } " )
504+
490505 if attempt < MAX_TRANSLATION_ATTEMPTS - 1 :
506+ if self .log_callback :
507+ self .log_callback ("llm_retry" , f" Retrying in 2 seconds..." )
491508 await asyncio .sleep (2 )
492509 continue
510+
511+ # All retry attempts exhausted
512+ if self .log_callback :
513+ self .log_callback ("llm_timeout_fatal" ,
514+ f"{ RED } ❌ All { MAX_TRANSLATION_ATTEMPTS } retry attempts exhausted{ RESET } \n "
515+ f"{ RED } Translation failed - unable to reach LLM server{ RESET } \n "
516+ f"{ RED } Recommendations:{ RESET } \n "
517+ f"{ RED } 1. Check if Ollama/llama.cpp server is running{ RESET } \n "
518+ f"{ RED } 2. Verify model is loaded: ollama list{ RESET } \n "
519+ f"{ RED } 3. Check server logs for crashes{ RESET } \n "
520+ f"{ RED } 4. Try reducing context size or chunk size{ RESET } " )
521+ else :
522+ print (f"{ RED } ❌ All retry attempts exhausted. Translation failed.{ RESET } " )
523+
493524 return None
494525 except httpx .HTTPStatusError as e :
526+ RED = '\033 [91m'
527+ YELLOW = '\033 [93m'
528+ RESET = '\033 [0m'
529+
495530 error_message = str (e )
496531 if e .response :
497532 try :
@@ -500,26 +535,110 @@ async def generate(self, prompt: str, timeout: int = REQUEST_TIMEOUT,
500535 except :
501536 pass
502537
538+ # Handle context overflow errors
503539 if any (keyword in error_message .lower ()
504540 for keyword in ["context" , "truncate" , "length" , "too long" ]):
505541 if self .log_callback :
506- self .log_callback ("error" ,
507- f"Context size exceeded! Prompt is too large for model's context window.\n "
508- f"Error: { error_message } \n "
509- f"Consider: 1) Reducing chunk_size, or 2) Increasing OLLAMA_NUM_CTX" )
542+ self .log_callback ("llm_context_overflow" ,
543+ f"{ RED } ❌ Context size exceeded!{ RESET } \n "
544+ f"{ RED } Prompt is too large for model's context window{ RESET } \n "
545+ f"{ RED } Current context window: { self .context_window } tokens{ RESET } \n "
546+ f"{ RED } Error: { error_message } { RESET } \n "
547+ f"{ YELLOW } Solutions:{ RESET } \n "
548+ f"{ YELLOW } 1. Reduce max_tokens_per_chunk (current chunk may be too large){ RESET } \n "
549+ f"{ YELLOW } 2. Increase OLLAMA_NUM_CTX in .env file{ RESET } \n "
550+ f"{ YELLOW } 3. Use a model with larger context window{ RESET } " )
551+ else :
552+ print (f"{ RED } Context size exceeded: { error_message } { RESET } " )
510553 raise ContextOverflowError (error_message )
511554
555+ # Handle other HTTP errors
556+ if self .log_callback :
557+ self .log_callback ("llm_http_error" ,
558+ f"{ YELLOW } ⚠️ HTTP error from LLM server (attempt { attempt + 1 } /{ MAX_TRANSLATION_ATTEMPTS } ){ RESET } \n "
559+ f"{ YELLOW } Status: { e .response .status_code if e .response else 'unknown' } { RESET } \n "
560+ f"{ YELLOW } Error: { error_message } { RESET } \n "
561+ f"{ YELLOW } Model: { self .model } { RESET } " )
562+ else :
563+ print (f"{ YELLOW } HTTP error (attempt { attempt + 1 } ): { error_message } { RESET } " )
564+
512565 if attempt < MAX_TRANSLATION_ATTEMPTS - 1 :
566+ if self .log_callback :
567+ self .log_callback ("llm_retry" , f" Retrying in 2 seconds..." )
513568 await asyncio .sleep (2 )
514569 continue
570+
571+ # All retries exhausted
572+ if self .log_callback :
573+ self .log_callback ("llm_http_error_fatal" ,
574+ f"{ RED } ❌ All { MAX_TRANSLATION_ATTEMPTS } retry attempts exhausted{ RESET } \n "
575+ f"{ RED } HTTP error persists - translation failed{ RESET } " )
576+ else :
577+ print (f"{ RED } ❌ All retry attempts exhausted. Translation failed.{ RESET } " )
578+
515579 return None
516580 except (RepetitionLoopError , ContextOverflowError ):
517581 # These errors should propagate up for handling by translator
518582 raise
519- except (json .JSONDecodeError , Exception ) as e :
583+ except json .JSONDecodeError as e :
584+ RED = '\033 [91m'
585+ YELLOW = '\033 [93m'
586+ RESET = '\033 [0m'
587+
588+ if self .log_callback :
589+ self .log_callback ("llm_json_error" ,
590+ f"{ YELLOW } ⚠️ Invalid JSON response from LLM (attempt { attempt + 1 } /{ MAX_TRANSLATION_ATTEMPTS } ){ RESET } \n "
591+ f"{ YELLOW } Model: { self .model } { RESET } \n "
592+ f"{ YELLOW } Error: { str (e )} { RESET } \n "
593+ f"{ YELLOW } This may indicate:{ RESET } \n "
594+ f"{ YELLOW } - Server returned malformed response{ RESET } \n "
595+ f"{ YELLOW } - Model output corrupted{ RESET } \n "
596+ f"{ YELLOW } - API endpoint incompatibility{ RESET } " )
597+ else :
598+ print (f"{ YELLOW } JSON decode error (attempt { attempt + 1 } ): { e } { RESET } " )
599+
600+ if attempt < MAX_TRANSLATION_ATTEMPTS - 1 :
601+ if self .log_callback :
602+ self .log_callback ("llm_retry" , f" Retrying in 2 seconds..." )
603+ await asyncio .sleep (2 )
604+ continue
605+
606+ if self .log_callback :
607+ self .log_callback ("llm_json_error_fatal" ,
608+ f"{ RED } ❌ All { MAX_TRANSLATION_ATTEMPTS } retry attempts exhausted{ RESET } \n "
609+ f"{ RED } Unable to parse LLM response - translation failed{ RESET } " )
610+ else :
611+ print (f"{ RED } ❌ All retry attempts exhausted. Translation failed.{ RESET } " )
612+
613+ return None
614+ except Exception as e :
615+ RED = '\033 [91m'
616+ YELLOW = '\033 [93m'
617+ RESET = '\033 [0m'
618+
619+ if self .log_callback :
620+ self .log_callback ("llm_unexpected_error" ,
621+ f"{ YELLOW } ⚠️ Unexpected error during LLM request (attempt { attempt + 1 } /{ MAX_TRANSLATION_ATTEMPTS } ){ RESET } \n "
622+ f"{ YELLOW } Model: { self .model } { RESET } \n "
623+ f"{ YELLOW } Error type: { type (e ).__name__ } { RESET } \n "
624+ f"{ YELLOW } Error: { str (e )} { RESET } " )
625+ else :
626+ print (f"{ YELLOW } Unexpected error (attempt { attempt + 1 } ): { type (e ).__name__ } : { e } { RESET } " )
627+
520628 if attempt < MAX_TRANSLATION_ATTEMPTS - 1 :
629+ if self .log_callback :
630+ self .log_callback ("llm_retry" , f" Retrying in 2 seconds..." )
521631 await asyncio .sleep (2 )
522632 continue
633+
634+ if self .log_callback :
635+ self .log_callback ("llm_unexpected_error_fatal" ,
636+ f"{ RED } ❌ All { MAX_TRANSLATION_ATTEMPTS } retry attempts exhausted{ RESET } \n "
637+ f"{ RED } Unexpected error persists - translation failed{ RESET } \n "
638+ f"{ RED } Please report this issue with the error details above{ RESET } " )
639+ else :
640+ print (f"{ RED } ❌ All retry attempts exhausted. Translation failed.{ RESET } " )
641+
523642 return None
524643
525644 return None
0 commit comments