diff --git a/engine_distribute.py b/engine_distribute.py index c3b3015..f231ee6 100644 --- a/engine_distribute.py +++ b/engine_distribute.py @@ -76,6 +76,11 @@ def run_distribution(in_queue, args): llm_paragraph_msg = f"[LLM-PARAGRAPH]: {speaker_prefix}{paragraph_text}" print(llm_paragraph_msg, flush=True) log_debug(llm_paragraph_msg) + + if payload.get("paragraph_fallback") and paragraph_text: + paragraph_msg = f"[PARAGRAPH]: {speaker_prefix}{paragraph_text}" + print(paragraph_msg, flush=True) + log_debug(paragraph_msg) for lang in ["es", "fr", "ar", "en"]: if payload.get(lang): diff --git a/engine_llm.py b/engine_llm.py index 728fe42..3cd75e5 100644 --- a/engine_llm.py +++ b/engine_llm.py @@ -29,6 +29,23 @@ def run_llm_processor(in_queue, out_queue, args): is_openai = args.post_correct_model.startswith("gpt-") llm_state = {"line_warned": False, "paragraph_warned": False} + def check_ollama_health(): + try: + response = requests.get("http://127.0.0.1:11434/api/tags", timeout=2.5) + response.raise_for_status() + data = response.json() + models = data.get("models", []) + available = {model.get("name") for model in models if model.get("name")} + if args.post_correct_model not in available and f"{args.post_correct_model}:latest" not in available: + print(f"[LLM] Configured Ollama model '{args.post_correct_model}' is not installed.") + return True + except Exception as exc: + print(f"[LLM] Ollama health check failed ({exc}). Local LLM features may fall back.") + return False + + if not is_openai: + check_ollama_health() + def normalize_english_caption(text): normalized = " ".join((text or "").split()).strip() if normalized and normalized[0].isalpha(): @@ -86,7 +103,8 @@ def run_llm_processor(in_queue, out_queue, args): return call_ollama(prompt, temperature) except Exception as exc: if not llm_state[warn_key]: - print(f"[LLM] {warn_key.replace('_', ' ').title()} unavailable ({exc}). Falling back to deterministic text.") + label = "Paragraph LLM" if warn_key == "paragraph_warned" else "Line LLM" + print(f"[LLM] {label} unavailable ({exc}). Falling back to deterministic text.") llm_state[warn_key] = True return "" @@ -182,6 +200,7 @@ def run_llm_processor(in_queue, out_queue, args): elif len(pending_buffer) >= 1 and (time.time() - last_llm_call_time) > 15: should_refine = True structured_paragraph = None + paragraph_from_llm = False if args.llm_paragraph and should_refine: new_batch = " ".join(pending_buffer) result = call_llm_rolling_refine(new_batch, active_context) @@ -199,6 +218,7 @@ def run_llm_processor(in_queue, out_queue, args): # No break, just update the context active_context = result structured_paragraph = result + paragraph_from_llm = True else: structured_paragraph = new_batch active_context = new_batch @@ -212,7 +232,7 @@ def run_llm_processor(in_queue, out_queue, args): "paragraph": structured_paragraph, "en_bridge": bridge_text, "used_llm_line": bool(getattr(args, "post_correct_llm", False)), - "used_llm_paragraph": bool(args.llm_paragraph and structured_paragraph), + "used_llm_paragraph": paragraph_from_llm, "detected_lang": item.get("detected_lang"), "speaker": item.get("speaker"), "ts": item.get("ts", time.time()) diff --git a/engine_translate.py b/engine_translate.py index f51e6f0..37d015f 100644 --- a/engine_translate.py +++ b/engine_translate.py @@ -77,6 +77,7 @@ def run_translation(in_queue, out_queue, args): "en_bridge": item.get("en_bridge"), "used_llm_line": item.get("used_llm_line", False), "used_llm_paragraph": item.get("used_llm_paragraph", False), + "paragraph_fallback": bool(paragraph_text) and not item.get("used_llm_paragraph", False), "speaker": item.get("speaker"), "ts": item.get("ts", time.time()) }