Views
No views yet
pip install torch pandas scikit-learn huggingface_hub1# ============================================================================
2# COMBINED INFERENCE: TRANSFORMER MODEL + FAQ SYSTEM
3# ============================================================================
4
5!pip install -q torch huggingface_hub pandas scikit-learn
6
7import torch
8import torch.nn as nn
9import torch.nn.functional as F
10import json
11import math
12from huggingface_hub import hf_hub_download, login
13import re
14import pandas as pd
15from sklearn.feature_extraction.text import TfidfVectorizer
16from sklearn.metrics.pairwise import cosine_similarity
17import numpy as np
18
19# ============================================================================
20# CONFIGURATION
21# ============================================================================
22
23HF_TOKEN = "hf_your_token_here" # Replace with your token
24REPO_ID = "callidus/good"
25
26login(token=HF_TOKEN, add_to_git_credential=False)
27
28# ============================================================================
29# TRANSFORMER MODEL ARCHITECTURE
30# ============================================================================
31
32class MultiHeadAttention(nn.Module):
33 def __init__(self, d_model, num_heads):
34 super().__init__()
35 assert d_model % num_heads == 0
36 self.d_model = d_model
37 self.num_heads = num_heads
38 self.d_k = d_model // num_heads
39 self.W_q = nn.Linear(d_model, d_model)
40 self.W_k = nn.Linear(d_model, d_model)
41 self.W_v = nn.Linear(d_model, d_model)
42 self.W_o = nn.Linear(d_model, d_model)
43
44 def split_heads(self, x, batch_size):
45 x = x.view(batch_size, -1, self.num_heads, self.d_k)
46 return x.transpose(1, 2)
47
48 def forward(self, x, mask=None):
49 batch_size = x.size(0)
50 Q = self.split_heads(self.W_q(x), batch_size)
51 K = self.split_heads(self.W_k(x), batch_size)
52 V = self.split_heads(self.W_v(x), batch_size)
53 scores = torch.matmul(Q, K.transpose(-2, -1)) / math.sqrt(self.d_k)
54 if mask is not None:
55 scores = scores.masked_fill(mask == 0, -1e9)
56 attention_weights = F.softmax(scores, dim=-1)
57 attention_output = torch.matmul(attention_weights, V)
58 attention_output = attention_output.transpose(1, 2).contiguous()
59 attention_output = attention_output.view(batch_size, -1, self.d_model)
60 return self.W_o(attention_output), attention_weights
61
62class FeedForward(nn.Module):
63 def __init__(self, d_model, d_ff, dropout=0.1):
64 super().__init__()
65 self.linear1 = nn.Linear(d_model, d_ff)
66 self.linear2 = nn.Linear(d_ff, d_model)
67 self.dropout = nn.Dropout(dropout)
68
69 def forward(self, x):
70 return self.linear2(self.dropout(F.relu(self.linear1(x))))
71
72class TransformerBlock(nn.Module):
73 def __init__(self, d_model, num_heads, d_ff, dropout=0.1):
74 super().__init__()
75 self.attention = MultiHeadAttention(d_model, num_heads)
76 self.feed_forward = FeedForward(d_model, d_ff, dropout)
77 self.norm1 = nn.LayerNorm(d_model)
78 self.norm2 = nn.LayerNorm(d_model)
79 self.dropout1 = nn.Dropout(dropout)
80 self.dropout2 = nn.Dropout(dropout)
81
82 def forward(self, x, mask=None):
83 attn_output, attn_weights = self.attention(x, mask)
84 x = self.norm1(x + self.dropout1(attn_output))
85 ff_output = self.feed_forward(x)
86 x = self.norm2(x + self.dropout2(ff_output))
87 return x, attn_weights
88
89class PositionalEncoding(nn.Module):
90 def __init__(self, d_model, max_len=5000):
91 super().__init__()
92 pe = torch.zeros(max_len, d_model)
93 position = torch.arange(0, max_len).unsqueeze(1).float()
94 div_term = torch.exp(torch.arange(0, d_model, 2).float() *
95 -(math.log(10000.0) / d_model))
96 pe[:, 0::2] = torch.sin(position * div_term)
97 pe[:, 1::2] = torch.cos(position * div_term)
98 pe = pe.unsqueeze(0)
99 self.register_buffer('pe', pe)
100
101 def forward(self, x):
102 return x + self.pe[:, :x.size(1)]
103
104class TransformerModel(nn.Module):
105 def __init__(self, vocab_size, d_model=512, num_heads=8,
106 num_layers=6, d_ff=2048, dropout=0.1, max_len=512):
107 super().__init__()
108 self.embedding = nn.Embedding(vocab_size, d_model)
109 self.pos_encoding = PositionalEncoding(d_model, max_len)
110 self.transformer_blocks = nn.ModuleList([
111 TransformerBlock(d_model, num_heads, d_ff, dropout)
112 for _ in range(num_layers)
113 ])
114 self.fc_out = nn.Linear(d_model, vocab_size)
115 self.dropout = nn.Dropout(dropout)
116 self.d_model = d_model
117
118 def forward(self, x, mask=None):
119 x = self.embedding(x) * math.sqrt(self.d_model)
120 x = self.pos_encoding(x)
121 x = self.dropout(x)
122 for transformer_block in self.transformer_blocks:
123 x, attn_weights = transformer_block(x, mask)
124 logits = self.fc_out(x)
125 return logits
126
127class Tokenizer:
128 def __init__(self, tokenizer_data):
129 self.word2idx = tokenizer_data['word2idx']
130 self.idx2word = {int(k): v for k, v in tokenizer_data['idx2word'].items()}
131 self.vocab_size = tokenizer_data['vocab_size']
132 self.special_tokens = tokenizer_data['special_tokens']
133
134 def encode(self, text):
135 words = re.findall(r'\w+', text.lower())
136 return [self.word2idx.get(word, self.word2idx['<UNK>']) for word in words]
137
138 def decode(self, indices):
139 words = []
140 for idx in indices:
141 if idx in self.idx2word:
142 word = self.idx2word[idx]
143 if word not in ['<PAD>', '<SOS>', '<EOS>']:
144 words.append(word)
145 return ' '.join(words)
146
147class TransformerInference:
148 def __init__(self, repo_id, token=None, device=None):
149 self.device = device or ('cuda' if torch.cuda.is_available() else 'cpu')
150 self.model = None
151 self.tokenizer = None
152 self.config = None
153 self.token = token
154 self.load_from_hub(repo_id)
155
156 def load_from_hub(self, repo_id):
157 config_path = hf_hub_download(repo_id=repo_id, filename="model_config.json", token=self.token)
158 weights_path = hf_hub_download(repo_id=repo_id, filename="model_weights.pt", token=self.token)
159 tokenizer_path = hf_hub_download(repo_id=repo_id, filename="tokenizer.json", token=self.token)
160
161 with open(config_path, 'r') as f:
162 self.config = json.load(f)
163
164 with open(tokenizer_path, 'r') as f:
165 tokenizer_data = json.load(f)
166 self.tokenizer = Tokenizer(tokenizer_data)
167
168 self.model = TransformerModel(
169 vocab_size=self.config['vocab_size'],
170 d_model=self.config['d_model'],
171 num_heads=self.config['num_heads'],
172 num_layers=self.config['num_layers'],
173 d_ff=self.config['d_ff'],
174 dropout=self.config.get('dropout', 0.1),
175 max_len=self.config.get('max_len', 512)
176 )
177
178 state_dict = torch.load(weights_path, map_location=self.device, weights_only=True)
179 self.model.load_state_dict(state_dict)
180 self.model = self.model.to(self.device)
181 self.model.eval()
182
183 def generate(self, prompt, max_length=50, temperature=0.8, top_k=50, top_p=0.9):
184 self.model.eval()
185 tokens = self.tokenizer.encode(prompt)
186
187 if not tokens or all(t == self.tokenizer.word2idx['<UNK>'] for t in tokens):
188 tokens = [self.tokenizer.word2idx['<SOS>']]
189
190 generated = tokens.copy()
191
192 with torch.no_grad():
193 for _ in range(max_length):
194 input_tokens = generated[-64:]
195 if len(input_tokens) < 64:
196 input_tokens = [self.tokenizer.word2idx['<PAD>']] * (64 - len(input_tokens)) + input_tokens
197
198 input_ids = torch.tensor([input_tokens], dtype=torch.long).to(self.device)
199 logits = self.model(input_ids)
200 next_token_logits = logits[0, -1, :] / temperature
201
202 next_token_logits[self.tokenizer.word2idx['<PAD>']] = -float('inf')
203 next_token_logits[self.tokenizer.word2idx['<UNK>']] = -float('inf')
204
205 if top_k > 0:
206 indices_to_remove = next_token_logits < torch.topk(next_token_logits, top_k)[0][..., -1, None]
207 next_token_logits[indices_to_remove] = -float('inf')
208
209 if top_p < 1.0:
210 sorted_logits, sorted_indices = torch.sort(next_token_logits, descending=True)
211 cumulative_probs = torch.cumsum(F.softmax(sorted_logits, dim=-1), dim=-1)
212 sorted_indices_to_remove = cumulative_probs > top_p
213 sorted_indices_to_remove[..., 1:] = sorted_indices_to_remove[..., :-1].clone()
214 sorted_indices_to_remove[..., 0] = 0
215 indices_to_remove = sorted_indices[sorted_indices_to_remove]
216 next_token_logits[indices_to_remove] = -float('inf')
217
218 probs = F.softmax(next_token_logits, dim=-1)
219 next_token = torch.multinomial(probs, num_samples=1).item()
220
221 if next_token == self.tokenizer.word2idx['<EOS>']:
222 break
223
224 generated.append(next_token)
225
226 return self.tokenizer.decode(generated)
227
228# ============================================================================
229# FAQ SYSTEM
230# ============================================================================
231
232class CodeBasicsFAQ:
233 def __init__(self, csv_path):
234 encodings = ['utf-8', 'latin-1', 'iso-8859-1', 'cp1252']
235 df = None
236
237 for encoding in encodings:
238 try:
239 df = pd.read_csv(csv_path, encoding=encoding)
240 break
241 except:
242 continue
243
244 if df is None:
245 raise Exception("Could not load FAQ CSV")
246
247 self.df = df
248 self.questions = df['prompt'].tolist()
249 self.answers = df['response'].tolist()
250
251 self.vectorizer = TfidfVectorizer(
252 lowercase=True,
253 stop_words='english',
254 ngram_range=(1, 2),
255 max_features=1000
256 )
257
258 self.question_vectors = self.vectorizer.fit_transform(self.questions)
259
260 def find_best_match(self, query, threshold=0.2):
261 query_vector = self.vectorizer.transform([query])
262 similarities = cosine_similarity(query_vector, self.question_vectors)[0]
263
264 best_idx = np.argmax(similarities)
265 best_score = similarities[best_idx]
266
267 if best_score >= threshold:
268 return {
269 'question': self.questions[best_idx],
270 'answer': self.answers[best_idx],
271 'confidence': best_score
272 }
273 return None
274
275# ============================================================================
276# LOAD BOTH SYSTEMS
277# ============================================================================
278
279print("Loading systems...")
280transformer = TransformerInference(repo_id=REPO_ID, token=HF_TOKEN)
281csv_path = hf_hub_download(repo_id=REPO_ID, filename="codebasics_faqs.csv", token=HF_TOKEN)
282faq = CodeBasicsFAQ(csv_path)
283print("Ready!")
284
285# ============================================================================
286# SMART INFERENCE FUNCTION
287# ============================================================================
288
289def smart_inference(query):
290 """Automatically chooses FAQ or text generation"""
291 faq_match = faq.find_best_match(query)
292
293 if faq_match:
294 return faq_match['answer']
295 else:
296 return transformer.generate(query, max_length=50, temperature=0.8)
297
298# ============================================================================
299# USAGE
300# ============================================================================
301
302# Ask questions - system automatically picks best method
303result = smart_inference("Can I take this bootcamp without programming experience?")
304print(result)
305
306# Interactive mode
307while True:
308 user_input = input("Ask me: ").strip()
309 if user_input.lower() in ['quit', 'exit']:
310 break
311 print(smart_inference(user_input))1result = smart_inference("Can I take this bootcamp without programming experience?")
2# Returns: "Yes, this is the perfect bootcamp for anyone..."
3
4result = smart_inference("Why should I trust Codebasics?")
5# Returns: "Till now 9000+ learners have benefitted..."1result = smart_inference("machine learning algorithms")
2# Returns: Generated text about ML
3
4result = smart_inference("artificial intelligence")
5# Returns: Generated text about AIcodebasics_faqs.csv - FAQ database (50+ Q&A pairs)model_config.json - Transformer configurationmodel_weights.pt - Transformer weightstokenizer.json - Tokenizer vocabularyREADME.md - This documentation1@misc{codebasics-faq-2024,
2 author = {callidus},
3 title = {CodeBasics FAQ and Text Generation System},
4 year = {2024},
5 publisher = {HuggingFace},
6 howpublished = {\url{https://huggingface.co/callidus/good}}
7}