JustScriptzz commited on
Commit
eaea5c6
·
verified ·
1 Parent(s): 8a49240

Upload chat.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. chat.py +204 -0
chat.py ADDED
@@ -0,0 +1,204 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import sys
3
+ import os
4
+
5
+ def run_nexus(weights_path):
6
+ sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src'))
7
+
8
+ from src.trainer import load_nexus
9
+ from tokenizers import Tokenizer
10
+ import torch.nn.functional as F
11
+
12
+ model, config = load_nexus(weights_path)
13
+
14
+ device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
15
+ model = model.to(device)
16
+
17
+ tokenizer_path = os.path.join(os.path.dirname(weights_path), '..', 'data', 'tokenizer.json')
18
+ tokenizer_path = os.path.normpath(tokenizer_path)
19
+
20
+ if not os.path.exists(tokenizer_path):
21
+ tokenizer_path = os.path.join(os.path.dirname(__file__), 'data', 'tokenizer.json')
22
+
23
+ tokenizer = Tokenizer.from_file(tokenizer_path)
24
+
25
+ print("\n{Nexus SmAll v1} Chat Interface")
26
+ print("{Nexus SmAll v1} Type 'exit' to quit, 'clear' to reset conversation")
27
+ print("{Nexus SmAll v1} Type '--temp 0.5' to change temperature")
28
+ print("{Nexus SmAll v1} Type '--help' for all commands\n")
29
+
30
+ bos_id = tokenizer.token_to_id("<bos>") if tokenizer.token_to_id("<bos>") is not None else 1
31
+ eos_id = tokenizer.token_to_id("<eos>") if tokenizer.token_to_id("<eos>") is not None else 2
32
+
33
+ conversation = [bos_id]
34
+
35
+ temperature = 0.2
36
+ top_k = 40
37
+ top_p = 0.9
38
+ max_tokens = 128
39
+ repetition_penalty = 1.2
40
+
41
+ while True:
42
+ try:
43
+ user_input = input("You: ").strip()
44
+
45
+ if not user_input:
46
+ continue
47
+ if user_input.lower() == 'exit':
48
+ print("Goodbye!")
49
+ break
50
+ elif user_input.lower() == 'clear':
51
+ conversation = [bos_id]
52
+ print("[Conversation reset]")
53
+ continue
54
+ elif user_input.startswith('--'):
55
+ parts = user_input.split()
56
+ if parts[0] == '--temp' and len(parts) >= 2:
57
+ temperature = float(parts[1])
58
+ print(f"[temperature={temperature}]")
59
+ continue
60
+ elif parts[0] == '--help':
61
+ print("Commands:")
62
+ print(" --temp <value> Set temperature (default 0.2)")
63
+ print(" --topk <value> Set top_k (default 40)")
64
+ print(" --topp <value> Set top_p (default 0.9)")
65
+ print(" --tokens <value> Set max new tokens (default 128)")
66
+ print(" --rep <value> Set repetition penalty (default 1.2)")
67
+ print(" clear Reset conversation")
68
+ print(" exit Exit")
69
+ continue
70
+ elif parts[0] == '--topk' and len(parts) >= 2:
71
+ top_k = int(parts[1])
72
+ print(f"[top_k={top_k}]")
73
+ continue
74
+ elif parts[0] == '--topp' and len(parts) >= 2:
75
+ top_p = float(parts[1])
76
+ print(f"[top_p={top_p}]")
77
+ continue
78
+ elif parts[0] == '--tokens' and len(parts) >= 2:
79
+ max_tokens = int(parts[1])
80
+ print(f"[max_tokens={max_tokens}]")
81
+ continue
82
+ elif parts[0] == '--rep' and len(parts) >= 2:
83
+ repetition_penalty = float(parts[1])
84
+ print(f"[repetition_penalty={repetition_penalty}]")
85
+ continue
86
+
87
+ prompt = f"\nUser: {user_input}\nAssistant:"
88
+ prompt_ids = tokenizer.encode(prompt).ids
89
+ input_ids = conversation + prompt_ids
90
+
91
+ if len(input_ids) > config.max_seq_len:
92
+ input_ids = input_ids[-config.max_seq_len + 64:]
93
+
94
+ input_tensor = torch.tensor([input_ids], dtype=torch.long, device=device)
95
+
96
+ generated_ids, full_ids = _generate_with_rep_penalty(
97
+ model, input_tensor, max_new_tokens=max_tokens,
98
+ temperature=temperature, top_k=top_k, top_p=top_p,
99
+ repetition_penalty=repetition_penalty,
100
+ eos_id=eos_id,
101
+ )
102
+
103
+ response_ids = full_ids[0, input_tensor.shape[1]:].tolist()
104
+ response_text = tokenizer.decode(response_ids)
105
+
106
+ if "<eos>" in response_text:
107
+ response_text = response_text[:response_text.index("<eos>")]
108
+ if "<bos>" in response_text:
109
+ response_text = response_text.replace("<bos>", "")
110
+ if "User:" in response_text:
111
+ response_text = response_text[:response_text.index("User:")]
112
+ if "Assistant:" in response_text:
113
+ response_text = response_text.replace("Assistant:", "")
114
+
115
+ response_text = response_text.strip()
116
+
117
+ if len(response_text) < 2:
118
+ response_text = "[no response]"
119
+
120
+ print(f"Nexus SmAll v1: {response_text}")
121
+
122
+ conversation = full_ids[0].tolist()
123
+ if eos_id is not None:
124
+ conversation.append(eos_id)
125
+
126
+ except KeyboardInterrupt:
127
+ print("\nGoodbye!")
128
+ break
129
+ except Exception as e:
130
+ print(f"[Error] {e}")
131
+ continue
132
+
133
+ def _generate_with_rep_penalty(model, input_ids, max_new_tokens, temperature, top_k, top_p, repetition_penalty, eos_id):
134
+ model.eval()
135
+
136
+ for _ in range(max_new_tokens):
137
+ seq_len = input_ids.shape[1]
138
+ if seq_len > model.config.max_seq_len:
139
+ input_ids = input_ids[:, -model.config.max_seq_len:]
140
+
141
+ with torch.no_grad():
142
+ logits = model(input_ids, 0)
143
+ logits = logits[:, -1, :]
144
+
145
+ if repetition_penalty != 1.0:
146
+ for batch_idx in range(logits.shape[0]):
147
+ for token_idx in range(input_ids.shape[1]):
148
+ token = input_ids[batch_idx, token_idx].item()
149
+ if logits[batch_idx, token] < 0:
150
+ logits[batch_idx, token] *= repetition_penalty
151
+ else:
152
+ logits[batch_idx, token] /= repetition_penalty
153
+
154
+ logits = logits / temperature
155
+
156
+ if top_k > 0:
157
+ top_k_values, _ = torch.topk(logits, min(top_k, logits.size(-1)))
158
+ min_top_k = top_k_values[:, -1].unsqueeze(-1)
159
+ logits = torch.where(logits < min_top_k,
160
+ torch.full_like(logits, float('-inf')), logits)
161
+
162
+ if top_p > 0 and top_p < 1.0:
163
+ sorted_logits, sorted_indices = torch.sort(logits, descending=True)
164
+ cumulative_probs = torch.cumsum(torch.nn.functional.softmax(sorted_logits, dim=-1), dim=-1)
165
+ sorted_indices_to_remove = cumulative_probs > top_p
166
+ sorted_indices_to_remove[:, 0] = False
167
+ indices_to_remove = torch.zeros_like(logits, dtype=torch.bool)
168
+ indices_to_remove = indices_to_remove.scatter(1, sorted_indices, sorted_indices_to_remove)
169
+ logits = torch.where(indices_to_remove,
170
+ torch.full_like(logits, float('-inf')), logits)
171
+
172
+ probs = torch.nn.functional.softmax(logits, dim=-1)
173
+ next_token = torch.multinomial(probs, num_samples=1)
174
+
175
+ input_ids = torch.cat([input_ids, next_token], dim=-1)
176
+
177
+ if eos_id is not None and next_token.item() == eos_id:
178
+ break
179
+
180
+ return None, input_ids
181
+
182
+ if __name__ == "__main__":
183
+ import argparse
184
+
185
+ parser = argparse.ArgumentParser(description="Nexus SmAll v1 Chat")
186
+ parser.add_argument("--weights", type=str, default="weights/nexus_final.pt",
187
+ help="Path to model weights (.pt file)")
188
+ parser.add_argument("--temp", type=float, default=0.2,
189
+ help="Temperature (default: 0.2)")
190
+ parser.add_argument("--top_k", type=int, default=40,
191
+ help="Top-k sampling (default: 40)")
192
+ parser.add_argument("--top_p", type=float, default=0.9,
193
+ help="Top-p sampling (default: 0.9)")
194
+ parser.add_argument("--max_tokens", type=int, default=128,
195
+ help="Max new tokens (default: 128)")
196
+ args = parser.parse_args()
197
+
198
+ if not os.path.exists(args.weights):
199
+ print(f"[Error] Weights not found: {args.weights}")
200
+ print("Make sure training completed successfully.")
201
+ input("Press Enter to exit...")
202
+ sys.exit(1)
203
+
204
+ run_nexus(args.weights)