Source code for evoproc_procedures.repairs
"""LLM-assisted repair helpers (backend-agnostic).
These functions *use* your pure validators to diagnose issues, then call a
provided `query_fn` to ask an LLM to minimally fix the JSON so it validates.
They don't import a specific backend; you pass a `query_fn` with signature:
query_fn(prompt: str, model: str, fmt: dict | None = None, seed: int | None = None) -> str
"""
from __future__ import annotations
from typing import Any, Dict, Callable, Optional
import json
from evoproc_procedures.models import Procedure
from evoproc.validators import validate_procedure_structured
JSON = Dict[str, Any]
QueryFn = Callable[[str, str, Optional[Dict[str, Any]], Optional[int]], str]
[docs]
def repair_procedure_structured(
proc: JSON,
*,
model: str,
query_fn: QueryFn,
max_tries: int = 10,
print_diagnostics: bool = False,
) -> JSON:
"""Iteratively repair a procedure JSON until it passes validation.
Args:
proc: Procedure JSON to repair.
model: LLM model name.
query_fn: Backend function to call the LLM (see signature above).
max_tries: Maximum number of repair attempts.
print_diagnostics: If True, prints diagnostics each loop.
Returns:
A structurally valid procedure JSON.
Raises:
RuntimeError: If the procedure could not be validated after `max_tries`.
"""
schema_json = Procedure.model_json_schema()
for _ in range(max_tries):
diags = validate_procedure_structured(proc)
if not diags:
return proc
if print_diagnostics:
print("[repair] diagnostics:")
for d in diags:
print(" -", d)
diag_str = "\n- ".join(str(i) for i in diags)
repair_prompt = (
"You will make the requested minimal structural fixes to the following "
"procedure JSON so that it validates against the schema.\n\n"
"# Schema (verbatim)\n"
f"{json.dumps(schema_json, ensure_ascii=False)}\n\n"
"# Fix Instructions\n"
f"- {diag_str}\n\n"
"# Procedure JSON\n"
f"{json.dumps(proc, ensure_ascii=False)}\n\n"
"Return ONLY the corrected JSON object. No commentary."
)
raw = query_fn(repair_prompt, model, schema_json, 1234)
try:
proc = json.loads(raw) if isinstance(raw, str) else raw
except Exception:
# keep looping; try again
continue
raise RuntimeError("Could not satisfy validator after retries.")