Skip to content

Commit 9d651eb

Browse files
committed
Add Log error for provider issues
1 parent 9a4fae4 commit 9d651eb

File tree

3 files changed

+282
-17
lines changed

3 files changed

+282
-17
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@ build/
1818
tests/.placeholder_tests/
1919
.telemetry/
2020
/plan/
21+
/experiments

src/core/llm/providers/ollama.py

Lines changed: 125 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)