| import os |
| import sys |
| import torch |
| import sentencepiece as spm |
|
|
| |
| ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) |
| sys.path.insert(0, ROOT) |
|
|
| from model.config import VaghLMConfig |
| from model.transformer import VaghLM |
|
|
| def run_generation(): |
| |
| config = VaghLMConfig() |
| device = torch.device("cuda" if torch.cuda.is_available() else "cpu") |
| print(f"Using device: {device}") |
|
|
| |
| tokenizer_path = os.path.join(ROOT, "tokenizer", "vocab", "tokenizer.model") |
| if not os.path.exists(tokenizer_path): |
| raise FileNotFoundError(f"Tokenizer not found at {tokenizer_path}. Please check your installation.") |
| |
| sp = spm.SentencePieceProcessor() |
| sp.load(tokenizer_path) |
| print(f"[OK] Tokenizer loaded successfully (Vocab size: {sp.vocab_size()})") |
|
|
| |
| model = VaghLM(config) |
| |
| |
| |
| checkpoint_names = ["finetuned_v2_best.pt", "best_checkpoint.pt"] |
| checkpoint_path = None |
| |
| for ckpt_name in checkpoint_names: |
| p = os.path.join(ROOT, "checkpoints", ckpt_name) |
| if os.path.exists(p): |
| checkpoint_path = p |
| break |
| |
| if checkpoint_path is None: |
| print("[WARNING] No pre-trained checkpoint found in checkpoints/. Initializing with random weights.") |
| else: |
| print(f"Loading checkpoint: {checkpoint_path}") |
| ckpt = torch.load(checkpoint_path, map_location=device) |
| model.load_state_dict(ckpt["model_state"]) |
| print(f"[OK] Model weights loaded (Step: {ckpt.get('step', 'N/A')}, Loss: {ckpt.get('loss', 'N/A'):.4f})") |
| |
| model.to(device) |
| model.eval() |
| print(f"Model parameters: {model.count_parameters():,}") |
|
|
| |
| BOS_ID = config.bos_id |
| USER_ID = config.user_id |
| ASSISTANT_ID = config.assistant_id |
| EOS_ID = config.eos_id |
|
|
| |
| prompt = "Explain what a black hole is." |
| max_new_tokens = 150 |
| temperature = 0.7 |
| top_k = 40 |
| top_p = 0.9 |
| repetition_penalty = 1.3 |
|
|
| print(f"\nPrompt: {prompt}") |
| print(f"Generation Parameters: temp={temperature}, top_k={top_k}, top_p={top_p}, rep_penalty={repetition_penalty}") |
| print("-" * 50) |
|
|
| |
| user_tokens = sp.encode(prompt) |
| input_ids = [BOS_ID, USER_ID] + user_tokens + [ASSISTANT_ID] |
| |
| x = torch.tensor([input_ids], dtype=torch.long, device=device) |
| generated = [] |
|
|
| |
| with torch.no_grad(): |
| for _ in range(max_new_tokens): |
| |
| if x.size(1) > config.context_length: |
| x = x[:, -config.context_length:] |
|
|
| |
| logits, _ = model(x) |
| logits = logits[:, -1, :] |
|
|
| |
| for token_id in set(x[0].tolist()): |
| if logits[0, token_id] > 0: |
| logits[0, token_id] /= repetition_penalty |
| else: |
| logits[0, token_id] *= repetition_penalty |
|
|
| |
| if temperature > 0: |
| logits = logits / temperature |
|
|
| |
| if top_k is not None and top_k > 0: |
| values, _ = torch.topk(logits, min(top_k, logits.size(-1))) |
| logits[logits < values[:, [-1]]] = -float("inf") |
|
|
| |
| if top_p is not None and top_p < 1.0: |
| sorted_logits, sorted_indices = torch.sort(logits, descending=True) |
| cumulative_probs = torch.cumsum(torch.softmax(sorted_logits, dim=-1), dim=-1) |
| |
| |
| sorted_indices_to_remove = (cumulative_probs - torch.softmax(sorted_logits, dim=-1)) > top_p |
| sorted_logits[sorted_indices_to_remove] = -float("inf") |
| |
| |
| logits = torch.zeros_like(logits).scatter_(1, sorted_indices, sorted_logits) |
|
|
| |
| if temperature == 0: |
| next_token = torch.argmax(logits, dim=-1, keepdim=True) |
| else: |
| probs = torch.softmax(logits, dim=-1) |
| next_token = torch.multinomial(probs, num_samples=1) |
|
|
| x = torch.cat([x, next_token], dim=1) |
| token_val = next_token.item() |
| generated.append(token_val) |
|
|
| |
| if token_val == EOS_ID: |
| break |
|
|
| |
| response = sp.decode(generated) |
| print(f"\nResponse:\n{response}\n") |
|
|
| if __name__ == "__main__": |
| run_generation() |
|
|