fix: recover empty validation compilations
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
"label": "Ollama Models",
|
||||
"description": "Inspect, manage, and chat with local Ollama models, including shared persistent conversations, performance metrics, images, PDFs, URLs, and live memory telemetry.",
|
||||
"icon": "Cpu",
|
||||
"version": "1.7.9",
|
||||
"version": "1.7.10",
|
||||
"tab": {"path": "/ollama-manager", "position": "after:models"},
|
||||
"entry": "dist/index.js",
|
||||
"css": "dist/style.css",
|
||||
|
||||
@@ -2150,13 +2150,13 @@ def _run_validation_harness(
|
||||
metrics.append(_persist_metric(conversation_id, final_id, primary, final_state, status="completed"))
|
||||
final_message = final_result.get("message") if isinstance(final_result.get("message"), dict) else {}
|
||||
final_content = str(final_message.get("content") or "").strip()
|
||||
if not final_content:
|
||||
raise HTTPException(502, "Primary model returned an empty compiled answer")
|
||||
if _looks_like_validation_report(final_content):
|
||||
compiler_needs_retry = not final_content or _looks_like_validation_report(final_content)
|
||||
if compiler_needs_retry:
|
||||
retry_id = uuid.uuid4().hex
|
||||
retry_started = time.time()
|
||||
retry_reason = "empty output" if not final_content else "review text"
|
||||
_persist_chat_stage(request_id, "compiler-retry", primary, "running", retry_started)
|
||||
_persist_chat_event(request_id, conversation_id, "compiler-retry-started", level="warning", stage="Primary returned review text; requesting final answer", model=primary)
|
||||
_persist_chat_event(request_id, conversation_id, "compiler-retry-started", level="warning", stage=f"Primary returned {retry_reason}; requesting final answer", model=primary)
|
||||
_chat_state(retry_id, state="preparing", stage="Preparing final-answer retry", model=primary, parent_id=request_id, conversation_id=conversation_id)
|
||||
retry_payload = _chat_payload(
|
||||
body,
|
||||
@@ -2178,8 +2178,8 @@ def _run_validation_harness(
|
||||
_persist_chat_event(request_id, conversation_id, "compiler-retry-completed", stage="Final answer retry completed", model=primary, payload={"output_chars": len(final_content)})
|
||||
else:
|
||||
final_content = draft
|
||||
_persist_chat_stage(request_id, "compiler-retry", primary, "fallback", retry_started, finished_at=retry_finished, output_chars=len(final_content), error="Primary returned review text twice; preserved the primary draft")
|
||||
_persist_chat_event(request_id, conversation_id, "compiler-retry-fallback", level="warning", stage="Preserved primary draft after invalid finalization", model=primary, payload={"output_chars": len(final_content)})
|
||||
_persist_chat_stage(request_id, "compiler-retry", primary, "fallback", retry_started, finished_at=retry_finished, output_chars=len(final_content), error=f"Primary returned {retry_reason} twice; preserved the primary draft")
|
||||
_persist_chat_event(request_id, conversation_id, "compiler-retry-fallback", level="warning", stage="Preserved primary draft after invalid finalization", model=primary, payload={"output_chars": len(final_content), "reason": retry_reason})
|
||||
compiler_finished = time.time()
|
||||
_persist_chat_stage(request_id, "compiler", primary, "completed", compiler_started, finished_at=compiler_finished, output_chars=len(final_content))
|
||||
_persist_chat_event(request_id, conversation_id, "compiler-completed", stage="Primary final answer compiled", model=primary, payload={"output_chars": len(final_content)})
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
name: ollama-manager
|
||||
version: 1.7.9
|
||||
version: 1.7.10
|
||||
description: Native dashboard manager and chat interface for local Ollama models, attachments, URLs, shared persistent conversations, performance metrics, and live runtime telemetry.
|
||||
auto_install_dependencies: true
|
||||
python_dependencies:
|
||||
|
||||
@@ -178,6 +178,42 @@ class ValidationHarnessTests(unittest.TestCase):
|
||||
self.assertEqual(len(metrics), 4)
|
||||
self.assertTrue(any("IMPORTANT FINALIZATION RETRY" in prompt for _, prompt in calls))
|
||||
|
||||
def test_empty_compiler_output_is_retried_and_never_becomes_a_502(self):
|
||||
body = api.ChatRequest(primary_model="primary", validator_models=["validator"], harness=True, message="Write the requested result")
|
||||
calls = []
|
||||
|
||||
def fake_stream(payload, request_id, cancel_event=None, parent_id=None):
|
||||
model = payload["model"]
|
||||
prompt = payload["messages"][-1]["content"]
|
||||
calls.append((model, prompt))
|
||||
if model == "validator":
|
||||
content = "Make the result more specific."
|
||||
elif "IMPORTANT FINALIZATION RETRY" in prompt:
|
||||
content = "refined final answer after empty compiler output"
|
||||
elif "VALIDATION REPORTS:" in prompt:
|
||||
content = ""
|
||||
else:
|
||||
content = "primary draft"
|
||||
return {"message": {"role": "assistant", "content": content}, "done": True}
|
||||
|
||||
def fake_metric(conversation_id, request_id, model, state, status=None, error=""):
|
||||
return {"request_id": request_id, "model": model, "status": status}
|
||||
|
||||
with patch.object(api, "_require_installed_model", side_effect=lambda name: name), patch.object(
|
||||
api, "_stream_chat_request", side_effect=fake_stream
|
||||
), patch.object(api, "_persist_metric", side_effect=fake_metric), patch.object(
|
||||
api, "_persist_chat_stage"
|
||||
), patch.object(api, "_persist_chat_event"), patch.object(api, "_chat_state"):
|
||||
final, metrics, reports = api._run_validation_harness(
|
||||
body, "root-request", "conversation", "primary", ["validator"], threading.Event(), []
|
||||
)
|
||||
|
||||
self.assertEqual(final, "refined final answer after empty compiler output")
|
||||
self.assertEqual(len(reports), 1)
|
||||
self.assertEqual(len(metrics), 4)
|
||||
self.assertTrue(any("Primary returned empty output" in prompt for _, prompt in calls) or any("IMPORTANT FINALIZATION RETRY" in prompt for _, prompt in calls))
|
||||
|
||||
|
||||
def test_status_omits_full_catalog_by_default(self):
|
||||
with patch.object(api, "_local_tags", return_value=[]), patch.object(api, "_local_ps", return_value=[]), patch.object(
|
||||
api, "_ensure_catalog", return_value={"models": [], "families": {}, "source": "test"}
|
||||
|
||||
Reference in New Issue
Block a user