diff --git a/services/heretic2-nvfp4-quant/quant_nvfp4.py b/services/heretic2-nvfp4-quant/quant_nvfp4.py index 6ae012d..ffad1f5 100644 --- a/services/heretic2-nvfp4-quant/quant_nvfp4.py +++ b/services/heretic2-nvfp4-quant/quant_nvfp4.py @@ -61,6 +61,14 @@ def load_calib_chat(path, tokenizer, seqlen): rows = [json.loads(l) for l in open(path) if l.strip()] out = [] for r in rows: + # Tool_call arguments arrive as OpenAI wire-form JSON *strings*; the Qwen3.6 + # template does .items() on them → needs a dict. Parse string→dict so the + # forward-pass sees the qwen3_coder XML the seat emits. (render_verify finding.) + for m in r["messages"]: + for tc in (m.get("tool_calls") or []): + a = tc.get("function", {}).get("arguments") + if isinstance(a, str): + tc["function"]["arguments"] = json.loads(a) text = tokenizer.apply_chat_template( r["messages"], tools=r.get("tools"), tokenize=False, add_generation_prompt=False, enable_thinking=True, diff --git a/services/heretic2-nvfp4-quant/render_verify.py b/services/heretic2-nvfp4-quant/render_verify.py new file mode 100644 index 0000000..cdbf885 --- /dev/null +++ b/services/heretic2-nvfp4-quant/render_verify.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 +"""Render-verify a tool-call-XML calib row through the Qwen3.6 chat template. + +brokkr's last gate before the production calib enters the quant: confirm the +assistant tool_calls serialize to the qwen3_coder XML the LIVE seat emits +(`\n\n...`), so the calibration +forward-pass sees the seat's REAL tool-call activations (#355-preservation). + +Usage: python3 render_verify.py [row_index] +""" +import json +import sys + +from transformers import AutoTokenizer + +tok_dir, calib = sys.argv[1], sys.argv[2] +idx = int(sys.argv[3]) if len(sys.argv) > 3 else 0 + +tok = AutoTokenizer.from_pretrained(tok_dir, trust_remote_code=True) +with open(calib) as f: + row = json.loads([l for l in f if l.strip()][idx]) + +# Tool_call arguments arrive in OpenAI wire form (a JSON *string*), but the Qwen3.6 +# chat template does .items() on them → needs a dict. Parse string→dict so the +# template renders the qwen3_coder XML. (render-verify finding.) +for m in row["messages"]: + for tc in (m.get("tool_calls") or []): + a = tc.get("function", {}).get("arguments") + if isinstance(a, str): + tc["function"]["arguments"] = json.loads(a) + +tools = row.get("tools", []) +print("=== tools:", [t.get("function", {}).get("name") for t in tools]) +print("=== message roles:", [m.get("role") for m in row["messages"]]) + +text = tok.apply_chat_template( + row["messages"], tools=tools, + tokenize=False, add_generation_prompt=False, enable_thinking=True, +) +print(f"=== rendered ({len(text)} chars) ===") +print(text) +print("=== qwen3_coder XML markers present? ===") +for m in ("", "", "bifrost.soong-lab."): + print(f" {m!r}: {m in text}")