vigneshwar234 commited on
Commit
97ade79
·
verified ·
1 Parent(s): d4f884d

Add inference.py

Browse files
Files changed (1) hide show
  1. inference.py +138 -0
inference.py ADDED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ TemporalMesh Transformer — Inference Script
3
+ Full greedy / top-p / top-k text generation with exit gate analysis.
4
+ """
5
+
6
+ import torch
7
+ import torch.nn.functional as F
8
+ from tmt.model.config import TMTConfig
9
+ from tmt.model.model import TMTModel
10
+
11
+
12
+ def load_model(checkpoint_path: str = None, config: TMTConfig = None) -> TMTModel:
13
+ if config is None:
14
+ config = TMTConfig(
15
+ vocab_size=50258, d_model=512, n_heads=8, n_layers=12,
16
+ graph_k=8, exit_threshold=0.85, memory_anchors=16, max_seq_len=256,
17
+ )
18
+ model = TMTModel(config)
19
+ if checkpoint_path:
20
+ ckpt = torch.load(checkpoint_path, map_location="cpu")
21
+ model.load_state_dict(ckpt["model_state"])
22
+ model.eval()
23
+ return model
24
+
25
+
26
+ @torch.no_grad()
27
+ def generate(
28
+ model: TMTModel,
29
+ input_ids: torch.Tensor,
30
+ max_new_tokens: int = 64,
31
+ temperature: float = 1.0,
32
+ top_k: int = 50,
33
+ top_p: float = 0.95,
34
+ do_sample: bool = True,
35
+ ) -> dict:
36
+ """
37
+ Generate tokens autoregressively. Returns generated ids + exit analysis.
38
+ """
39
+ device = next(model.parameters()).device
40
+ input_ids = input_ids.to(device)
41
+ generated = input_ids.clone()
42
+ all_exit_stats = []
43
+
44
+ for _ in range(max_new_tokens):
45
+ output = model(generated)
46
+ logits = output.logits[:, -1, :] / temperature # (B, V)
47
+
48
+ if top_k > 0:
49
+ values, _ = torch.topk(logits, top_k)
50
+ logits[logits < values[:, -1:]] = -float("Inf")
51
+
52
+ if top_p < 1.0:
53
+ sorted_logits, sorted_idx = torch.sort(logits, descending=True)
54
+ cumulative = torch.cumsum(F.softmax(sorted_logits, dim=-1), dim=-1)
55
+ remove = cumulative - F.softmax(sorted_logits, dim=-1) > top_p
56
+ remove[:, 1:] = remove[:, :-1].clone()
57
+ remove[:, 0] = False
58
+ sorted_logits[remove] = -float("Inf")
59
+ logits.scatter_(1, sorted_idx, sorted_logits)
60
+
61
+ probs = F.softmax(logits, dim=-1)
62
+ next_token = (
63
+ torch.multinomial(probs, num_samples=1) if do_sample
64
+ else logits.argmax(dim=-1, keepdim=True)
65
+ )
66
+ generated = torch.cat([generated, next_token], dim=1)
67
+
68
+ # capture exit stats for this step
69
+ step_exit = {
70
+ "exit_rates": [m.float().mean().item() for m in output.exit_masks],
71
+ "avg_confidence": [c.mean().item() for c in output.confidences],
72
+ }
73
+ all_exit_stats.append(step_exit)
74
+
75
+ # stop at max_seq_len
76
+ if generated.shape[1] >= model.config.max_seq_len:
77
+ break
78
+
79
+ avg_compute = sum(
80
+ sum(s["exit_rates"]) / len(s["exit_rates"])
81
+ for s in all_exit_stats
82
+ ) / len(all_exit_stats)
83
+
84
+ return {
85
+ "generated_ids": generated,
86
+ "new_tokens": generated[:, input_ids.shape[1]:],
87
+ "exit_stats": all_exit_stats,
88
+ "avg_compute_used": round(avg_compute, 3),
89
+ }
90
+
91
+
92
+ def analyse_sequence(model: TMTModel, input_ids: torch.Tensor) -> None:
93
+ """
94
+ Run a single forward pass and print detailed exit gate analysis.
95
+ """
96
+ device = next(model.parameters()).device
97
+ with torch.no_grad():
98
+ output = model(input_ids.to(device))
99
+
100
+ S = input_ids.shape[1]
101
+ print(f"\n{'='*55}")
102
+ print(f" TMT Sequence Analysis (seq_len={S})")
103
+ print(f"{'='*55}")
104
+ print(f" Logits shape: {output.logits.shape}")
105
+ print(f" Graph edges: {output.graph_edges[0].shape[1]} active edges")
106
+ print(f" Memory state: {output.memory_state.shape}\n")
107
+ print(f" {'Layer':<8} {'Tokens frozen':>14} {'Exit rate':>12} {'Avg conf':>10}")
108
+ print(f" {'-'*46}")
109
+
110
+ total_frozen = 0
111
+ for i, (mask, conf) in enumerate(zip(output.exit_masks, output.confidences)):
112
+ n_frozen = mask.sum().item()
113
+ total_frozen += n_frozen
114
+ rate = n_frozen / S
115
+ avg_c = conf.mean().item()
116
+ print(f" {i+1:<8} {n_frozen:>14} {rate:>11.1%} {avg_c:>10.3f}")
117
+
118
+ print(f" {'-'*46}")
119
+ print(f" Total compute fraction: {total_frozen/(S*len(output.exit_masks)):.1%} of max")
120
+ print(f" Active graph edges: {output.graph_edges[0].shape[1]}")
121
+ print(f"{'='*55}\n")
122
+
123
+
124
+ if __name__ == "__main__":
125
+ print("Loading TMT-Small for quick demo...")
126
+ cfg = TMTConfig(
127
+ vocab_size=50258, d_model=256, n_heads=4, n_layers=6,
128
+ graph_k=4, exit_threshold=0.80, memory_anchors=8, max_seq_len=128,
129
+ )
130
+ model = load_model(config=cfg)
131
+ print(f"Parameters: {sum(p.numel() for p in model.parameters()):,}")
132
+
133
+ ids = torch.randint(100, 50000, (1, 32))
134
+ analyse_sequence(model, ids)
135
+
136
+ result = generate(model, ids, max_new_tokens=16, do_sample=False)
137
+ print(f"Generated {result['new_tokens'].shape[1]} new tokens.")
138
+ print(f"Avg compute used per step: {result['avg_compute_used']:.1%}")