awacke1 commited on
Commit
69c1a49
·
verified ·
1 Parent(s): 83f7f1b

Create backup7.app.py

Browse files
Files changed (1) hide show
  1. backup7.app.py +569 -0
backup7.app.py ADDED
@@ -0,0 +1,569 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ # What is working:
3
+ # Img Gen, PDF Download,
4
+ # Next: Get multiple PDF upload 2 workflow pages by image through image fly wheel of AI.
5
+
6
+
7
+ import os
8
+ import glob
9
+ import base64
10
+ import time
11
+ import shutil
12
+ import streamlit as st
13
+ import pandas as pd
14
+ import torch
15
+ import torch.nn as nn
16
+ import torch.nn.functional as F
17
+ from transformers import AutoModelForCausalLM, AutoTokenizer, AutoModel
18
+ from diffusers import StableDiffusionPipeline
19
+ from torch.utils.data import Dataset, DataLoader
20
+ import csv
21
+ import fitz
22
+ import requests
23
+ from PIL import Image
24
+ import cv2
25
+ import numpy as np
26
+ import logging
27
+ import asyncio
28
+ import aiofiles
29
+ from io import BytesIO
30
+ from dataclasses import dataclass
31
+ from typing import Optional, Tuple
32
+ import zipfile
33
+ import math
34
+ import random
35
+ import re
36
+
37
+ logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
38
+ logger = logging.getLogger(__name__)
39
+ log_records = []
40
+
41
+ class LogCaptureHandler(logging.Handler):
42
+ def emit(self, record):
43
+ log_records.append(record)
44
+
45
+ logger.addHandler(LogCaptureHandler())
46
+
47
+ st.set_page_config(
48
+ page_title="AI Vision & SFT Titans 🚀",
49
+ page_icon="🤖",
50
+ layout="wide",
51
+ initial_sidebar_state="expanded",
52
+ menu_items={
53
+ 'Get Help': 'https://huggingface.co/awacke1',
54
+ 'Report a Bug': 'https://huggingface.co/spaces/awacke1',
55
+ 'About': "AI Vision & SFT Titans: PDFs, OCR, Image Gen, Line Drawings, Custom Diffusion, and SFT on CPU! 🌌"
56
+ }
57
+ )
58
+
59
+ if 'history' not in st.session_state:
60
+ st.session_state['history'] = []
61
+ if 'builder' not in st.session_state:
62
+ st.session_state['builder'] = None
63
+ if 'model_loaded' not in st.session_state:
64
+ st.session_state['model_loaded'] = False
65
+ if 'processing' not in st.session_state:
66
+ st.session_state['processing'] = {}
67
+ if 'asset_checkboxes' not in st.session_state:
68
+ st.session_state['asset_checkboxes'] = {}
69
+ if 'downloaded_pdfs' not in st.session_state:
70
+ st.session_state['downloaded_pdfs'] = {}
71
+ if 'unique_counter' not in st.session_state:
72
+ st.session_state['unique_counter'] = 0
73
+ if 'selected_model_type' not in st.session_state:
74
+ st.session_state['selected_model_type'] = "Causal LM"
75
+ if 'selected_model' not in st.session_state:
76
+ st.session_state['selected_model'] = "None"
77
+ if 'cam0_file' not in st.session_state:
78
+ st.session_state['cam0_file'] = None
79
+ if 'cam1_file' not in st.session_state:
80
+ st.session_state['cam1_file'] = None
81
+
82
+ @dataclass
83
+ class ModelConfig:
84
+ name: str
85
+ base_model: str
86
+ size: str
87
+ domain: Optional[str] = None
88
+ model_type: str = "causal_lm"
89
+ @property
90
+ def model_path(self):
91
+ return f"models/{self.name}"
92
+
93
+ @dataclass
94
+ class DiffusionConfig:
95
+ name: str
96
+ base_model: str
97
+ size: str
98
+ domain: Optional[str] = None
99
+ @property
100
+ def model_path(self):
101
+ return f"diffusion_models/{self.name}"
102
+
103
+ class ModelBuilder:
104
+ def __init__(self):
105
+ self.config = None
106
+ self.model = None
107
+ self.tokenizer = None
108
+ self.jokes = ["Why did the AI go to therapy? Too many layers to unpack! 😂", "Training complete! Time for a binary coffee break. ☕"]
109
+ def load_model(self, model_path: str, config: Optional[ModelConfig] = None):
110
+ with st.spinner(f"Loading {model_path}... ⏳"):
111
+ self.model = AutoModelForCausalLM.from_pretrained(model_path)
112
+ self.tokenizer = AutoTokenizer.from_pretrained(model_path)
113
+ if self.tokenizer.pad_token is None:
114
+ self.tokenizer.pad_token = self.tokenizer.eos_token
115
+ if config:
116
+ self.config = config
117
+ self.model.to("cuda" if torch.cuda.is_available() else "cpu")
118
+ st.success(f"Model loaded! 🎉 {random.choice(self.jokes)}")
119
+ return self
120
+ def save_model(self, path: str):
121
+ with st.spinner("Saving model... 💾"):
122
+ os.makedirs(os.path.dirname(path), exist_ok=True)
123
+ self.model.save_pretrained(path)
124
+ self.tokenizer.save_pretrained(path)
125
+ st.success(f"Model saved at {path}! ✅")
126
+
127
+ class DiffusionBuilder:
128
+ def __init__(self):
129
+ self.config = None
130
+ self.pipeline = None
131
+ def load_model(self, model_path: str, config: Optional[DiffusionConfig] = None):
132
+ with st.spinner(f"Loading diffusion model {model_path}... ⏳"):
133
+ self.pipeline = StableDiffusionPipeline.from_pretrained(model_path, torch_dtype=torch.float32).to("cpu")
134
+ if config:
135
+ self.config = config
136
+ st.success(f"Diffusion model loaded! 🎨")
137
+ return self
138
+ def save_model(self, path: str):
139
+ with st.spinner("Saving diffusion model... 💾"):
140
+ os.makedirs(os.path.dirname(path), exist_ok=True)
141
+ self.pipeline.save_pretrained(path)
142
+ st.success(f"Diffusion model saved at {path}! ✅")
143
+ def generate(self, prompt: str):
144
+ return self.pipeline(prompt, num_inference_steps=20).images[0]
145
+
146
+ def generate_filename(sequence, ext="png"):
147
+ timestamp = time.strftime("%d%m%Y%H%M%S")
148
+ return f"{sequence}_{timestamp}.{ext}"
149
+
150
+ def pdf_url_to_filename(url):
151
+ safe_name = re.sub(r'[<>:"/\\|?*]', '_', url)
152
+ return f"{safe_name}.pdf"
153
+
154
+ def get_download_link(file_path, mime_type="application/pdf", label="Download"):
155
+ with open(file_path, 'rb') as f:
156
+ data = f.read()
157
+ b64 = base64.b64encode(data).decode()
158
+ return f'<a href="data:{mime_type};base64,{b64}" download="{os.path.basename(file_path)}">{label}</a>'
159
+
160
+ def zip_directory(directory_path, zip_path):
161
+ with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
162
+ for root, _, files in os.walk(directory_path):
163
+ for file in files:
164
+ zipf.write(os.path.join(root, file), os.path.relpath(os.path.join(root, file), os.path.dirname(directory_path)))
165
+
166
+ def get_model_files(model_type="causal_lm"):
167
+ path = "models/*" if model_type == "causal_lm" else "diffusion_models/*"
168
+ dirs = [d for d in glob.glob(path) if os.path.isdir(d)]
169
+ return dirs if dirs else ["None"]
170
+
171
+ def get_gallery_files(file_types=["png", "pdf"]):
172
+ return sorted(list(set([f for ext in file_types for f in glob.glob(f"*.{ext}")]))) # Deduplicate files
173
+
174
+ def get_pdf_files():
175
+ return sorted(glob.glob("*.pdf"))
176
+
177
+ def download_pdf(url, output_path):
178
+ try:
179
+ response = requests.get(url, stream=True, timeout=10)
180
+ if response.status_code == 200:
181
+ with open(output_path, "wb") as f:
182
+ for chunk in response.iter_content(chunk_size=8192):
183
+ f.write(chunk)
184
+ return True
185
+ except requests.RequestException as e:
186
+ logger.error(f"Failed to download {url}: {e}")
187
+ return False
188
+
189
+ async def process_pdf_snapshot(pdf_path, mode="single"):
190
+ start_time = time.time()
191
+ status = st.empty()
192
+ status.text(f"Processing PDF Snapshot ({mode})... (0s)")
193
+ try:
194
+ doc = fitz.open(pdf_path)
195
+ output_files = []
196
+ if mode == "single":
197
+ page = doc[0]
198
+ pix = page.get_pixmap(matrix=fitz.Matrix(2.0, 2.0))
199
+ output_file = generate_filename("single", "png")
200
+ pix.save(output_file)
201
+ output_files.append(output_file)
202
+ elif mode == "twopage":
203
+ for i in range(min(2, len(doc))):
204
+ page = doc[i]
205
+ pix = page.get_pixmap(matrix=fitz.Matrix(2.0, 2.0))
206
+ output_file = generate_filename(f"twopage_{i}", "png")
207
+ pix.save(output_file)
208
+ output_files.append(output_file)
209
+ elif mode == "allpages":
210
+ for i in range(len(doc)):
211
+ page = doc[i]
212
+ pix = page.get_pixmap(matrix=fitz.Matrix(2.0, 2.0))
213
+ output_file = generate_filename(f"page_{i}", "png")
214
+ pix.save(output_file)
215
+ output_files.append(output_file)
216
+ doc.close()
217
+ elapsed = int(time.time() - start_time)
218
+ status.text(f"PDF Snapshot ({mode}) completed in {elapsed}s!")
219
+ update_gallery()
220
+ return output_files
221
+ except Exception as e:
222
+ status.error(f"Failed to process PDF: {str(e)}")
223
+ return []
224
+
225
+ async def process_ocr(image, output_file):
226
+ start_time = time.time()
227
+ status = st.empty()
228
+ status.text("Processing GOT-OCR2_0... (0s)")
229
+ tokenizer = AutoTokenizer.from_pretrained("ucaslcl/GOT-OCR2_0", trust_remote_code=True)
230
+ model = AutoModel.from_pretrained("ucaslcl/GOT-OCR2_0", trust_remote_code=True, torch_dtype=torch.float32).to("cpu").eval()
231
+ # Save image to temporary file since GOT-OCR2_0 expects a file path
232
+ temp_file = f"temp_{int(time.time())}.png"
233
+ image.save(temp_file)
234
+ result = model.chat(tokenizer, temp_file, ocr_type='ocr')
235
+ os.remove(temp_file) # Clean up temporary file
236
+ elapsed = int(time.time() - start_time)
237
+ status.text(f"GOT-OCR2_0 completed in {elapsed}s!")
238
+ async with aiofiles.open(output_file, "w") as f:
239
+ await f.write(result)
240
+ update_gallery()
241
+ return result
242
+
243
+ async def process_image_gen(prompt, output_file):
244
+ start_time = time.time()
245
+ status = st.empty()
246
+ status.text("Processing Image Gen... (0s)")
247
+ if st.session_state['builder'] and isinstance(st.session_state['builder'], DiffusionBuilder) and st.session_state['builder'].pipeline:
248
+ pipeline = st.session_state['builder'].pipeline
249
+ else:
250
+ pipeline = StableDiffusionPipeline.from_pretrained("OFA-Sys/small-stable-diffusion-v0", torch_dtype=torch.float32).to("cpu")
251
+ gen_image = pipeline(prompt, num_inference_steps=20).images[0]
252
+ elapsed = int(time.time() - start_time)
253
+ status.text(f"Image Gen completed in {elapsed}s!")
254
+ gen_image.save(output_file)
255
+ update_gallery()
256
+ return gen_image
257
+
258
+ st.title("AI Vision & SFT Titans 🚀")
259
+
260
+ # Sidebar
261
+ model_type = st.sidebar.selectbox("Model Type", ["Causal LM", "Diffusion"], key="sidebar_model_type", index=0 if st.session_state['selected_model_type'] == "Causal LM" else 1)
262
+ model_dirs = get_model_files(model_type)
263
+ if model_dirs and st.session_state['selected_model'] == "None" and "None" not in model_dirs:
264
+ st.session_state['selected_model'] = model_dirs[0]
265
+ selected_model = st.sidebar.selectbox("Select Saved Model", model_dirs, key="sidebar_model_select", index=model_dirs.index(st.session_state['selected_model']) if st.session_state['selected_model'] in model_dirs else 0)
266
+ if selected_model != "None" and st.sidebar.button("Load Model 📂"):
267
+ builder = ModelBuilder() if model_type == "Causal LM" else DiffusionBuilder()
268
+ config = (ModelConfig if model_type == "Causal LM" else DiffusionConfig)(name=os.path.basename(selected_model), base_model="unknown", size="small")
269
+ builder.load_model(selected_model, config)
270
+ st.session_state['builder'] = builder
271
+ st.session_state['model_loaded'] = True
272
+ st.rerun()
273
+
274
+ st.sidebar.header("Captured Files 📜")
275
+ cols = st.sidebar.columns(2)
276
+ with cols[0]:
277
+ if st.button("Zip All 🤐"):
278
+ zip_path = f"all_assets_{int(time.time())}.zip"
279
+ with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
280
+ for file in get_gallery_files():
281
+ zipf.write(file, os.path.basename(file))
282
+ st.sidebar.markdown(get_download_link(zip_path, "application/zip", "Download All Assets"), unsafe_allow_html=True)
283
+ with cols[1]:
284
+ if st.button("Zap All! 🗑️"):
285
+ for file in get_gallery_files():
286
+ os.remove(file)
287
+ st.session_state['asset_checkboxes'].clear()
288
+ st.session_state['downloaded_pdfs'].clear()
289
+ st.session_state['cam0_file'] = None
290
+ st.session_state['cam1_file'] = None
291
+ st.sidebar.success("All assets vaporized! 💨")
292
+ st.rerun()
293
+
294
+ gallery_size = st.sidebar.slider("Gallery Size", 1, 10, 2)
295
+ def update_gallery():
296
+ all_files = get_gallery_files()
297
+ if all_files:
298
+ st.sidebar.subheader("Asset Gallery 📸📖")
299
+ cols = st.sidebar.columns(2)
300
+ for idx, file in enumerate(all_files[:gallery_size * 2]):
301
+ with cols[idx % 2]:
302
+ st.session_state['unique_counter'] += 1
303
+ unique_id = st.session_state['unique_counter']
304
+ if file.endswith('.png'):
305
+ st.image(Image.open(file), caption=os.path.basename(file), use_container_width=True)
306
+ else:
307
+ doc = fitz.open(file)
308
+ pix = doc[0].get_pixmap(matrix=fitz.Matrix(0.5, 0.5))
309
+ img = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)
310
+ st.image(img, caption=os.path.basename(file), use_container_width=True)
311
+ doc.close()
312
+ checkbox_key = f"asset_{file}_{unique_id}"
313
+ st.session_state['asset_checkboxes'][file] = st.checkbox(
314
+ "Use for SFT/Input",
315
+ value=st.session_state['asset_checkboxes'].get(file, False),
316
+ key=checkbox_key
317
+ )
318
+ mime_type = "image/png" if file.endswith('.png') else "application/pdf"
319
+ st.markdown(get_download_link(file, mime_type, "Snag It! 📥"), unsafe_allow_html=True)
320
+ if st.button("Zap It! 🗑️", key=f"delete_{file}_{unique_id}"):
321
+ os.remove(file)
322
+ if file in st.session_state['asset_checkboxes']:
323
+ del st.session_state['asset_checkboxes'][file]
324
+ if file.endswith('.pdf'):
325
+ url_key = next((k for k, v in st.session_state['downloaded_pdfs'].items() if v == file), None)
326
+ if url_key:
327
+ del st.session_state['downloaded_pdfs'][url_key]
328
+ if file == st.session_state['cam0_file']:
329
+ st.session_state['cam0_file'] = None
330
+ if file == st.session_state['cam1_file']:
331
+ st.session_state['cam1_file'] = None
332
+ st.sidebar.success(f"Asset {os.path.basename(file)} vaporized! 💨")
333
+ st.rerun()
334
+ update_gallery()
335
+
336
+ st.sidebar.subheader("Action Logs 📜")
337
+ log_container = st.sidebar.empty()
338
+ with log_container:
339
+ for record in log_records:
340
+ st.write(f"{record.asctime} - {record.levelname} - {record.message}")
341
+
342
+ st.sidebar.subheader("History 📜")
343
+ history_container = st.sidebar.empty()
344
+ with history_container:
345
+ for entry in st.session_state['history'][-gallery_size * 2:]:
346
+ st.write(entry)
347
+
348
+ tab1, tab2, tab3, tab4 = st.tabs([
349
+ "Camera Snap 📷", "Download PDFs 📥", "Test OCR 🔍", "Build Titan 🌱"
350
+ ])
351
+
352
+ with tab1:
353
+ st.header("Camera Snap 📷")
354
+ st.subheader("Single Capture")
355
+ cols = st.columns(2)
356
+ with cols[0]:
357
+ cam0_img = st.camera_input("Take a picture - Cam 0", key="cam0")
358
+ if cam0_img:
359
+ filename = generate_filename("cam0")
360
+ if st.session_state['cam0_file'] and os.path.exists(st.session_state['cam0_file']):
361
+ os.remove(st.session_state['cam0_file'])
362
+ with open(filename, "wb") as f:
363
+ f.write(cam0_img.getvalue())
364
+ st.session_state['cam0_file'] = filename
365
+ entry = f"Snapshot from Cam 0: {filename}"
366
+ if entry not in st.session_state['history']:
367
+ st.session_state['history'] = [e for e in st.session_state['history'] if not e.startswith("Snapshot from Cam 0:")] + [entry]
368
+ st.image(Image.open(filename), caption="Camera 0", use_container_width=True)
369
+ logger.info(f"Saved snapshot from Camera 0: {filename}")
370
+ update_gallery()
371
+ elif st.session_state['cam0_file'] and os.path.exists(st.session_state['cam0_file']):
372
+ st.image(Image.open(st.session_state['cam0_file']), caption="Camera 0", use_container_width=True)
373
+ with cols[1]:
374
+ cam1_img = st.camera_input("Take a picture - Cam 1", key="cam1")
375
+ if cam1_img:
376
+ filename = generate_filename("cam1")
377
+ if st.session_state['cam1_file'] and os.path.exists(st.session_state['cam1_file']):
378
+ os.remove(st.session_state['cam1_file'])
379
+ with open(filename, "wb") as f:
380
+ f.write(cam1_img.getvalue())
381
+ st.session_state['cam1_file'] = filename
382
+ entry = f"Snapshot from Cam 1: {filename}"
383
+ if entry not in st.session_state['history']:
384
+ st.session_state['history'] = [e for e in st.session_state['history'] if not e.startswith("Snapshot from Cam 1:")] + [entry]
385
+ st.image(Image.open(filename), caption="Camera 1", use_container_width=True)
386
+ logger.info(f"Saved snapshot from Camera 1: {filename}")
387
+ update_gallery()
388
+ elif st.session_state['cam1_file'] and os.path.exists(st.session_state['cam1_file']):
389
+ st.image(Image.open(st.session_state['cam1_file']), caption="Camera 1", use_container_width=True)
390
+
391
+ with tab2:
392
+ st.header("Download PDFs 📥")
393
+ if st.button("Examples 📚"):
394
+ example_urls = [
395
+ "https://arxiv.org/pdf/2308.03892",
396
+ "https://arxiv.org/pdf/1912.01703",
397
+ "https://arxiv.org/pdf/2408.11039",
398
+ "https://arxiv.org/pdf/2109.10282",
399
+ "https://arxiv.org/pdf/2112.10752",
400
+ "https://arxiv.org/pdf/2308.11236",
401
+ "https://arxiv.org/pdf/1706.03762",
402
+ "https://arxiv.org/pdf/2006.11239",
403
+ "https://arxiv.org/pdf/2305.11207",
404
+ "https://arxiv.org/pdf/2106.09685",
405
+ "https://arxiv.org/pdf/2005.11401",
406
+ "https://arxiv.org/pdf/2106.10504"
407
+ ]
408
+ st.session_state['pdf_urls'] = "\n".join(example_urls)
409
+
410
+ url_input = st.text_area("Enter PDF URLs (one per line)", value=st.session_state.get('pdf_urls', ""), height=200)
411
+ if st.button("Robo-Download 🤖"):
412
+ urls = url_input.strip().split("\n")
413
+ progress_bar = st.progress(0)
414
+ status_text = st.empty()
415
+ total_urls = len(urls)
416
+ existing_pdfs = get_pdf_files()
417
+ for idx, url in enumerate(urls):
418
+ if url:
419
+ output_path = pdf_url_to_filename(url)
420
+ status_text.text(f"Fetching {idx + 1}/{total_urls}: {os.path.basename(output_path)}...")
421
+ if output_path not in existing_pdfs:
422
+ if download_pdf(url, output_path):
423
+ st.session_state['downloaded_pdfs'][url] = output_path
424
+ logger.info(f"Downloaded PDF from {url} to {output_path}")
425
+ entry = f"Downloaded PDF: {output_path}"
426
+ if entry not in st.session_state['history']:
427
+ st.session_state['history'].append(entry)
428
+ st.session_state['asset_checkboxes'][output_path] = True # Auto-check the box
429
+ else:
430
+ st.error(f"Failed to nab {url} 😿")
431
+ else:
432
+ st.info(f"Already got {os.path.basename(output_path)}! Skipping... 🐾")
433
+ st.session_state['downloaded_pdfs'][url] = output_path
434
+ progress_bar.progress((idx + 1) / total_urls)
435
+ status_text.text("Robo-Download complete! 🚀")
436
+ update_gallery()
437
+
438
+ mode = st.selectbox("Snapshot Mode", ["Single Page (High-Res)", "Two Pages (High-Res)", "All Pages (High-Res)"], key="download_mode")
439
+ if st.button("Snapshot Selected 📸"):
440
+ selected_pdfs = [path for path in get_gallery_files() if path.endswith('.pdf') and st.session_state['asset_checkboxes'].get(path, False)]
441
+ if selected_pdfs:
442
+ for pdf_path in selected_pdfs:
443
+ mode_key = {"Single Page (High-Res)": "single", "Two Pages (High-Res)": "twopage", "All Pages (High-Res)": "allpages"}[mode]
444
+ snapshots = asyncio.run(process_pdf_snapshot(pdf_path, mode_key))
445
+ for snapshot in snapshots:
446
+ st.image(Image.open(snapshot), caption=snapshot, use_container_width=True)
447
+ st.session_state['asset_checkboxes'][snapshot] = True # Auto-check new snapshots
448
+ update_gallery()
449
+ else:
450
+ st.warning("No PDFs selected for snapshotting! Check some boxes in the sidebar gallery.")
451
+
452
+ with tab3:
453
+ st.header("Test OCR 🔍")
454
+ all_files = get_gallery_files()
455
+ if all_files:
456
+ if st.button("OCR All Assets 🚀"):
457
+ full_text = "# OCR Results\n\n"
458
+ for file in all_files:
459
+ if file.endswith('.png'):
460
+ image = Image.open(file)
461
+ else:
462
+ doc = fitz.open(file)
463
+ pix = doc[0].get_pixmap(matrix=fitz.Matrix(2.0, 2.0))
464
+ image = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)
465
+ doc.close()
466
+ output_file = generate_filename(f"ocr_{os.path.basename(file)}", "txt")
467
+ result = asyncio.run(process_ocr(image, output_file))
468
+ full_text += f"## {os.path.basename(file)}\n\n{result}\n\n"
469
+ entry = f"OCR Test: {file} -> {output_file}"
470
+ if entry not in st.session_state['history']:
471
+ st.session_state['history'].append(entry)
472
+ md_output_file = f"full_ocr_{int(time.time())}.md"
473
+ with open(md_output_file, "w") as f:
474
+ f.write(full_text)
475
+ st.success(f"Full OCR saved to {md_output_file}")
476
+ st.markdown(get_download_link(md_output_file, "text/markdown", "Download Full OCR Markdown"), unsafe_allow_html=True)
477
+ selected_file = st.selectbox("Select Image or PDF", all_files, key="ocr_select")
478
+ if selected_file:
479
+ if selected_file.endswith('.png'):
480
+ image = Image.open(selected_file)
481
+ else:
482
+ doc = fitz.open(selected_file)
483
+ pix = doc[0].get_pixmap(matrix=fitz.Matrix(2.0, 2.0))
484
+ image = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)
485
+ doc.close()
486
+ st.image(image, caption="Input Image", use_container_width=True)
487
+ if st.button("Run OCR 🚀", key="ocr_run"):
488
+ output_file = generate_filename("ocr_output", "txt")
489
+ st.session_state['processing']['ocr'] = True
490
+ result = asyncio.run(process_ocr(image, output_file))
491
+ entry = f"OCR Test: {selected_file} -> {output_file}"
492
+ if entry not in st.session_state['history']:
493
+ st.session_state['history'].append(entry)
494
+ st.text_area("OCR Result", result, height=200, key="ocr_result")
495
+ st.success(f"OCR output saved to {output_file}")
496
+ st.session_state['processing']['ocr'] = False
497
+ if selected_file.endswith('.pdf') and st.button("OCR All Pages 🚀", key="ocr_all_pages"):
498
+ doc = fitz.open(selected_file)
499
+ full_text = f"# OCR Results for {os.path.basename(selected_file)}\n\n"
500
+ for i in range(len(doc)):
501
+ pix = doc[i].get_pixmap(matrix=fitz.Matrix(2.0, 2.0))
502
+ image = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)
503
+ output_file = generate_filename(f"ocr_page_{i}", "txt")
504
+ result = asyncio.run(process_ocr(image, output_file))
505
+ full_text += f"## Page {i + 1}\n\n{result}\n\n"
506
+ entry = f"OCR Test: {selected_file} Page {i + 1} -> {output_file}"
507
+ if entry not in st.session_state['history']:
508
+ st.session_state['history'].append(entry)
509
+ md_output_file = f"full_ocr_{os.path.basename(selected_file)}_{int(time.time())}.md"
510
+ with open(md_output_file, "w") as f:
511
+ f.write(full_text)
512
+ st.success(f"Full OCR saved to {md_output_file}")
513
+ st.markdown(get_download_link(md_output_file, "text/markdown", "Download Full OCR Markdown"), unsafe_allow_html=True)
514
+ else:
515
+ st.warning("No assets in gallery yet. Use Camera Snap or Download PDFs!")
516
+
517
+ with tab4:
518
+ st.header("Build Titan 🌱")
519
+ model_type = st.selectbox("Model Type", ["Causal LM", "Diffusion"], key="build_type")
520
+ base_model = st.selectbox("Select Tiny Model",
521
+ ["HuggingFaceTB/SmolLM-135M", "Qwen/Qwen1.5-0.5B-Chat"] if model_type == "Causal LM" else
522
+ ["OFA-Sys/small-stable-diffusion-v0", "stabilityai/stable-diffusion-2-base"])
523
+ model_name = st.text_input("Model Name", f"tiny-titan-{int(time.time())}")
524
+ domain = st.text_input("Target Domain", "general")
525
+ if st.button("Download Model ⬇️"):
526
+ config = (ModelConfig if model_type == "Causal LM" else DiffusionConfig)(name=model_name, base_model=base_model, size="small", domain=domain)
527
+ builder = ModelBuilder() if model_type == "Causal LM" else DiffusionBuilder()
528
+ builder.load_model(base_model, config)
529
+ builder.save_model(config.model_path)
530
+ st.session_state['builder'] = builder
531
+ st.session_state['model_loaded'] = True
532
+ st.session_state['selected_model_type'] = model_type
533
+ st.session_state['selected_model'] = config.model_path
534
+ entry = f"Built {model_type} model: {model_name}"
535
+ if entry not in st.session_state['history']:
536
+ st.session_state['history'].append(entry)
537
+ st.success(f"Model downloaded and saved to {config.model_path}! 🎉")
538
+ st.rerun()
539
+
540
+ tab5 = st.tabs(["Test Image Gen 🎨"])[0]
541
+ with tab5:
542
+ st.header("Test Image Gen 🎨")
543
+ all_files = get_gallery_files()
544
+ if all_files:
545
+ selected_file = st.selectbox("Select Image or PDF", all_files, key="gen_select")
546
+ if selected_file:
547
+ if selected_file.endswith('.png'):
548
+ image = Image.open(selected_file)
549
+ else:
550
+ doc = fitz.open(selected_file)
551
+ pix = doc[0].get_pixmap(matrix=fitz.Matrix(2.0, 2.0))
552
+ image = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)
553
+ doc.close()
554
+ st.image(image, caption="Reference Image", use_container_width=True)
555
+ prompt = st.text_area("Prompt", "Generate a neon superhero version of this image", key="gen_prompt")
556
+ if st.button("Run Image Gen 🚀", key="gen_run"):
557
+ output_file = generate_filename("gen_output", "png")
558
+ st.session_state['processing']['gen'] = True
559
+ result = asyncio.run(process_image_gen(prompt, output_file))
560
+ entry = f"Image Gen Test: {prompt} -> {output_file}"
561
+ if entry not in st.session_state['history']:
562
+ st.session_state['history'].append(entry)
563
+ st.image(result, caption="Generated Image", use_container_width=True)
564
+ st.success(f"Image saved to {output_file}")
565
+ st.session_state['processing']['gen'] = False
566
+ else:
567
+ st.warning("No images or PDFs in gallery yet. Use Camera Snap or Download PDFs!")
568
+
569
+ update_gallery()