awacke1 commited on
Commit
0982afe
·
verified ·
1 Parent(s): a1e5a93

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +217 -125
app.py CHANGED
@@ -45,10 +45,14 @@ st.set_page_config(
45
  # Initialize st.session_state
46
  if 'captured_images' not in st.session_state:
47
  st.session_state['captured_images'] = []
48
- if 'builder' not in st.session_state:
49
- st.session_state['builder'] = None
50
- if 'model_loaded' not in st.session_state:
51
- st.session_state['model_loaded'] = False
 
 
 
 
52
  if 'active_tab' not in st.session_state:
53
  st.session_state['active_tab'] = "Build Titan 🌱"
54
 
@@ -113,50 +117,76 @@ class ModelBuilder:
113
  self.sft_data = None
114
  self.jokes = ["Why did the AI go to therapy? Too many layers to unpack! 😂", "Training complete! Time for a binary coffee break. ☕"]
115
  def load_model(self, model_path: str, config: Optional[ModelConfig] = None):
116
- with st.spinner(f"Loading {model_path}... ⏳ (Patience, young padawan!)"):
117
- self.model = AutoModelForCausalLM.from_pretrained(model_path)
118
- self.tokenizer = AutoTokenizer.from_pretrained(model_path)
119
- if self.tokenizer.pad_token is None:
120
- self.tokenizer.pad_token = self.tokenizer.eos_token
121
- if config:
122
- self.config = config
123
- self.model.to("cuda" if torch.cuda.is_available() else "cpu")
124
- st.success(f"Model loaded! 🎉 {random.choice(self.jokes)}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
  return self
126
  def fine_tune_sft(self, csv_path: str, epochs: int = 3, batch_size: int = 4):
127
- self.sft_data = []
128
- with open(csv_path, "r") as f:
129
- reader = csv.DictReader(f)
130
- for row in reader:
131
- self.sft_data.append({"prompt": row["prompt"], "response": row["response"]})
132
- dataset = SFTDataset(self.sft_data, self.tokenizer)
133
- dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=True)
134
- optimizer = torch.optim.AdamW(self.model.parameters(), lr=2e-5)
135
- self.model.train()
136
- device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
137
- self.model.to(device)
138
- for epoch in range(epochs):
139
- with st.spinner(f"Training epoch {epoch + 1}/{epochs}... ⚙️ (The AI is lifting weights!)"):
140
- total_loss = 0
141
- for batch in dataloader:
142
- optimizer.zero_grad()
143
- input_ids = batch["input_ids"].to(device)
144
- attention_mask = batch["attention_mask"].to(device)
145
- labels = batch["labels"].to(device)
146
- outputs = self.model(input_ids=input_ids, attention_mask=attention_mask, labels=labels)
147
- loss = outputs.loss
148
- loss.backward()
149
- optimizer.step()
150
- total_loss += loss.item()
151
- st.write(f"Epoch {epoch + 1} completed. Average loss: {total_loss / len(dataloader):.4f}")
152
- st.success(f"SFT Fine-tuning completed! 🎉 {random.choice(self.jokes)}")
 
 
 
 
 
 
153
  return self
154
  def save_model(self, path: str):
155
- with st.spinner("Saving model... 💾 (Packing the AI’s suitcase!)"):
156
- os.makedirs(os.path.dirname(path), exist_ok=True)
157
- self.model.save_pretrained(path)
158
- self.tokenizer.save_pretrained(path)
159
- st.success(f"Model saved at {path}! ✅ May the force be with it.")
 
 
 
 
 
 
160
  def evaluate(self, prompt: str, status_container=None):
161
  self.model.eval()
162
  if status_container:
@@ -181,46 +211,77 @@ class DiffusionBuilder:
181
  self.pipeline = None
182
  def load_model(self, model_path: str, config: Optional[DiffusionConfig] = None):
183
  from diffusers import StableDiffusionPipeline
184
- with st.spinner(f"Loading diffusion model {model_path}... ⏳"):
185
- self.pipeline = StableDiffusionPipeline.from_pretrained(model_path)
186
- self.pipeline.to("cuda" if torch.cuda.is_available() else "cpu")
187
- if config:
188
- self.config = config
189
- st.success(f"Diffusion model loaded! 🎨")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
190
  return self
191
  def fine_tune_sft(self, images, texts, epochs=3):
192
- dataset = DiffusionDataset(images, texts)
193
- dataloader = DataLoader(dataset, batch_size=1, shuffle=True)
194
- optimizer = torch.optim.AdamW(self.pipeline.unet.parameters(), lr=1e-5)
195
- self.pipeline.unet.train()
196
- device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
197
- for epoch in range(epochs):
198
- with st.spinner(f"Training diffusion epoch {epoch + 1}/{epochs}... ⚙️"):
199
- total_loss = 0
200
- for batch in dataloader:
201
- optimizer.zero_grad()
202
- image = batch["image"][0].to(device)
203
- text = batch["text"][0]
204
- latents = self.pipeline.vae.encode(torch.tensor(np.array(image)).permute(2, 0, 1).unsqueeze(0).float().to(device)).latent_dist.sample()
205
- noise = torch.randn_like(latents)
206
- timesteps = torch.randint(0, self.pipeline.scheduler.num_train_timesteps, (latents.shape[0],), device=latents.device)
207
- noisy_latents = self.pipeline.scheduler.add_noise(latents, noise, timesteps)
208
- text_embeddings = self.pipeline.text_encoder(self.pipeline.tokenizer(text, return_tensors="pt").input_ids.to(device))[0]
209
- pred_noise = self.pipeline.unet(noisy_latents, timesteps, encoder_hidden_states=text_embeddings).sample
210
- loss = torch.nn.functional.mse_loss(pred_noise, noise)
211
- loss.backward()
212
- optimizer.step()
213
- total_loss += loss.item()
214
- st.write(f"Epoch {epoch + 1} completed. Average loss: {total_loss / len(dataloader):.4f}")
215
- st.success("Diffusion SFT Fine-tuning completed! 🎨")
 
 
 
 
 
 
216
  return self
217
  def save_model(self, path: str):
218
- with st.spinner("Saving diffusion model... 💾"):
219
- os.makedirs(os.path.dirname(path), exist_ok=True)
220
- self.pipeline.save_pretrained(path)
221
- st.success(f"Diffusion model saved at {path}! ✅")
 
 
 
 
 
 
222
  def generate(self, prompt: str):
223
- return self.pipeline(prompt, num_inference_steps=50).images[0]
 
 
 
 
 
224
 
225
  # Utility Functions
226
  def generate_filename(sequence, ext="png"):
@@ -231,16 +292,24 @@ def generate_filename(sequence, ext="png"):
231
  return f"{dt.strftime('%m-%d-%Y-%I-%M-%S-%p')}.{ext}"
232
 
233
  def get_download_link(file_path, mime_type="text/plain", label="Download"):
234
- with open(file_path, 'rb') as f:
235
- data = f.read()
236
- b64 = base64.b64encode(data).decode()
237
- return f'<a href="data:{mime_type};base64,{b64}" download="{os.path.basename(file_path)}">{label} 📥</a>'
 
 
 
 
238
 
239
  def zip_directory(directory_path, zip_path):
240
- with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
241
- for root, _, files in os.walk(directory_path):
242
- for file in files:
243
- zipf.write(os.path.join(root, file), os.path.relpath(os.path.join(root, file), os.path.dirname(directory_path)))
 
 
 
 
244
 
245
  def get_model_files(model_type="causal_lm"):
246
  path = "models/*" if model_type == "causal_lm" else "diffusion_models/*"
@@ -321,7 +390,7 @@ def calculate_cargo_travel_time(origin_coords: Tuple[float, float], destination_
321
  # Main App
322
  st.title("SFT Tiny Titans 🚀 (Small but Mighty!)")
323
 
324
- # Sidebar Galleries
325
  st.sidebar.header("Media Gallery 🎨")
326
  gallery_size = st.sidebar.slider("Gallery Size 📸", 1, 10, 4, help="Adjust how many epic captures you see! 🌟")
327
  update_gallery()
@@ -333,10 +402,21 @@ selected_model = st.sidebar.selectbox("Select Saved Model", ["None"] + model_dir
333
  if selected_model != "None" and st.sidebar.button("Load Model 📂"):
334
  builder = ModelBuilder() if model_type == "Causal LM" else DiffusionBuilder()
335
  config = (ModelConfig if model_type == "Causal LM" else DiffusionConfig)(name=os.path.basename(selected_model), base_model="unknown", size="small")
336
- builder.load_model(selected_model, config)
337
- st.session_state['builder'] = builder
338
- st.session_state['model_loaded'] = True
339
- st.rerun()
 
 
 
 
 
 
 
 
 
 
 
340
 
341
  # Tabs
342
  tabs = [
@@ -364,11 +444,18 @@ with tab1:
364
  if st.button("Download Model ⬇️"):
365
  config = ModelConfig(name=model_name, base_model=base_model, size="small", domain=domain) if model_type == "Causal LM" else DiffusionConfig(name=model_name, base_model=base_model, size="small")
366
  builder = ModelBuilder() if model_type == "Causal LM" else DiffusionBuilder()
367
- builder.load_model(base_model, config)
368
- builder.save_model(config.model_path)
369
- st.session_state['builder'] = builder
370
- st.session_state['model_loaded'] = True
371
- st.rerun()
 
 
 
 
 
 
 
372
 
373
  with tab2:
374
  st.header("Camera Snap 📷 (Dual Capture!)")
@@ -402,7 +489,7 @@ with tab2:
402
 
403
  with tab3: # Fine-Tune Titan (NLP)
404
  st.header("Fine-Tune Titan (NLP) 🔧 (Teach Your Word Wizard Some Tricks!)")
405
- if 'builder' not in st.session_state or not st.session_state.get('model_loaded', False) or not isinstance(st.session_state['builder'], ModelBuilder):
406
  st.warning("Please build or load an NLP Titan first! ⚠️ (No word wizard, no magic!)")
407
  else:
408
  if st.button("Generate Sample CSV 📝"):
@@ -423,12 +510,12 @@ with tab3: # Fine-Tune Titan (NLP)
423
  csv_path = f"uploaded_sft_data_{int(time.time())}.csv"
424
  with open(csv_path, "wb") as f:
425
  f.write(uploaded_csv.read())
426
- new_model_name = f"{st.session_state['builder'].config.name}-sft-{int(time.time())}"
427
- new_config = ModelConfig(name=new_model_name, base_model=st.session_state['builder'].config.base_model, size="small", domain=st.session_state['builder'].config.domain)
428
- st.session_state['builder'].config = new_config
429
  with st.status("Fine-tuning NLP Titan... ⏳ (Whipping words into shape!)", expanded=True) as status:
430
- st.session_state['builder'].fine_tune_sft(csv_path)
431
- st.session_state['builder'].save_model(new_config.model_path)
432
  status.update(label="Fine-tuning completed! 🎉 (Wordsmith Titan unleashed!)", state="complete")
433
  zip_path = f"{new_config.model_path}.zip"
434
  zip_directory(new_config.model_path, zip_path)
@@ -436,17 +523,17 @@ with tab3: # Fine-Tune Titan (NLP)
436
 
437
  with tab4: # Test Titan (NLP)
438
  st.header("Test Titan (NLP) 🧪 (Put Your Word Wizard to the Test!)")
439
- if 'builder' not in st.session_state or not st.session_state.get('model_loaded', False) or not isinstance(st.session_state['builder'], ModelBuilder):
440
  st.warning("Please build or load an NLP Titan first! ⚠️ (No word wizard, no test drive!)")
441
  else:
442
- if st.session_state['builder'].sft_data:
443
  st.write("Testing with SFT Data:")
444
  with st.spinner("Running SFT data tests... ⏳ (Titan’s flexing its word muscles!)"):
445
- for item in st.session_state['builder'].sft_data[:3]:
446
  prompt = item["prompt"]
447
  expected = item["response"]
448
  status_container = st.empty()
449
- generated = st.session_state['builder'].evaluate(prompt, status_container)
450
  st.write(f"**Prompt**: {prompt}")
451
  st.write(f"**Expected**: {expected}")
452
  st.write(f"**Generated**: {generated} (Titan says: '{random.choice(['Bleep bloop!', 'I am groot!', '42!'])}')")
@@ -456,19 +543,19 @@ with tab4: # Test Titan (NLP)
456
  if st.button("Run Test ▶️"):
457
  with st.spinner("Testing your prompt... ⏳ (Titan’s pondering deeply!)"):
458
  status_container = st.empty()
459
- result = st.session_state['builder'].evaluate(test_prompt, status_container)
460
  st.write(f"**Generated Response**: {result} (Titan’s wisdom unleashed!)")
461
  status_container.empty()
462
 
463
  with tab5: # Agentic RAG Party (NLP)
464
  st.header("Agentic RAG Party (NLP) 🌐 (Party Like It’s 2099!)")
465
  st.write("This demo uses your SFT-tuned NLP Titan to plan a superhero party with mock retrieval!")
466
- if 'builder' not in st.session_state or not st.session_state.get('model_loaded', False) or not isinstance(st.session_state['builder'], ModelBuilder):
467
  st.warning("Please build or load an NLP Titan first! ⚠️ (No word wizard, no party!)")
468
  else:
469
  if st.button("Run NLP RAG Demo 🎉"):
470
  with st.spinner("Loading your SFT-tuned NLP Titan... ⏳ (Titan’s suiting up!)"):
471
- agent = PartyPlannerAgent(st.session_state['builder'].model, st.session_state['builder'].tokenizer)
472
  st.write("Agent ready! 🦸‍♂️ (Time to plan an epic bash!)")
473
  task = """
474
  Plan a luxury superhero-themed party at Wayne Manor (42.3601° N, 71.0589° W).
@@ -508,10 +595,11 @@ with tab5: # Agentic RAG Party (NLP)
508
  st.write("Party on, Wayne! 🦸‍♂️🎉")
509
  except Exception as e:
510
  st.error(f"Error planning party: {str(e)} (Even Superman has kryptonite days!)")
 
511
 
512
  with tab6: # Fine-Tune Titan (CV)
513
  st.header("Fine-Tune Titan (CV) 🔧 (Paint Your Titan’s Masterpiece!)")
514
- if 'builder' not in st.session_state or not st.session_state.get('model_loaded', False) or not isinstance(st.session_state['builder'], DiffusionBuilder):
515
  st.warning("Please build or load a CV Titan first! ⚠️ (No artist, no canvas!)")
516
  else:
517
  captured_images = get_gallery_files(["png"])
@@ -521,12 +609,12 @@ with tab6: # Fine-Tune Titan (CV)
521
  if st.button("Fine-Tune with Dataset 🔄"):
522
  images = [Image.open(row["image"]) for _, row in edited_data.iterrows()]
523
  texts = [row["text"] for _, row in edited_data.iterrows()]
524
- new_model_name = f"{st.session_state['builder'].config.name}-sft-{int(time.time())}"
525
- new_config = DiffusionConfig(name=new_model_name, base_model=st.session_state['builder'].config.base_model, size="small")
526
- st.session_state['builder'].config = new_config
527
  with st.status("Fine-tuning CV Titan... ⏳ (Brushing up those pixels!)", expanded=True) as status:
528
- st.session_state['builder'].fine_tune_sft(images, texts)
529
- st.session_state['builder'].save_model(new_config.model_path)
530
  status.update(label="Fine-tuning completed! 🎉 (Pixel Titan unleashed!)", state="complete")
531
  zip_path = f"{new_config.model_path}.zip"
532
  zip_directory(new_config.model_path, zip_path)
@@ -541,32 +629,36 @@ with tab6: # Fine-Tune Titan (CV)
541
 
542
  with tab7: # Test Titan (CV)
543
  st.header("Test Titan (CV) 🧪 (Unleash Your Pixel Power!)")
544
- if 'builder' not in st.session_state or not st.session_state.get('model_loaded', False) or not isinstance(st.session_state['builder'], DiffusionBuilder):
545
  st.warning("Please build or load a CV Titan first! ⚠️ (No artist, no masterpiece!)")
546
  else:
547
  test_prompt = st.text_area("Enter Test Prompt 🎨", "Neon Batman", help="Dream up a wild image—your Titan’s got the brush! 🖌️")
548
  if st.button("Run Test ▶️"):
549
  with st.spinner("Painting your masterpiece... ⏳ (Titan’s mixing colors!)"):
550
- image = st.session_state['builder'].generate(test_prompt)
551
  st.image(image, caption="Generated Image", use_container_width=True)
552
 
553
  with tab8: # Agentic RAG Party (CV)
554
  st.header("Agentic RAG Party (CV) 🌐 (Party with Pixels!)")
555
  st.write("This demo uses your SFT-tuned CV Titan to generate superhero party images with mock retrieval!")
556
- if 'builder' not in st.session_state or not st.session_state.get('model_loaded', False) or not isinstance(st.session_state['builder'], DiffusionBuilder):
557
  st.warning("Please build or load a CV Titan first! ⚠️ (No artist, no party!)")
558
  else:
559
  if st.button("Run CV RAG Demo 🎉"):
560
  with st.spinner("Loading your SFT-tuned CV Titan... ⏳ (Titan’s grabbing its paintbrush!)"):
561
- agent = CVPartyPlannerAgent(st.session_state['builder'].pipeline)
562
  st.write("Agent ready! 🎨 (Time to paint an epic bash!)")
563
  task = "Generate images for a luxury superhero-themed party."
564
  with st.spinner("Crafting superhero party visuals... ⏳ (Pixels assemble!)"):
565
- plan_df = agent.plan_party(task)
566
- st.dataframe(plan_df)
567
- for _, row in plan_df.iterrows():
568
- image = agent.generate(row["Image Idea"])
569
- st.image(image, caption=f"{row['Theme']} - {row['Image Idea']}", use_container_width=True)
 
 
 
 
570
 
571
  # Display Logs
572
  st.sidebar.subheader("Action Logs 📜")
 
45
  # Initialize st.session_state
46
  if 'captured_images' not in st.session_state:
47
  st.session_state['captured_images'] = []
48
+ if 'nlp_builder' not in st.session_state:
49
+ st.session_state['nlp_builder'] = None
50
+ if 'cv_builder' not in st.session_state:
51
+ st.session_state['cv_builder'] = None
52
+ if 'nlp_loaded' not in st.session_state:
53
+ st.session_state['nlp_loaded'] = False
54
+ if 'cv_loaded' not in st.session_state:
55
+ st.session_state['cv_loaded'] = False
56
  if 'active_tab' not in st.session_state:
57
  st.session_state['active_tab'] = "Build Titan 🌱"
58
 
 
117
  self.sft_data = None
118
  self.jokes = ["Why did the AI go to therapy? Too many layers to unpack! 😂", "Training complete! Time for a binary coffee break. ☕"]
119
  def load_model(self, model_path: str, config: Optional[ModelConfig] = None):
120
+ try:
121
+ with st.spinner(f"Loading {model_path}... (Patience, young padawan!)"):
122
+ self.model = AutoModelForCausalLM.from_pretrained(model_path)
123
+ self.tokenizer = AutoTokenizer.from_pretrained(model_path)
124
+ if self.tokenizer.pad_token is None:
125
+ self.tokenizer.pad_token = self.tokenizer.eos_token
126
+ if config:
127
+ self.config = config
128
+ self.model.to("cuda" if torch.cuda.is_available() else "cpu")
129
+ st.success(f"Model loaded! 🎉 {random.choice(self.jokes)}")
130
+ logger.info(f"Successfully loaded Causal LM model: {model_path}")
131
+ except torch.cuda.OutOfMemoryError as e:
132
+ st.error(f"GPU memory error loading {model_path}: {str(e)} 💥 (Out of GPU juice!)")
133
+ logger.error(f"GPU memory error loading {model_path}: {str(e)}")
134
+ raise
135
+ except MemoryError as e:
136
+ st.error(f"CPU memory error loading {model_path}: {str(e)} 💥 (RAM ran away!)")
137
+ logger.error(f"CPU memory error loading {model_path}: {str(e)}")
138
+ raise
139
+ except Exception as e:
140
+ st.error(f"Failed to load {model_path}: {str(e)} 💥 (Something broke—check the logs!)")
141
+ logger.error(f"Failed to load {model_path}: {str(e)}")
142
+ raise
143
  return self
144
  def fine_tune_sft(self, csv_path: str, epochs: int = 3, batch_size: int = 4):
145
+ try:
146
+ self.sft_data = []
147
+ with open(csv_path, "r") as f:
148
+ reader = csv.DictReader(f)
149
+ for row in reader:
150
+ self.sft_data.append({"prompt": row["prompt"], "response": row["response"]})
151
+ dataset = SFTDataset(self.sft_data, self.tokenizer)
152
+ dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=True)
153
+ optimizer = torch.optim.AdamW(self.model.parameters(), lr=2e-5)
154
+ self.model.train()
155
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
156
+ self.model.to(device)
157
+ for epoch in range(epochs):
158
+ with st.spinner(f"Training epoch {epoch + 1}/{epochs}... ⚙️ (The AI is lifting weights!)"):
159
+ total_loss = 0
160
+ for batch in dataloader:
161
+ optimizer.zero_grad()
162
+ input_ids = batch["input_ids"].to(device)
163
+ attention_mask = batch["attention_mask"].to(device)
164
+ labels = batch["labels"].to(device)
165
+ outputs = self.model(input_ids=input_ids, attention_mask=attention_mask, labels=labels)
166
+ loss = outputs.loss
167
+ loss.backward()
168
+ optimizer.step()
169
+ total_loss += loss.item()
170
+ st.write(f"Epoch {epoch + 1} completed. Average loss: {total_loss / len(dataloader):.4f}")
171
+ st.success(f"SFT Fine-tuning completed! 🎉 {random.choice(self.jokes)}")
172
+ logger.info(f"Successfully fine-tuned Causal LM model: {self.config.name}")
173
+ except Exception as e:
174
+ st.error(f"Fine-tuning failed: {str(e)} 💥 (Training hit a snag!)")
175
+ logger.error(f"Fine-tuning failed: {str(e)}")
176
+ raise
177
  return self
178
  def save_model(self, path: str):
179
+ try:
180
+ with st.spinner("Saving model... 💾 (Packing the AI’s suitcase!)"):
181
+ os.makedirs(os.path.dirname(path), exist_ok=True)
182
+ self.model.save_pretrained(path)
183
+ self.tokenizer.save_pretrained(path)
184
+ st.success(f"Model saved at {path}! ✅ May the force be with it.")
185
+ logger.info(f"Model saved at {path}")
186
+ except Exception as e:
187
+ st.error(f"Failed to save model: {str(e)} 💥 (Save operation crashed!)")
188
+ logger.error(f"Failed to save model: {str(e)}")
189
+ raise
190
  def evaluate(self, prompt: str, status_container=None):
191
  self.model.eval()
192
  if status_container:
 
211
  self.pipeline = None
212
  def load_model(self, model_path: str, config: Optional[DiffusionConfig] = None):
213
  from diffusers import StableDiffusionPipeline
214
+ try:
215
+ with st.spinner(f"Loading diffusion model {model_path}... ⏳"):
216
+ self.pipeline = StableDiffusionPipeline.from_pretrained(model_path)
217
+ self.pipeline.to("cuda" if torch.cuda.is_available() else "cpu")
218
+ if config:
219
+ self.config = config
220
+ st.success(f"Diffusion model loaded! 🎨")
221
+ logger.info(f"Successfully loaded Diffusion model: {model_path}")
222
+ except torch.cuda.OutOfMemoryError as e:
223
+ st.error(f"GPU memory error loading {model_path}: {str(e)} 💥 (Out of GPU juice!)")
224
+ logger.error(f"GPU memory error loading {model_path}: {str(e)}")
225
+ raise
226
+ except MemoryError as e:
227
+ st.error(f"CPU memory error loading {model_path}: {str(e)} 💥 (RAM ran away!)")
228
+ logger.error(f"CPU memory error loading {model_path}: {str(e)}")
229
+ raise
230
+ except Exception as e:
231
+ st.error(f"Failed to load {model_path}: {str(e)} 💥 (Something broke—check the logs!)")
232
+ logger.error(f"Failed to load {model_path}: {str(e)}")
233
+ raise
234
  return self
235
  def fine_tune_sft(self, images, texts, epochs=3):
236
+ try:
237
+ dataset = DiffusionDataset(images, texts)
238
+ dataloader = DataLoader(dataset, batch_size=1, shuffle=True)
239
+ optimizer = torch.optim.AdamW(self.pipeline.unet.parameters(), lr=1e-5)
240
+ self.pipeline.unet.train()
241
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
242
+ for epoch in range(epochs):
243
+ with st.spinner(f"Training diffusion epoch {epoch + 1}/{epochs}... ⚙️"):
244
+ total_loss = 0
245
+ for batch in dataloader:
246
+ optimizer.zero_grad()
247
+ image = batch["image"][0].to(device)
248
+ text = batch["text"][0]
249
+ latents = self.pipeline.vae.encode(torch.tensor(np.array(image)).permute(2, 0, 1).unsqueeze(0).float().to(device)).latent_dist.sample()
250
+ noise = torch.randn_like(latents)
251
+ timesteps = torch.randint(0, self.pipeline.scheduler.num_train_timesteps, (latents.shape[0],), device=latents.device)
252
+ noisy_latents = self.pipeline.scheduler.add_noise(latents, noise, timesteps)
253
+ text_embeddings = self.pipeline.text_encoder(self.pipeline.tokenizer(text, return_tensors="pt").input_ids.to(device))[0]
254
+ pred_noise = self.pipeline.unet(noisy_latents, timesteps, encoder_hidden_states=text_embeddings).sample
255
+ loss = torch.nn.functional.mse_loss(pred_noise, noise)
256
+ loss.backward()
257
+ optimizer.step()
258
+ total_loss += loss.item()
259
+ st.write(f"Epoch {epoch + 1} completed. Average loss: {total_loss / len(dataloader):.4f}")
260
+ st.success("Diffusion SFT Fine-tuning completed! 🎨")
261
+ logger.info(f"Successfully fine-tuned Diffusion model: {self.config.name}")
262
+ except Exception as e:
263
+ st.error(f"Fine-tuning failed: {str(e)} 💥 (Training hit a snag!)")
264
+ logger.error(f"Fine-tuning failed: {str(e)}")
265
+ raise
266
  return self
267
  def save_model(self, path: str):
268
+ try:
269
+ with st.spinner("Saving diffusion model... 💾"):
270
+ os.makedirs(os.path.dirname(path), exist_ok=True)
271
+ self.pipeline.save_pretrained(path)
272
+ st.success(f"Diffusion model saved at {path}! ✅")
273
+ logger.info(f"Diffusion model saved at {path}")
274
+ except Exception as e:
275
+ st.error(f"Failed to save model: {str(e)} 💥 (Save operation crashed!)")
276
+ logger.error(f"Failed to save model: {str(e)}")
277
+ raise
278
  def generate(self, prompt: str):
279
+ try:
280
+ return self.pipeline(prompt, num_inference_steps=50).images[0]
281
+ except Exception as e:
282
+ st.error(f"Image generation failed: {str(e)} 💥 (Pixel party pooper!)")
283
+ logger.error(f"Image generation failed: {str(e)}")
284
+ raise
285
 
286
  # Utility Functions
287
  def generate_filename(sequence, ext="png"):
 
292
  return f"{dt.strftime('%m-%d-%Y-%I-%M-%S-%p')}.{ext}"
293
 
294
  def get_download_link(file_path, mime_type="text/plain", label="Download"):
295
+ try:
296
+ with open(file_path, 'rb') as f:
297
+ data = f.read()
298
+ b64 = base64.b64encode(data).decode()
299
+ return f'<a href="data:{mime_type};base64,{b64}" download="{os.path.basename(file_path)}">{label} 📥</a>'
300
+ except Exception as e:
301
+ logger.error(f"Failed to generate download link for {file_path}: {str(e)}")
302
+ return f"Error: Could not generate link for {file_path}"
303
 
304
  def zip_directory(directory_path, zip_path):
305
+ try:
306
+ with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
307
+ for root, _, files in os.walk(directory_path):
308
+ for file in files:
309
+ zipf.write(os.path.join(root, file), os.path.relpath(os.path.join(root, file), os.path.dirname(directory_path)))
310
+ except Exception as e:
311
+ logger.error(f"Failed to zip directory {directory_path}: {str(e)}")
312
+ raise
313
 
314
  def get_model_files(model_type="causal_lm"):
315
  path = "models/*" if model_type == "causal_lm" else "diffusion_models/*"
 
390
  # Main App
391
  st.title("SFT Tiny Titans 🚀 (Small but Mighty!)")
392
 
393
+ # Sidebar Galleries and Status
394
  st.sidebar.header("Media Gallery 🎨")
395
  gallery_size = st.sidebar.slider("Gallery Size 📸", 1, 10, 4, help="Adjust how many epic captures you see! 🌟")
396
  update_gallery()
 
402
  if selected_model != "None" and st.sidebar.button("Load Model 📂"):
403
  builder = ModelBuilder() if model_type == "Causal LM" else DiffusionBuilder()
404
  config = (ModelConfig if model_type == "Causal LM" else DiffusionConfig)(name=os.path.basename(selected_model), base_model="unknown", size="small")
405
+ try:
406
+ builder.load_model(selected_model, config)
407
+ if model_type == "Causal LM":
408
+ st.session_state['nlp_builder'] = builder
409
+ st.session_state['nlp_loaded'] = True
410
+ else:
411
+ st.session_state['cv_builder'] = builder
412
+ st.session_state['cv_loaded'] = True
413
+ st.rerun()
414
+ except Exception as e:
415
+ st.error(f"Model load failed: {str(e)} 💥 (Check logs for details!)")
416
+
417
+ st.sidebar.subheader("Model Status 🚦")
418
+ st.sidebar.write(f"**NLP Model**: {'Loaded' if st.session_state['nlp_loaded'] else 'Not Loaded'} {'(Active)' if st.session_state['nlp_loaded'] and isinstance(st.session_state.get('nlp_builder'), ModelBuilder) else ''}")
419
+ st.sidebar.write(f"**CV Model**: {'Loaded' if st.session_state['cv_loaded'] else 'Not Loaded'} {'(Active)' if st.session_state['cv_loaded'] and isinstance(st.session_state.get('cv_builder'), DiffusionBuilder) else ''}")
420
 
421
  # Tabs
422
  tabs = [
 
444
  if st.button("Download Model ⬇️"):
445
  config = ModelConfig(name=model_name, base_model=base_model, size="small", domain=domain) if model_type == "Causal LM" else DiffusionConfig(name=model_name, base_model=base_model, size="small")
446
  builder = ModelBuilder() if model_type == "Causal LM" else DiffusionBuilder()
447
+ try:
448
+ builder.load_model(base_model, config)
449
+ builder.save_model(config.model_path)
450
+ if model_type == "Causal LM":
451
+ st.session_state['nlp_builder'] = builder
452
+ st.session_state['nlp_loaded'] = True
453
+ else:
454
+ st.session_state['cv_builder'] = builder
455
+ st.session_state['cv_loaded'] = True
456
+ st.rerun()
457
+ except Exception as e:
458
+ st.error(f"Model build failed: {str(e)} 💥 (Check logs for details!)")
459
 
460
  with tab2:
461
  st.header("Camera Snap 📷 (Dual Capture!)")
 
489
 
490
  with tab3: # Fine-Tune Titan (NLP)
491
  st.header("Fine-Tune Titan (NLP) 🔧 (Teach Your Word Wizard Some Tricks!)")
492
+ if not st.session_state['nlp_loaded'] or not isinstance(st.session_state['nlp_builder'], ModelBuilder):
493
  st.warning("Please build or load an NLP Titan first! ⚠️ (No word wizard, no magic!)")
494
  else:
495
  if st.button("Generate Sample CSV 📝"):
 
510
  csv_path = f"uploaded_sft_data_{int(time.time())}.csv"
511
  with open(csv_path, "wb") as f:
512
  f.write(uploaded_csv.read())
513
+ new_model_name = f"{st.session_state['nlp_builder'].config.name}-sft-{int(time.time())}"
514
+ new_config = ModelConfig(name=new_model_name, base_model=st.session_state['nlp_builder'].config.base_model, size="small", domain=st.session_state['nlp_builder'].config.domain)
515
+ st.session_state['nlp_builder'].config = new_config
516
  with st.status("Fine-tuning NLP Titan... ⏳ (Whipping words into shape!)", expanded=True) as status:
517
+ st.session_state['nlp_builder'].fine_tune_sft(csv_path)
518
+ st.session_state['nlp_builder'].save_model(new_config.model_path)
519
  status.update(label="Fine-tuning completed! 🎉 (Wordsmith Titan unleashed!)", state="complete")
520
  zip_path = f"{new_config.model_path}.zip"
521
  zip_directory(new_config.model_path, zip_path)
 
523
 
524
  with tab4: # Test Titan (NLP)
525
  st.header("Test Titan (NLP) 🧪 (Put Your Word Wizard to the Test!)")
526
+ if not st.session_state['nlp_loaded'] or not isinstance(st.session_state['nlp_builder'], ModelBuilder):
527
  st.warning("Please build or load an NLP Titan first! ⚠️ (No word wizard, no test drive!)")
528
  else:
529
+ if st.session_state['nlp_builder'].sft_data:
530
  st.write("Testing with SFT Data:")
531
  with st.spinner("Running SFT data tests... ⏳ (Titan’s flexing its word muscles!)"):
532
+ for item in st.session_state['nlp_builder'].sft_data[:3]:
533
  prompt = item["prompt"]
534
  expected = item["response"]
535
  status_container = st.empty()
536
+ generated = st.session_state['nlp_builder'].evaluate(prompt, status_container)
537
  st.write(f"**Prompt**: {prompt}")
538
  st.write(f"**Expected**: {expected}")
539
  st.write(f"**Generated**: {generated} (Titan says: '{random.choice(['Bleep bloop!', 'I am groot!', '42!'])}')")
 
543
  if st.button("Run Test ▶️"):
544
  with st.spinner("Testing your prompt... ⏳ (Titan’s pondering deeply!)"):
545
  status_container = st.empty()
546
+ result = st.session_state['nlp_builder'].evaluate(test_prompt, status_container)
547
  st.write(f"**Generated Response**: {result} (Titan’s wisdom unleashed!)")
548
  status_container.empty()
549
 
550
  with tab5: # Agentic RAG Party (NLP)
551
  st.header("Agentic RAG Party (NLP) 🌐 (Party Like It’s 2099!)")
552
  st.write("This demo uses your SFT-tuned NLP Titan to plan a superhero party with mock retrieval!")
553
+ if not st.session_state['nlp_loaded'] or not isinstance(st.session_state['nlp_builder'], ModelBuilder):
554
  st.warning("Please build or load an NLP Titan first! ⚠️ (No word wizard, no party!)")
555
  else:
556
  if st.button("Run NLP RAG Demo 🎉"):
557
  with st.spinner("Loading your SFT-tuned NLP Titan... ⏳ (Titan’s suiting up!)"):
558
+ agent = PartyPlannerAgent(st.session_state['nlp_builder'].model, st.session_state['nlp_builder'].tokenizer)
559
  st.write("Agent ready! 🦸‍♂️ (Time to plan an epic bash!)")
560
  task = """
561
  Plan a luxury superhero-themed party at Wayne Manor (42.3601° N, 71.0589° W).
 
595
  st.write("Party on, Wayne! 🦸‍♂️🎉")
596
  except Exception as e:
597
  st.error(f"Error planning party: {str(e)} (Even Superman has kryptonite days!)")
598
+ logger.error(f"Error in NLP RAG demo: {str(e)}")
599
 
600
  with tab6: # Fine-Tune Titan (CV)
601
  st.header("Fine-Tune Titan (CV) 🔧 (Paint Your Titan’s Masterpiece!)")
602
+ if not st.session_state['cv_loaded'] or not isinstance(st.session_state['cv_builder'], DiffusionBuilder):
603
  st.warning("Please build or load a CV Titan first! ⚠️ (No artist, no canvas!)")
604
  else:
605
  captured_images = get_gallery_files(["png"])
 
609
  if st.button("Fine-Tune with Dataset 🔄"):
610
  images = [Image.open(row["image"]) for _, row in edited_data.iterrows()]
611
  texts = [row["text"] for _, row in edited_data.iterrows()]
612
+ new_model_name = f"{st.session_state['cv_builder'].config.name}-sft-{int(time.time())}"
613
+ new_config = DiffusionConfig(name=new_model_name, base_model=st.session_state['cv_builder'].config.base_model, size="small")
614
+ st.session_state['cv_builder'].config = new_config
615
  with st.status("Fine-tuning CV Titan... ⏳ (Brushing up those pixels!)", expanded=True) as status:
616
+ st.session_state['cv_builder'].fine_tune_sft(images, texts)
617
+ st.session_state['cv_builder'].save_model(new_config.model_path)
618
  status.update(label="Fine-tuning completed! 🎉 (Pixel Titan unleashed!)", state="complete")
619
  zip_path = f"{new_config.model_path}.zip"
620
  zip_directory(new_config.model_path, zip_path)
 
629
 
630
  with tab7: # Test Titan (CV)
631
  st.header("Test Titan (CV) 🧪 (Unleash Your Pixel Power!)")
632
+ if not st.session_state['cv_loaded'] or not isinstance(st.session_state['cv_builder'], DiffusionBuilder):
633
  st.warning("Please build or load a CV Titan first! ⚠️ (No artist, no masterpiece!)")
634
  else:
635
  test_prompt = st.text_area("Enter Test Prompt 🎨", "Neon Batman", help="Dream up a wild image—your Titan’s got the brush! 🖌️")
636
  if st.button("Run Test ▶️"):
637
  with st.spinner("Painting your masterpiece... ⏳ (Titan’s mixing colors!)"):
638
+ image = st.session_state['cv_builder'].generate(test_prompt)
639
  st.image(image, caption="Generated Image", use_container_width=True)
640
 
641
  with tab8: # Agentic RAG Party (CV)
642
  st.header("Agentic RAG Party (CV) 🌐 (Party with Pixels!)")
643
  st.write("This demo uses your SFT-tuned CV Titan to generate superhero party images with mock retrieval!")
644
+ if not st.session_state['cv_loaded'] or not isinstance(st.session_state['cv_builder'], DiffusionBuilder):
645
  st.warning("Please build or load a CV Titan first! ⚠️ (No artist, no party!)")
646
  else:
647
  if st.button("Run CV RAG Demo 🎉"):
648
  with st.spinner("Loading your SFT-tuned CV Titan... ⏳ (Titan’s grabbing its paintbrush!)"):
649
+ agent = CVPartyPlannerAgent(st.session_state['cv_builder'].pipeline)
650
  st.write("Agent ready! 🎨 (Time to paint an epic bash!)")
651
  task = "Generate images for a luxury superhero-themed party."
652
  with st.spinner("Crafting superhero party visuals... ⏳ (Pixels assemble!)"):
653
+ try:
654
+ plan_df = agent.plan_party(task)
655
+ st.dataframe(plan_df)
656
+ for _, row in plan_df.iterrows():
657
+ image = agent.generate(row["Image Idea"])
658
+ st.image(image, caption=f"{row['Theme']} - {row['Image Idea']}", use_container_width=True)
659
+ except Exception as e:
660
+ st.error(f"Error in CV RAG demo: {str(e)} 💥 (Pixel party crashed!)")
661
+ logger.error(f"Error in CV RAG demo: {str(e)}")
662
 
663
  # Display Logs
664
  st.sidebar.subheader("Action Logs 📜")