Update app.py
Browse files
app.py
CHANGED
@@ -1,381 +1,227 @@
|
|
|
|
|
|
1 |
import os
|
2 |
-
import random
|
3 |
-
import uuid
|
4 |
import base64
|
5 |
-
import json
|
6 |
-
import re
|
7 |
-
import gradio as gr
|
8 |
-
import numpy as np
|
9 |
-
from PIL import Image
|
10 |
-
import torch
|
11 |
import glob
|
12 |
-
|
13 |
-
import pandas as pd
|
14 |
-
import anthropic
|
15 |
import pytz
|
16 |
-
|
17 |
-
from
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
def save_json(file, data):
|
39 |
-
with open(file, 'w', encoding='utf-8') as f:
|
40 |
-
json.dump(data, f, indent=4)
|
41 |
-
|
42 |
-
likes_cache = load_json(LIKES_CACHE_FILE) or {}
|
43 |
-
all_logs = load_json(LOG_CACHE_FILE) if os.path.exists(LOG_CACHE_FILE) else []
|
44 |
-
quotes_cache = load_json(QUOTE_CACHE_FILE) if os.path.exists(QUOTE_CACHE_FILE) else []
|
45 |
-
|
46 |
-
# Image metadata
|
47 |
-
image_metadata = pd.DataFrame(columns=['Filename', 'Prompt', 'Likes', 'Dislikes', 'Hearts', 'Created'])
|
48 |
-
|
49 |
-
# ---------- Anthropic (Claude) Setup (optional) ---------- #
|
50 |
-
anthropic_api_key = os.environ.get("ANTHROPIC_API_KEY", None)
|
51 |
-
claude_client = anthropic.Anthropic(api_key=anthropic_api_key) if anthropic_api_key else None
|
52 |
-
|
53 |
-
# ------------------ Logging of Inputs/Outputs ------------------ #
|
54 |
-
def log_input_output(user_input, model_output, file_link=""):
|
55 |
-
global all_logs
|
56 |
-
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
57 |
-
new_entry = {
|
58 |
-
"timestamp": timestamp,
|
59 |
-
"input": user_input,
|
60 |
-
"output": model_output,
|
61 |
-
"file_link": file_link
|
62 |
-
}
|
63 |
-
all_logs.append(new_entry)
|
64 |
-
save_json(LOG_CACHE_FILE, all_logs)
|
65 |
-
|
66 |
-
# ------------------ Votes & Images ------------------ #
|
67 |
-
def load_likes_cache():
|
68 |
-
return likes_cache
|
69 |
-
|
70 |
-
def save_likes_cache():
|
71 |
-
save_json(LIKES_CACHE_FILE, likes_cache)
|
72 |
-
|
73 |
-
def get_image_caption(filename):
|
74 |
-
global likes_cache, image_metadata
|
75 |
-
if filename in likes_cache:
|
76 |
-
likes = likes_cache[filename]['likes']
|
77 |
-
dislikes = likes_cache[filename]['dislikes']
|
78 |
-
hearts = likes_cache[filename]['hearts']
|
79 |
-
row = image_metadata.loc[image_metadata['Filename'] == filename]
|
80 |
-
if not row.empty:
|
81 |
-
prompt = row.iloc[0]['Prompt']
|
82 |
-
return f"{filename}\nPrompt: {prompt}\n👍 {likes} 👎 {dislikes} ❤️ {hearts}"
|
83 |
-
return filename
|
84 |
-
|
85 |
-
def get_image_gallery():
|
86 |
-
global image_metadata
|
87 |
-
image_files = image_metadata['Filename'].tolist()
|
88 |
-
return [
|
89 |
-
(file, get_image_caption(file))
|
90 |
-
for file in image_files if os.path.exists(file)
|
91 |
-
]
|
92 |
-
|
93 |
-
def delete_all_images():
|
94 |
-
global image_metadata, likes_cache
|
95 |
-
for file in image_metadata['Filename']:
|
96 |
-
if os.path.exists(file):
|
97 |
-
os.remove(file)
|
98 |
-
image_metadata = pd.DataFrame(columns=['Filename','Prompt','Likes','Dislikes','Hearts','Created'])
|
99 |
-
likes_cache.clear()
|
100 |
-
save_likes_cache()
|
101 |
-
return get_image_gallery(), image_metadata.values.tolist()
|
102 |
-
|
103 |
-
def delete_image(filename):
|
104 |
-
global image_metadata, likes_cache
|
105 |
-
if filename and os.path.exists(filename):
|
106 |
-
os.remove(filename)
|
107 |
-
image_metadata = image_metadata[image_metadata['Filename'] != filename]
|
108 |
-
if filename in likes_cache:
|
109 |
-
del likes_cache[filename]
|
110 |
-
save_likes_cache()
|
111 |
-
return get_image_gallery(), image_metadata.values.tolist()
|
112 |
-
|
113 |
-
def vote(filename, vote_type):
|
114 |
-
global likes_cache, image_metadata
|
115 |
-
if filename in likes_cache:
|
116 |
-
likes_cache[filename][vote_type.lower()] += 1
|
117 |
-
save_likes_cache()
|
118 |
-
# Reflect in dataframe
|
119 |
-
row_idx = image_metadata[image_metadata['Filename'] == filename].index
|
120 |
-
if not row_idx.empty:
|
121 |
-
col = vote_type.capitalize()
|
122 |
-
curr_val = image_metadata.at[row_idx[0], col]
|
123 |
-
image_metadata.at[row_idx[0], col] = curr_val + 1
|
124 |
-
return get_image_gallery(), image_metadata.values.tolist()
|
125 |
-
|
126 |
-
# ------------------ Image Generation (Original Code) ------------------ #
|
127 |
-
MAX_SEED = np.iinfo(np.int32).max
|
128 |
-
if not torch.cuda.is_available():
|
129 |
-
DESCRIPTION += "\n<p>Running on CPU 🥶 This demo may not work on CPU.</p>"
|
130 |
-
|
131 |
-
# Load pipeline
|
132 |
-
if torch.cuda.is_available():
|
133 |
-
pipe = StableDiffusionXLPipeline.from_pretrained(
|
134 |
-
"fluently/Fluently-XL-v4",
|
135 |
-
torch_dtype=torch.float16,
|
136 |
-
use_safetensors=True,
|
137 |
-
)
|
138 |
-
pipe.scheduler = EulerAncestralDiscreteScheduler.from_config(pipe.scheduler.config)
|
139 |
-
pipe.load_lora_weights("ehristoforu/dalle-3-xl-v2", weight_name="dalle-3-xl-lora-v2.safetensors", adapter_name="dalle")
|
140 |
-
pipe.set_adapters("dalle")
|
141 |
-
pipe.to("cuda")
|
142 |
-
else:
|
143 |
-
pipe = None
|
144 |
-
|
145 |
-
def randomize_seed_fn(seed: int, randomize_seed: bool):
|
146 |
-
if randomize_seed:
|
147 |
-
seed = random.randint(0, MAX_SEED)
|
148 |
-
return seed
|
149 |
-
|
150 |
-
def save_image(img, prompt):
|
151 |
-
global image_metadata, likes_cache
|
152 |
-
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
153 |
-
safe_prompt = re.sub(r'[^\w\s-]', '', prompt.lower())[:50]
|
154 |
-
safe_prompt = re.sub(r'[-\s]+', '-', safe_prompt).strip('-')
|
155 |
-
filename = f"{timestamp}_{safe_prompt}.png"
|
156 |
-
img.save(filename)
|
157 |
-
# Add metadata row
|
158 |
-
new_row = {
|
159 |
-
'Filename': filename,
|
160 |
-
'Prompt': prompt,
|
161 |
-
'Likes': 0,
|
162 |
-
'Dislikes': 0,
|
163 |
-
'Hearts': 0,
|
164 |
-
'Created': datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
165 |
}
|
166 |
-
|
167 |
-
likes_cache[filename] = {'likes': 0, 'dislikes': 0, 'hearts': 0}
|
168 |
-
save_likes_cache()
|
169 |
-
return filename
|
170 |
-
|
171 |
-
def generate(
|
172 |
-
prompt: str,
|
173 |
-
negative_prompt: str = "",
|
174 |
-
use_negative_prompt: bool = False,
|
175 |
-
seed: int = 0,
|
176 |
-
width: int = 1024,
|
177 |
-
height: int = 1024,
|
178 |
-
guidance_scale: float = 3,
|
179 |
-
randomize_seed: bool = False,
|
180 |
-
progress=gr.Progress(track_tqdm=True),
|
181 |
-
):
|
182 |
-
if pipe is None:
|
183 |
-
return ["Error: No GPU or pipeline not loaded"], 0, [], get_image_gallery(), image_metadata.values.tolist()
|
184 |
-
|
185 |
-
seed = randomize_seed_fn(seed, randomize_seed)
|
186 |
-
if not use_negative_prompt:
|
187 |
-
negative_prompt = ""
|
188 |
-
|
189 |
-
images = pipe(
|
190 |
-
prompt=prompt,
|
191 |
-
negative_prompt=negative_prompt,
|
192 |
-
width=width,
|
193 |
-
height=height,
|
194 |
-
guidance_scale=guidance_scale,
|
195 |
-
num_inference_steps=20,
|
196 |
-
num_images_per_prompt=1,
|
197 |
-
cross_attention_kwargs={"scale": 0.65},
|
198 |
-
output_type="pil",
|
199 |
-
).images
|
200 |
-
|
201 |
-
image_paths = [save_image(img, prompt) for img in images]
|
202 |
-
# Build static-content file links
|
203 |
-
file_links = [f"{URL_PREFIX}{p}" for p in image_paths]
|
204 |
-
|
205 |
-
# Log this generation
|
206 |
-
log_input_output(user_input=prompt, model_output="(image generated)", file_link=", ".join(file_links))
|
207 |
|
208 |
-
|
|
|
209 |
|
210 |
-
#
|
211 |
-
|
212 |
-
|
213 |
-
"Impressionist", "Cubist", "Surrealist", "Abstract Expressionist",
|
214 |
-
"Pop Art", "Minimalist", "Baroque", "Art Nouveau", "Pointillist", "Fauvism"
|
215 |
-
]
|
216 |
-
return random.choice(styles)
|
217 |
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
|
|
|
|
223 |
|
224 |
-
#
|
225 |
-
def
|
226 |
-
if not claude_client:
|
227 |
-
# If no API key or no client
|
228 |
-
return "Claude not available. Set ANTHROPIC_API_KEY."
|
229 |
-
if not user_input.strip():
|
230 |
-
return "No input provided."
|
231 |
-
|
232 |
-
response = claude_client.messages.create(
|
233 |
-
model="claude-3-sonnet-20240229",
|
234 |
-
max_tokens=1000,
|
235 |
-
messages=[{"role": "user", "content": user_input}]
|
236 |
-
)
|
237 |
-
text = response.content[0].text
|
238 |
-
log_input_output(user_input, text, "")
|
239 |
-
return text
|
240 |
-
|
241 |
-
# ------------------ Quotes Feature (Short Version) ------------------ #
|
242 |
-
def get_quotes_df():
|
243 |
-
return pd.DataFrame(quotes_cache) if quotes_cache else pd.DataFrame(columns=["text", "likes", "created"])
|
244 |
-
|
245 |
-
def add_quote(quote_text):
|
246 |
-
if not quote_text.strip():
|
247 |
-
return get_quotes_df()
|
248 |
central = pytz.timezone('US/Central')
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
return
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
if
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
#
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
301 |
)
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
-
|
323 |
-
|
324 |
-
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
with
|
357 |
-
|
358 |
-
|
359 |
-
quote_data = gr.Dataframe(headers=["text","likes","created"], interactive=False)
|
360 |
-
with gr.Row():
|
361 |
-
row_index = gr.Number(label="Index to like:")
|
362 |
-
like_btn = gr.Button("Like Quote")
|
363 |
-
|
364 |
-
add_quote_btn.click(fn=add_quote, inputs=quote_text, outputs=quote_data)
|
365 |
-
like_btn.click(fn=like_quote, inputs=row_index, outputs=quote_data)
|
366 |
-
|
367 |
-
with gr.Tab("Logs"):
|
368 |
-
gr.Markdown("#### All logged inputs & outputs")
|
369 |
-
logs_data = gr.Dataframe(
|
370 |
-
label="Log Data",
|
371 |
-
value=pd.DataFrame(all_logs),
|
372 |
-
interactive=False
|
373 |
-
)
|
374 |
-
|
375 |
-
def update_gallery_and_metadata():
|
376 |
-
return gr.update(value=get_image_gallery()), gr.update(value=image_metadata.values.tolist())
|
377 |
-
|
378 |
-
demo.load(fn=update_gallery_and_metadata, outputs=[image_gallery, metadata_df])
|
379 |
|
380 |
if __name__ == "__main__":
|
381 |
-
|
|
|
1 |
+
import streamlit as st
|
2 |
+
import anthropic
|
3 |
import os
|
|
|
|
|
4 |
import base64
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
import glob
|
6 |
+
import json
|
|
|
|
|
7 |
import pytz
|
8 |
+
from datetime import datetime
|
9 |
+
from streamlit.components.v1 import html
|
10 |
+
from PIL import Image
|
11 |
+
import re
|
12 |
+
from urllib.parse import quote
|
13 |
+
|
14 |
+
# 1. Configuration
|
15 |
+
Site_Name = '🤖🧠Ant🔬Claude📝'
|
16 |
+
title="🤖🧠Ant🔬Claude📝"
|
17 |
+
helpURL='https://huggingface.co/awacke1'
|
18 |
+
bugURL='https://huggingface.co/spaces/awacke1'
|
19 |
+
icons='🤖🧠🔬📝'
|
20 |
+
st.set_page_config(
|
21 |
+
page_title=title,
|
22 |
+
page_icon=icons,
|
23 |
+
layout="wide",
|
24 |
+
#initial_sidebar_state="expanded",
|
25 |
+
initial_sidebar_state="auto",
|
26 |
+
menu_items={
|
27 |
+
'Get Help': helpURL,
|
28 |
+
'Report a bug': bugURL,
|
29 |
+
'About': title
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
}
|
31 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
32 |
|
33 |
+
# Set up the Anthropic client
|
34 |
+
client = anthropic.Anthropic(api_key=os.environ.get("ANTHROPIC_API_KEY"))
|
35 |
|
36 |
+
# Initialize session state
|
37 |
+
if "chat_history" not in st.session_state:
|
38 |
+
st.session_state.chat_history = []
|
|
|
|
|
|
|
|
|
39 |
|
40 |
+
# Function to get file download link
|
41 |
+
def get_download_link(file_path):
|
42 |
+
with open(file_path, "rb") as file:
|
43 |
+
contents = file.read()
|
44 |
+
b64 = base64.b64encode(contents).decode()
|
45 |
+
file_name = os.path.basename(file_path)
|
46 |
+
return f'<a href="data:file/txt;base64,{b64}" download="{file_name}">Download {file_name}</a>'
|
47 |
|
48 |
+
# Function to generate filename
|
49 |
+
def generate_filename(prompt, file_type):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
central = pytz.timezone('US/Central')
|
51 |
+
safe_date_time = datetime.now(central).strftime("%m%d_%H%M")
|
52 |
+
replaced_prompt = prompt.replace(" ", "_").replace("\n", "_")
|
53 |
+
safe_prompt = "".join(x for x in replaced_prompt if x.isalnum() or x == "_")[:90]
|
54 |
+
return f"{safe_date_time}_{safe_prompt}.{file_type}"
|
55 |
+
|
56 |
+
# Function to create file
|
57 |
+
def create_file(filename, prompt, response, should_save=True):
|
58 |
+
if not should_save:
|
59 |
+
return
|
60 |
+
with open(filename, 'w', encoding='utf-8') as file:
|
61 |
+
file.write(prompt + "\n\n" + response)
|
62 |
+
|
63 |
+
# Function to load file content
|
64 |
+
def load_file(file_name):
|
65 |
+
with open(file_name, "r", encoding='utf-8') as file:
|
66 |
+
content = file.read()
|
67 |
+
return content
|
68 |
+
|
69 |
+
# Function to display glossary entity
|
70 |
+
def display_glossary_entity(k):
|
71 |
+
search_urls = {
|
72 |
+
"🚀🌌ArXiv": lambda k: f"/?q={quote(k)}",
|
73 |
+
"📖": lambda k: f"https://en.wikipedia.org/wiki/{quote(k)}",
|
74 |
+
"🔍": lambda k: f"https://www.google.com/search?q={quote(k)}",
|
75 |
+
"🎥": lambda k: f"https://www.youtube.com/results?search_query={quote(k)}",
|
76 |
+
}
|
77 |
+
links_md = ' '.join([f"[{emoji}]({url(k)})" for emoji, url in search_urls.items()])
|
78 |
+
st.markdown(f"**{k}** <small>{links_md}</small>", unsafe_allow_html=True)
|
79 |
+
|
80 |
+
# Function to create zip of files
|
81 |
+
def create_zip_of_files(files):
|
82 |
+
import zipfile
|
83 |
+
zip_name = "all_files.zip"
|
84 |
+
with zipfile.ZipFile(zip_name, 'w') as zipf:
|
85 |
+
for file in files:
|
86 |
+
zipf.write(file)
|
87 |
+
return zip_name
|
88 |
+
|
89 |
+
# Function to get zip download link
|
90 |
+
def get_zip_download_link(zip_file):
|
91 |
+
with open(zip_file, 'rb') as f:
|
92 |
+
data = f.read()
|
93 |
+
b64 = base64.b64encode(data).decode()
|
94 |
+
href = f'<a href="data:application/zip;base64,{b64}" download="{zip_file}">Download All</a>'
|
95 |
+
return href
|
96 |
+
|
97 |
+
# Function to create HTML for autoplaying and looping video
|
98 |
+
def get_video_html(video_path, width="100%"):
|
99 |
+
video_url = f"data:video/mp4;base64,{base64.b64encode(open(video_path, 'rb').read()).decode()}"
|
100 |
+
return f'''
|
101 |
+
<video width="{width}" controls autoplay muted loop>
|
102 |
+
<source src="{video_url}" type="video/mp4">
|
103 |
+
Your browser does not support the video tag.
|
104 |
+
</video>
|
105 |
+
'''
|
106 |
+
|
107 |
+
# Function to create HTML for audio player
|
108 |
+
def get_audio_html(audio_path, width="100%"):
|
109 |
+
audio_url = f"data:audio/mpeg;base64,{base64.b64encode(open(audio_path, 'rb').read()).decode()}"
|
110 |
+
return f'''
|
111 |
+
<audio controls style="width: {width};">
|
112 |
+
<source src="{audio_url}" type="audio/mpeg">
|
113 |
+
Your browser does not support the audio element.
|
114 |
+
</audio>
|
115 |
+
'''
|
116 |
+
|
117 |
+
|
118 |
+
|
119 |
+
# Streamlit app
|
120 |
+
def main():
|
121 |
+
|
122 |
+
# Sidebar
|
123 |
+
st.sidebar.title("🤖🧠Ant🔬Claude📝🔊 - Anthropic Claude 3.5 Sonnet")
|
124 |
+
|
125 |
+
# File management
|
126 |
+
all_files = glob.glob("*.md")
|
127 |
+
all_files = [file for file in all_files if len(os.path.splitext(file)[0]) >= 10]
|
128 |
+
all_files.sort(key=lambda x: (os.path.splitext(x)[1], x), reverse=True)
|
129 |
+
|
130 |
+
if st.sidebar.button("🗑 Delete All"):
|
131 |
+
for file in all_files:
|
132 |
+
os.remove(file)
|
133 |
+
st.rerun()
|
134 |
+
|
135 |
+
if st.sidebar.button("⬇️ Download All"):
|
136 |
+
zip_file = create_zip_of_files(all_files)
|
137 |
+
st.sidebar.markdown(get_zip_download_link(zip_file), unsafe_allow_html=True)
|
138 |
+
|
139 |
+
for file in all_files:
|
140 |
+
col1, col2, col3, col4 = st.sidebar.columns([1,3,1,1])
|
141 |
+
with col1:
|
142 |
+
if st.button("🌐", key="view_"+file):
|
143 |
+
st.session_state.current_file = file
|
144 |
+
st.session_state.file_content = load_file(file)
|
145 |
+
with col2:
|
146 |
+
st.markdown(get_download_link(file), unsafe_allow_html=True)
|
147 |
+
with col3:
|
148 |
+
if st.button("📂", key="edit_"+file):
|
149 |
+
st.session_state.current_file = file
|
150 |
+
st.session_state.file_content = load_file(file)
|
151 |
+
with col4:
|
152 |
+
if st.button("🗑", key="delete_"+file):
|
153 |
+
os.remove(file)
|
154 |
+
st.rerun()
|
155 |
+
|
156 |
+
# Main content area
|
157 |
+
user_input = st.text_area("Enter your message:", height=100)
|
158 |
+
|
159 |
+
if st.button("Send"):
|
160 |
+
if user_input:
|
161 |
+
response = client.messages.create(
|
162 |
+
model="claude-3-sonnet-20240229",
|
163 |
+
max_tokens=1000,
|
164 |
+
messages=[
|
165 |
+
{"role": "user", "content": user_input}
|
166 |
+
]
|
167 |
)
|
168 |
+
|
169 |
+
st.write("Claude's response:")
|
170 |
+
st.write(response.content[0].text)
|
171 |
+
|
172 |
+
# Save response to file
|
173 |
+
filename = generate_filename(user_input, "md")
|
174 |
+
create_file(filename, user_input, response.content[0].text)
|
175 |
+
|
176 |
+
# Add to chat history
|
177 |
+
st.session_state.chat_history.append({"user": user_input, "claude": response.content[0].text})
|
178 |
+
|
179 |
+
# Display chat history
|
180 |
+
st.subheader("Chat History")
|
181 |
+
for chat in st.session_state.chat_history:
|
182 |
+
st.text_area("You:", chat["user"], height=100, disabled=True)
|
183 |
+
st.text_area("Claude:", chat["claude"], height=200, disabled=True)
|
184 |
+
st.markdown("---")
|
185 |
+
|
186 |
+
# File content viewer/editor
|
187 |
+
if hasattr(st.session_state, 'current_file'):
|
188 |
+
st.subheader(f"Editing: {st.session_state.current_file}")
|
189 |
+
new_content = st.text_area("File Content:", st.session_state.file_content, height=300)
|
190 |
+
if st.button("Save Changes"):
|
191 |
+
with open(st.session_state.current_file, 'w', encoding='utf-8') as file:
|
192 |
+
file.write(new_content)
|
193 |
+
st.success("File updated successfully!")
|
194 |
+
|
195 |
+
# Image Gallery
|
196 |
+
st.subheader("Image Gallery")
|
197 |
+
image_files = glob.glob("*.png") + glob.glob("*.jpg") + glob.glob("*.jpeg")
|
198 |
+
image_cols = st.slider("Image Gallery Columns", min_value=1, max_value=5, value=3)
|
199 |
+
cols = st.columns(image_cols)
|
200 |
+
for idx, image_file in enumerate(image_files):
|
201 |
+
with cols[idx % image_cols]:
|
202 |
+
img = Image.open(image_file)
|
203 |
+
st.image(img, caption=image_file, use_column_width=True)
|
204 |
+
display_glossary_entity(os.path.splitext(image_file)[0])
|
205 |
+
|
206 |
+
# Video Gallery
|
207 |
+
st.subheader("Video Gallery")
|
208 |
+
video_files = glob.glob("*.mp4")
|
209 |
+
video_cols = st.slider("Video Gallery Columns", min_value=1, max_value=5, value=3)
|
210 |
+
cols = st.columns(video_cols)
|
211 |
+
for idx, video_file in enumerate(video_files):
|
212 |
+
with cols[idx % video_cols]:
|
213 |
+
st.markdown(get_video_html(video_file, width="100%"), unsafe_allow_html=True)
|
214 |
+
display_glossary_entity(os.path.splitext(video_file)[0])
|
215 |
+
|
216 |
+
# Audio Gallery
|
217 |
+
st.subheader("Audio Gallery")
|
218 |
+
audio_files = glob.glob("*.mp3") + glob.glob("*.wav")
|
219 |
+
audio_cols = st.slider("Audio Gallery Columns", min_value=1, max_value=5, value=3)
|
220 |
+
cols = st.columns(audio_cols)
|
221 |
+
for idx, audio_file in enumerate(audio_files):
|
222 |
+
with cols[idx % audio_cols]:
|
223 |
+
st.markdown(get_audio_html(audio_file, width="100%"), unsafe_allow_html=True)
|
224 |
+
display_glossary_entity(os.path.splitext(audio_file)[0])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
225 |
|
226 |
if __name__ == "__main__":
|
227 |
+
main()
|