JayF14 commited on
Commit
816b76b
·
verified ·
1 Parent(s): 11f637d

Upload chat.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. chat.py +170 -0
chat.py ADDED
@@ -0,0 +1,170 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import torch.nn as nn
3
+ from torch.nn import functional as F
4
+ import sys
5
+ import re
6
+ from indic_transliteration import sanscript
7
+ from indic_transliteration.sanscript import transliterate
8
+
9
+ # 1. COPY HYPERPARAMETERS & MODEL ARCHITECTURE
10
+ # (Must match train_llm.py EXACTLY)
11
+ block_size = 256
12
+ n_embd = 384
13
+ n_head = 6
14
+ n_layer = 6
15
+ dropout = 0.2
16
+ device = 'cuda' if torch.cuda.is_available() else 'cpu'
17
+
18
+ # Load the dataset to rebuild the vocabulary mapping
19
+ with open('dataset_awadhi_tulsidas_verified.txt', 'r', encoding='utf-8') as f:
20
+ text = f.read()
21
+
22
+ chars = sorted(list(set(text)))
23
+ vocab_size = len(chars)
24
+
25
+ stoi = { ch:i for i,ch in enumerate(chars) }
26
+ itos = { i:ch for i,ch in enumerate(chars) }
27
+ def encode(s):
28
+ unknown = [c for c in s if c not in stoi]
29
+ if unknown:
30
+ raise ValueError(f"Unsupported character(s) in Devanagari output: {unknown}. Make sure you only use standard Hindi characters.")
31
+ return [stoi[c] for c in s]
32
+ decode = lambda l: ''.join([itos[i] for i in l])
33
+
34
+ class Head(nn.Module):
35
+ def __init__(self, head_size):
36
+ super().__init__()
37
+ self.key = nn.Linear(n_embd, head_size, bias=False)
38
+ self.query = nn.Linear(n_embd, head_size, bias=False)
39
+ self.value = nn.Linear(n_embd, head_size, bias=False)
40
+ self.register_buffer('tril', torch.tril(torch.ones(block_size, block_size)))
41
+ self.dropout = nn.Dropout(dropout)
42
+
43
+ def forward(self, x):
44
+ B, T, C = x.shape
45
+ k = self.key(x)
46
+ q = self.query(x)
47
+ wei = q @ k.transpose(-2, -1) * (k.shape[-1] ** -0.5)
48
+ wei = wei.masked_fill(self.tril[:T, :T] == 0, float('-inf'))
49
+ wei = F.softmax(wei, dim=-1)
50
+ wei = self.dropout(wei)
51
+ v = self.value(x)
52
+ out = wei @ v
53
+ return out
54
+
55
+ class MultiHeadAttention(nn.Module):
56
+ def __init__(self, num_heads, head_size):
57
+ super().__init__()
58
+ self.heads = nn.ModuleList([Head(head_size) for _ in range(num_heads)])
59
+ self.proj = nn.Linear(n_embd, n_embd)
60
+ self.dropout = nn.Dropout(dropout)
61
+
62
+ def forward(self, x):
63
+ out = torch.cat([h(x) for h in self.heads], dim=-1)
64
+ out = self.dropout(self.proj(out))
65
+ return out
66
+
67
+ class FeedForward(nn.Module):
68
+ def __init__(self, n_embd):
69
+ super().__init__()
70
+ self.net = nn.Sequential(
71
+ nn.Linear(n_embd, 4 * n_embd),
72
+ nn.ReLU(),
73
+ nn.Linear(4 * n_embd, n_embd),
74
+ nn.Dropout(dropout),
75
+ )
76
+ def forward(self, x):
77
+ return self.net(x)
78
+
79
+ class Block(nn.Module):
80
+ def __init__(self, n_embd, n_head):
81
+ super().__init__()
82
+ head_size = n_embd // n_head
83
+ self.sa = MultiHeadAttention(n_head, head_size)
84
+ self.ffwd = FeedForward(n_embd)
85
+ self.ln1 = nn.LayerNorm(n_embd)
86
+ self.ln2 = nn.LayerNorm(n_embd)
87
+
88
+ def forward(self, x):
89
+ x = x + self.sa(self.ln1(x))
90
+ x = x + self.ffwd(self.ln2(x))
91
+ return x
92
+
93
+ class LanguageModel(nn.Module):
94
+ def __init__(self):
95
+ super().__init__()
96
+ self.token_embedding_table = nn.Embedding(vocab_size, n_embd)
97
+ self.position_embedding_table = nn.Embedding(block_size, n_embd)
98
+ self.blocks = nn.Sequential(*[Block(n_embd, n_head=n_head) for _ in range(n_layer)])
99
+ self.ln_f = nn.LayerNorm(n_embd)
100
+ self.lm_head = nn.Linear(n_embd, vocab_size)
101
+
102
+ def forward(self, idx, targets=None):
103
+ B, T = idx.shape
104
+ tok_emb = self.token_embedding_table(idx)
105
+ pos_emb = self.position_embedding_table(torch.arange(T, device=device))
106
+ x = tok_emb + pos_emb
107
+ x = self.blocks(x)
108
+ x = self.ln_f(x)
109
+ logits = self.lm_head(x)
110
+ return logits, None
111
+
112
+ def generate(self, idx, max_new_tokens):
113
+ for _ in range(max_new_tokens):
114
+ idx_cond = idx[:, -block_size:]
115
+ logits, _ = self(idx_cond)
116
+ logits = logits[:, -1, :]
117
+ probs = F.softmax(logits, dim=-1)
118
+ idx_next = torch.multinomial(probs, num_samples=1)
119
+ idx = torch.cat((idx, idx_next), dim=1)
120
+ return idx
121
+
122
+ # 2. LOAD TRAINED WEIGHTS
123
+ try:
124
+ print("Loading model weights from 'tulsidas_model.pth'...")
125
+ model = LanguageModel()
126
+ model.load_state_dict(torch.load('tulsidas_model.pth', map_location=device))
127
+ model = model.to(device)
128
+ model.eval() # Set to evaluation mode
129
+ print("Model loaded successfully!")
130
+ except FileNotFoundError:
131
+ print("Error: 'tulsidas_model.pth' not found. Please run train_llm.py first.")
132
+ sys.exit(1)
133
+
134
+ # 3. INTERACTIVE CHAT INTERFACE
135
+ def chat():
136
+ print("\n" + "="*50)
137
+ print("🙏 MANAS (Model for Awadhi Natural Autoregressive Sequences) 🙏")
138
+ print("You can type in English (e.g. 'shri ram') or Devanagari (e.g. 'श्री राम').")
139
+ print("Type 'quit' or 'exit' to stop.")
140
+ print("="*50 + "\n")
141
+
142
+ while True:
143
+ try:
144
+ user_input = input("You: ")
145
+ if user_input.lower() in ['quit', 'exit']:
146
+ break
147
+ if not user_input.strip():
148
+ continue
149
+
150
+ # Detect if user typed in English letters
151
+ if re.search(r'[a-zA-Z]', user_input):
152
+ # Transliterate ITRANS (English) -> Devanagari
153
+ hindi_input = transliterate(user_input, sanscript.ITRANS, sanscript.DEVANAGARI)
154
+ print(f"[Auto-translated]: {hindi_input}")
155
+ else:
156
+ hindi_input = user_input
157
+
158
+ # Start with the user's prompt
159
+ context = torch.tensor([encode(hindi_input)], dtype=torch.long, device=device)
160
+
161
+ print("\nMANAS:")
162
+ generated_tokens = model.generate(context, max_new_tokens=500)[0].tolist()
163
+ print(decode(generated_tokens))
164
+ print("\n" + "-"*50)
165
+
166
+ except KeyboardInterrupt:
167
+ break
168
+
169
+ if __name__ == '__main__':
170
+ chat()