Views
No views yet
train.py and inference.py. Have fun :-)1"""
2StorySupra-10M — Interactive Story Generator
3Loads model weights directly from HuggingFace: SupraLabs/StorySupra-10M
4"""
5
6import torch
7from transformers import LlamaForCausalLM, PreTrainedTokenizerFast
8
9# ──────────────────────────────────────────────
10# Configuration
11# ──────────────────────────────────────────────
12MODEL_ID = "SupraLabs/StorySupra-10M"
13
14GENERATION_DEFAULTS = {
15 "max_new_tokens": 100,
16 "temperature": 0.55,
17 "top_k": 25,
18 "top_p": 0.85,
19 "repetition_penalty": 1.1,
20 "do_sample": True,
21}
22
23EXIT_COMMANDS = {"exit", "quit", "leave"}
24
25# ──────────────────────────────────────────────
26# Model loading
27# ──────────────────────────────────────────────
28
29def load_model(model_id: str):
30 """Download and return the tokenizer and model from HuggingFace Hub."""
31 print(f"Downloading model from HuggingFace: {model_id}")
32 print("(This may take a moment on first run — weights will be cached locally.)\n")
33
34 tokenizer = PreTrainedTokenizerFast.from_pretrained(model_id)
35 model = LlamaForCausalLM.from_pretrained(model_id)
36
37 device = "cuda" if torch.cuda.is_available() else "cpu"
38 print(f"Using device: {device}\n")
39
40 model.to(device)
41 model.eval()
42
43 return tokenizer, model, device
44
45
46# ──────────────────────────────────────────────
47# Text generation
48# ──────────────────────────────────────────────
49
50def generate_text(
51 prompt: str,
52 tokenizer,
53 model,
54 device: str,
55 max_new_tokens: int = GENERATION_DEFAULTS["max_new_tokens"],
56 temperature: float = GENERATION_DEFAULTS["temperature"],
57 top_k: int = GENERATION_DEFAULTS["top_k"],
58 top_p: float = GENERATION_DEFAULTS["top_p"],
59 repetition_penalty: float = GENERATION_DEFAULTS["repetition_penalty"],
60) -> str:
61 """Generate a story continuation from the given prompt."""
62 inputs = tokenizer(prompt, return_tensors="pt").to(device)
63
64 with torch.no_grad():
65 output_tokens = model.generate(
66 **inputs,
67 max_new_tokens=max_new_tokens,
68 do_sample=True,
69 temperature=temperature,
70 top_k=top_k,
71 top_p=top_p,
72 repetition_penalty=repetition_penalty,
73 pad_token_id=tokenizer.pad_token_id,
74 eos_token_id=tokenizer.eos_token_id,
75 )
76
77 return tokenizer.decode(output_tokens[0], skip_special_tokens=True)
78
79
80# ──────────────────────────────────────────────
81# Interactive loop
82# ──────────────────────────────────────────────
83
84def run():
85 print("=" * 50)
86 print(" StorySupra-10M — Interactive Story Generator")
87 print("=" * 50)
88
89 tokenizer, model, device = load_model(MODEL_ID)
90
91 print("-" * 50)
92 print("Model ready! Type a prompt to generate a story.")
93 print(f"Type {' / '.join(EXIT_COMMANDS)} to quit.")
94 print("-" * 50)
95
96 while True:
97 try:
98 user_prompt = input("\nYour prompt: ").strip()
99 except (EOFError, KeyboardInterrupt):
100 print("\nExiting. Goodbye!")
101 break
102
103 if not user_prompt:
104 print("Please enter a prompt.")
105 continue
106
107 if user_prompt.lower() in EXIT_COMMANDS:
108 print("Goodbye!")
109 break
110
111 print("\nGenerating...\n")
112 story = generate_text(user_prompt, tokenizer, model, device)
113
114 print("Generated story:")
115 print("-" * 20)
116 print(story)
117 print("-" * 20)
118
119
120# ──────────────────────────────────────────────
121# Entry point
122# ──────────────────────────────────────────────
123
124if __name__ == "__main__":
125 run()