MLVXN commited on
Commit
5797bb9
·
verified ·
1 Parent(s): 18f41dc

feat: add chat_loop.py

Browse files
Files changed (1) hide show
  1. chat_loop.py +115 -0
chat_loop.py ADDED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ MicroLLM2 Interactive Chat Loop
4
+ - Loads MLVXN/MicroLLM2 (or local ./microllm2-checkpoints/final_merged)
5
+ - ChatML: <|im_start|>user / assistant
6
+ - Works on H100 (bf16) and local CPU
7
+ - Run: python chat_loop.py [--local] [--temp 0.7]
8
+
9
+ No token hardcoded — uses HF_TOKEN env if private, else public pull.
10
+ """
11
+ import os, sys, torch
12
+ from pathlib import Path
13
+
14
+ # Use local checkpoint if available (faster on H100), else HF
15
+ LOCAL = Path("/home/zeus/microllm2/microllm2-checkpoints/final_merged")
16
+ HF_ID = "MLVXN/MicroLLM2"
17
+ MODEL_ID = str(LOCAL) if LOCAL.exists() else HF_ID
18
+
19
+ # Allow override
20
+ if "--local" in sys.argv and LOCAL.exists():
21
+ MODEL_ID = str(LOCAL)
22
+ elif "--hf" in sys.argv:
23
+ MODEL_ID = HF_ID
24
+
25
+ print(f"[*] Loading MicroLLM2 from {MODEL_ID} ...")
26
+ try:
27
+ from transformers import AutoTokenizer, AutoModelForCausalLM
28
+ except ImportError:
29
+ print("pip install transformers accelerate torch"); sys.exit(1)
30
+
31
+ tok = AutoTokenizer.from_pretrained(MODEL_ID, trust_remote_code=False)
32
+ if tok.pad_token is None:
33
+ tok.pad_token = tok.eos_token
34
+ # Ensure ChatML tokens exist
35
+ if "<|im_start|>" not in tok.get_vocab():
36
+ tok.add_special_tokens({"additional_special_tokens": ["<|im_start|>", "<|im_end|>"]})
37
+
38
+ dtype = torch.bfloat16 if torch.cuda.is_available() else torch.float32
39
+ device_map = "auto" if torch.cuda.is_available() else None
40
+ try:
41
+ model = AutoModelForCausalLM.from_pretrained(
42
+ MODEL_ID, torch_dtype=dtype, device_map=device_map,
43
+ trust_remote_code=False, attn_implementation="sdpa"
44
+ )
45
+ except Exception as e:
46
+ print(f"[!] sdpa load failed {e}, retry without attn arg")
47
+ model = AutoModelForCausalLM.from_pretrained(MODEL_ID, torch_dtype=dtype, device_map=device_map)
48
+
49
+ model.eval()
50
+ device = next(model.parameters()).device
51
+ print(f"[+] Loaded on {device} ({dtype}) — {model.num_parameters()/1e9:.2f}B params")
52
+ print(f"[+] MicroLLM2 by Maximalist Labs — type 'exit' to quit, 'clear' to reset history\n")
53
+
54
+ # Chat history as list of dicts for ChatML
55
+ history = []
56
+
57
+ def format_prompt(history, user_msg):
58
+ # Build ChatML prompt
59
+ msgs = history + [{"role": "user", "content": user_msg}]
60
+ parts = []
61
+ for m in msgs:
62
+ parts.append(f"<|im_start|>{m['role']}\n{m['content']}<|im_end|>")
63
+ parts.append("<|im_start|>assistant\n")
64
+ return "\n".join(parts)
65
+
66
+ # Generation defaults — tuned for GPT2-XL 1.5B chat
67
+ temp = 0.7
68
+ top_p = 0.9
69
+ max_new = 120
70
+ if "--temp" in sys.argv:
71
+ try: temp = float(sys.argv[sys.argv.index("--temp")+1])
72
+ except: pass
73
+
74
+ while True:
75
+ try:
76
+ user = input("\nYou: ").strip()
77
+ except (EOFError, KeyboardInterrupt):
78
+ print("\nbye"); break
79
+ if not user:
80
+ continue
81
+ if user.lower() in ("exit","quit","q"):
82
+ break
83
+ if user.lower() in ("clear","reset","new"):
84
+ history = []; print("[*] history cleared"); continue
85
+
86
+ prompt = format_prompt(history, user)
87
+ inputs = tok(prompt, return_tensors="pt", truncation=True, max_length=900).to(device)
88
+
89
+ # Warn if truncated (1024 limit)
90
+ if inputs.input_ids.shape[1] >= 900:
91
+ print("[!] near 1024 ctx — consider 'clear'")
92
+
93
+ with torch.no_grad():
94
+ out = model.generate(
95
+ **inputs, max_new_tokens=max_new, do_sample=(temp>0),
96
+ temperature=temp if temp>0 else 1.0, top_p=top_p,
97
+ repetition_penalty=1.1, pad_token_id=tok.eos_token_id,
98
+ eos_token_id=tok.convert_tokens_to_ids("<|im_end|>") if "<|im_end|>" in tok.get_vocab() else tok.eos_token_id,
99
+ )
100
+ # Decode only new tokens
101
+ gen = out[0][inputs.input_ids.shape[1]:]
102
+ text = tok.decode(gen, skip_special_tokens=False)
103
+ # Strip ChatML tail
104
+ if "<|im_end|>" in text:
105
+ text = text.split("<|im_end|>")[0]
106
+ text = text.replace("<|endoftext|>", "").strip()
107
+ print(f"\nMicroLLM2: {text}")
108
+
109
+ # Keep history (trim to last 6 turns to stay <1024)
110
+ history.append({"role": "user", "content": user})
111
+ history.append({"role": "assistant", "content": text})
112
+ if len(history) > 12:
113
+ history = history[-12:]
114
+
115
+ print("done")