Skip to content

utils

genlm.eval.domains.ds1000.utils

unwrap_redeclared_function(solution, code_context)

If the model answered a DS-1000 body-insertion slot with a standalone function that re-declares the one the slot already opens (def f(df): template + def f(df): ... answer), return just the function body so insertion doesn't IndentationError. Conservative: fires only when the slot is a def, the solution is one top-level FunctionDef, and the names match. Otherwise returns the solution unchanged, preserving a bare-body answer's indentation. See genlm/rollouts issue #18.

Source code in genlm/eval/domains/ds1000/utils.py
def unwrap_redeclared_function(solution: str, code_context: str) -> str:
    """If the model answered a DS-1000 body-insertion slot with a *standalone* function that
    re-declares the one the slot already opens (`def f(df):` template + `def f(df): ...` answer),
    return just the function body so insertion doesn't `IndentationError`. Conservative: fires
    only when the slot is a `def`, the solution is one top-level FunctionDef, and the names match.
    Otherwise returns the solution unchanged, preserving a bare-body answer's indentation. See
    genlm/rollouts issue #18."""
    head = _insert_slot_def(code_context)
    if not head:
        return solution
    slot_name = head[4:head.find("(")].strip()
    try:
        tree = ast.parse(solution)
    except SyntaxError:
        return solution
    if len(tree.body) == 1 and isinstance(tree.body[0], ast.FunctionDef):
        fn = tree.body[0]
        if fn.name == slot_name and fn.body:
            lines = solution.splitlines()
            body = "\n".join(lines[fn.body[0].lineno - 1:])
            # DS-1000 bodies are uniformly indented under the slot's `def`, so the body keeps
            # its own valid indentation; return as-is.
            return body if body.strip() else solution
    return solution