| import torch, joblib |
| from transformers import AutoModelForCausalLM, AutoTokenizer |
| from peft import PeftModel |
| from sentence_transformers import SentenceTransformer |
|
|
| BASE = "microsoft/bitnet-b1.58-2B-4T-bf16" |
| ADAPTERS = { |
| "mult": "UlukaDev/bitnet-2digit-mult-expert", |
| "roman": "UlukaDev/bitnet-roman-numeral-expert", |
| } |
| SYS = "You are a careful calculator. Work step by step, then end with exactly 'The answer is X'." |
|
|
| tok = AutoTokenizer.from_pretrained(BASE) |
| if tok.pad_token is None: tok.pad_token = tok.eos_token |
| tok.padding_side = "left" |
|
|
| base = AutoModelForCausalLM.from_pretrained(BASE, torch_dtype=torch.bfloat16, device_map="auto") |
| names = list(ADAPTERS) |
| model = PeftModel.from_pretrained(base, ADAPTERS[names[0]], adapter_name=names[0]) |
| for n in names[1:]: |
| model.load_adapter(ADAPTERS[n], adapter_name=n) |
| model.eval() |
|
|
| enc = SentenceTransformer("all-MiniLM-L6-v2") |
| clf = joblib.load("router.joblib") |
|
|
| def route(q): |
| return clf.predict(enc.encode([q], normalize_embeddings=True))[0] |
|
|
| @torch.no_grad() |
| def moe_generate(q, max_new_tokens=250): |
| expert = route(q) |
| model.set_adapter(expert) |
| msgs = [{"role":"system","content":SYS}, {"role":"user","content":q}] |
| enc_in = tok.apply_chat_template(msgs, add_generation_prompt=True, |
| return_tensors="pt", return_dict=True).to(model.device) |
| in_len = enc_in["input_ids"].shape[1] |
| out = model.generate(**enc_in, max_new_tokens=max_new_tokens, do_sample=False) |
| return expert, tok.decode(out[0, in_len:], skip_special_tokens=True) |
|
|
| if __name__ == "__main__": |
| for q in ["What is 34 times 57?", "Convert 1994 to Roman numerals"]: |
| expert, ans = moe_generate(q) |
| print(f"[{expert}] {q}\n -> {ans}\n") |
|
|