MARICL / examples /synthetic_data /agent_step.py
rezapop's picture
Add MARICL paper (PDF + LaTeX source) and code
ee2fc0d verified
Raw History Blame Contribute Delete
3.68 kB
"""One step of an agent-answered MARICL run (the only command the answering agent uses).
python agent_step.py --task TASK --seed S # print the pending LLM request (or DONE)
python agent_step.py --task TASK --seed S <<'JSON' # answer it, then print the next request
{ ...one JSON object matching the requested schema... }
JSON
"""
from __future__ import annotations
import argparse
import importlib
import json
import os
import sys
HERE = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, HERE)
from claude_backend import install_import_shims # noqa: E402
install_import_shims()
import maricl_core as mc # noqa: E402
from bridge import BridgeLLM, NeedResponse # noqa: E402
SCHEMAS = {"Hypothesis": mc.Hypothesis, "Correction": mc.Correction, "Critique": mc.Critique}
def show(req: dict, root: str, task: str, seed: int) -> None:
answered = len(os.listdir(os.path.join(root, "responses")))
props = req["json_schema"]["properties"]
print(f"=== REQUEST {req['id']} | answer schema: {req['schema']} | {answered} answered so far ===")
print("[SYSTEM PROMPT]")
print(req["system"])
print("\n[USER PROMPT]")
print(req["user"])
print("\n[ANSWER FORMAT] one JSON object with exactly these fields:")
for name, spec in props.items():
kind = spec.get("type", "string")
if kind == "array":
kind = "array of strings"
print(f" - {name} ({kind}): {spec.get('description', '')}")
print(f"\nAnswer with:\npython agent_step.py --task {task} --seed {seed} <<'JSON'\n{{ ... }}\nJSON")
def main() -> int:
ap = argparse.ArgumentParser()
ap.add_argument("--task", choices=["regression", "classification"], required=True)
ap.add_argument("--seed", type=int, required=True)
ap.add_argument("--T", type=int, default=10)
args = ap.parse_args()
example = importlib.import_module(args.task)
root = os.path.join(HERE, "recorded_answers", args.task, f"seed{args.seed}")
os.makedirs(os.path.join(root, "responses"), exist_ok=True)
pending_path = os.path.join(root, "pending.json")
answer_text = "" if sys.stdin is None or sys.stdin.isatty() else sys.stdin.read().strip()
if answer_text:
if not os.path.exists(pending_path):
print("No pending request. Run without input to see it.")
return 1
pending = json.load(open(pending_path))
try:
obj = json.loads(answer_text)
SCHEMAS[pending["schema"]].model_validate(obj)
except Exception as exc: # malformed JSON or schema mismatch: ask again
print(f"ANSWER REJECTED for request {pending['id']}: {exc}\nFix the JSON and answer again.\n")
show(pending, root, args.task, args.seed)
return 2
with open(os.path.join(root, "responses", f"{pending['id']}.json"), "w") as fh:
json.dump(obj, fh, indent=2)
os.remove(pending_path)
counter = {"n": 0}
llm = BridgeLLM(root, "base", counter)
llm_creative = BridgeLLM(root, "encoder", counter)
try:
example.run_experiment(args.seed, args.T, llm, llm_creative,
out_dir=os.path.join(HERE, "results", args.task), tag=f"seed{args.seed}",
fit_log=os.path.join(root, "fit_log.txt"))
except NeedResponse as need:
with open(pending_path, "w") as fh:
json.dump(need.request, fh, indent=2)
show(need.request, root, args.task, args.seed)
return 0
print(f"=== DONE: all LLM requests for seed {args.seed} are answered. Stop here. ===")
return 0
if __name__ == "__main__":
sys.exit(main())