opus-max-record / harness /scripts /check_render_parity.py
simonycl's picture
Upload folder using huggingface_hub
b2ebc95 verified
Raw
History Blame Contribute Delete
2.51 kB
#!/usr/bin/env python3
"""Show that the RL rollout path and the serving path render different system prompts.
The renderer serialises whatever tool objects it is handed. verifiers hands it its own flat
`ToolSpec`, so the tool block comes out as {"name":…,"description":…,"parameters":…}; the served
chat template emits {"type":"function","function":{…}}. That is a ~68-character difference in the
system prompt on *every turn* of an RL rollout, which is why GRPO through pi scores 0 on tasks
the same harness solves ~16% of the time under the eval client.
Fix (in shared verifiers, so not done here): hand the renderer OAI-nested tools.
python3 scripts/check_render_parity.py [ckpt] [trace.jsonl]
"""
import copy, json, sys
from transformers import AutoTokenizer
from renderers.base import create_renderer
from renderers.configs import Qwen35RendererConfig
WS = "/mnt/pvc/users/simon/agentptb/runs/a-opus-max/workspace"
ckpt = sys.argv[1] if len(sys.argv) > 1 else f"{WS}/ckpt/sft_v5/weights/step_900"
trace = sys.argv[2] if len(sys.argv) > 2 else f"{WS}/runs/verify_ws/traces.jsonl"
tk = AutoTokenizer.from_pretrained(ckpt)
rend = create_renderer(tk, Qwen35RendererConfig())
t = [json.loads(l) for l in open(trace)][0]["traces"][0]
msgs = [n["message"] for n in t["nodes"][:6]]
tools = t["tools"]
oai = [{"type": "function", "function": {"name": x["name"], "description": x.get("description", ""),
"parameters": x.get("parameters")}} for x in tools]
srv_msgs = []
for m in copy.deepcopy(msgs):
if m.get("tool_calls"):
m["tool_calls"] = [{"id": tc.get("id"), "type": "function",
"function": {"name": tc.get("name"),
"arguments": json.loads(tc.get("arguments") or "{}")}}
for tc in m["tool_calls"]]
if isinstance(m.get("content"), list):
m["content"] = "".join(p.get("text", "") for p in m["content"] if isinstance(p, dict))
srv_msgs.append(m)
served = tk.apply_chat_template(srv_msgs, tools=oai, tokenize=False, add_generation_prompt=True)
flat = tk.decode(list(rend.render_ids(msgs, tools=tools, add_generation_prompt=True)))
nested = tk.decode(list(rend.render_ids(msgs, tools=oai, add_generation_prompt=True)))
print("renderer(flat ToolSpec) == served template :", flat == served)
print("renderer(OAI-nested) == served template :", nested == served)
print("system-prompt delta (chars):", len(served) - len(flat))