58 lines
2.5 KiB
Python
58 lines
2.5 KiB
Python
|
|
import os, json, argparse
|
||
|
|
HERE = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||
|
|
os.environ["HF_HOME"] = os.path.join(HERE, "hf_cache")
|
||
|
|
|
||
|
|
import torch
|
||
|
|
from transformers import AutoModelForCausalLM, AutoTokenizer
|
||
|
|
from tools_common import TOOLS, parse_tool_calls
|
||
|
|
|
||
|
|
def norm_args(d):
|
||
|
|
return {k: (v.strip() if isinstance(v, str) else v) for k, v in (d or {}).items()}
|
||
|
|
|
||
|
|
def main():
|
||
|
|
ap = argparse.ArgumentParser()
|
||
|
|
ap.add_argument("--model", default="Qwen/Qwen3-0.6B")
|
||
|
|
ap.add_argument("--adapter", default=None)
|
||
|
|
ap.add_argument("--eval", default=os.path.join(HERE, "eval", "tools_eval.py"))
|
||
|
|
ap.add_argument("--out", default=os.path.join(HERE, "eval", "baseline_tools.json"))
|
||
|
|
a = ap.parse_args()
|
||
|
|
|
||
|
|
device = "cuda" if torch.cuda.is_available() else ("mps" if torch.backends.mps.is_available() else "cpu")
|
||
|
|
tok = AutoTokenizer.from_pretrained(a.model)
|
||
|
|
model = AutoModelForCausalLM.from_pretrained(a.model, dtype=torch.float32).to(device)
|
||
|
|
if a.adapter:
|
||
|
|
from peft import PeftModel
|
||
|
|
model = PeftModel.from_pretrained(model, a.adapter).to(device)
|
||
|
|
model.eval()
|
||
|
|
|
||
|
|
cases = [json.loads(l) for l in open(a.eval) if l.strip()]
|
||
|
|
results, name_hits, full_hits = [], 0, 0
|
||
|
|
|
||
|
|
for c in cases:
|
||
|
|
msgs = [{"role": "user", "content": c["query"]}]
|
||
|
|
text = tok.apply_chat_template(msgs, tools=TOOLS, tokenize=False,
|
||
|
|
add_generation_prompt=True, enable_thinking=False)
|
||
|
|
ids = tok(text, return_tensors="pt").to(device)
|
||
|
|
out = model.generate(**ids, max_new_tokens=128, do_sample=False)
|
||
|
|
reply = tok.decode(out[0][ids.input_ids.shape[1]:], skip_special_tokens=True)
|
||
|
|
|
||
|
|
calls = parse_tool_calls(reply)
|
||
|
|
got = calls[0] if calls else None
|
||
|
|
exp = c["expected"]
|
||
|
|
name_ok = bool(got) and got.get("name") == exp["name"]
|
||
|
|
full_ok = name_ok and norm_args(got.get("arguments")) == norm_args(exp["arguments"])
|
||
|
|
name_hits += name_ok
|
||
|
|
full_hits += full_ok
|
||
|
|
results.append({"query": c["query"], "expected": exp,
|
||
|
|
"got": got, "raw": reply,
|
||
|
|
"name_ok": name_ok, "full_ok": full_ok})
|
||
|
|
|
||
|
|
n = len(cases)
|
||
|
|
summary = {"model": a.model, "adapter": a.adapter, "n": n,
|
||
|
|
"name_acc": round(name_hits / n, 3),
|
||
|
|
"full_acc": round(full_hits / n, 3)}
|
||
|
|
json.dump({"summary": summary, "results": results}, open(a.out, "w"), indent=2)
|
||
|
|
print(json.dumps(summary, indent=2))
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
main()
|