| |
| """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)) |
|
|