Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,78 +1,915 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
import shutil
|
| 4 |
-
import hashlib
|
| 5 |
-
import subprocess
|
| 6 |
-
import pandas as pd
|
| 7 |
from PIL import Image
|
| 8 |
from datetime import datetime
|
| 9 |
-
import io
|
| 10 |
import base64
|
| 11 |
import requests
|
|
|
|
| 12 |
import json
|
| 13 |
import logging
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
|
| 15 |
-
#
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
THUMBS_DOWN_FOLDER = os.path.join(IMAGE_FOLDER, "Thumbs_Down")
|
| 20 |
-
BACKUP_FOLDER = "Backup_Scripts"
|
| 21 |
-
ALLOWED_EXTENSIONS = ['.jpg', '.jpeg', '.png', '.gif', '.bmp']
|
| 22 |
-
LOGGING_LEVEL = logging.INFO
|
| 23 |
-
API_URL = "https://api.openai.com/v1/chat/completions"
|
| 24 |
|
| 25 |
-
#
|
| 26 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
os.makedirs(THUMBS_UP_FOLDER, exist_ok=True)
|
| 31 |
-
os.makedirs(THUMBS_DOWN_FOLDER, exist_ok=True)
|
| 32 |
-
os.makedirs(BACKUP_FOLDER, exist_ok=True)
|
| 33 |
|
| 34 |
-
|
| 35 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
|
| 37 |
def get_image_description(image, custom_prompt):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 38 |
if not custom_prompt.strip():
|
| 39 |
custom_prompt = "Describe this image"
|
| 40 |
-
|
| 41 |
-
payload =
|
| 42 |
"model": "gpt-4-vision-preview",
|
| 43 |
-
"messages": [
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
|
|
|
|
|
|
|
|
|
| 49 |
"max_tokens": 300
|
| 50 |
-
}
|
| 51 |
-
response = requests.post(
|
| 52 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 53 |
|
| 54 |
-
def
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 58 |
|
| 59 |
-
def
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 60 |
text_file_path = f"{os.path.splitext(image_path)[0]}.txt"
|
| 61 |
-
|
| 62 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 63 |
|
| 64 |
with gr.Blocks() as app:
|
| 65 |
with gr.Row():
|
| 66 |
upload_btn = gr.File(label="Upload Images", type="binary", file_count='multiple')
|
| 67 |
gallery = gr.Gallery(label="Uploaded Images Gallery")
|
| 68 |
-
upload_btn.change(fn=
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 69 |
|
| 70 |
-
with gr.Accordion("Training Data"):
|
| 71 |
-
details_df = gr.Dataframe()
|
| 72 |
-
thumbs_up_gallery = gr.Gallery(value=load_gallery(THUMBS_UP_FOLDER), label="Thumbs Up Gallery")
|
| 73 |
-
thumbs_down_gallery = gr.Gallery(value=load_gallery(THUMBS_DOWN_FOLDER), label="Thumbs Down Gallery")
|
| 74 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 75 |
refresh_btn = gr.Button("Refresh")
|
| 76 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 77 |
|
| 78 |
-
|
|
|
|
| 1 |
+
project_index = 0 # Initialize project_index with a default value
|
| 2 |
+
|
| 3 |
+
import gradio as gr,os,shutil,numpy as np,hashlib,subprocess,pandas as pd
|
|
|
|
|
|
|
|
|
|
| 4 |
from PIL import Image
|
| 5 |
from datetime import datetime
|
|
|
|
| 6 |
import base64
|
| 7 |
import requests
|
| 8 |
+
import io
|
| 9 |
import json
|
| 10 |
import logging
|
| 11 |
+
import re
|
| 12 |
+
|
| 13 |
+
"""
|
| 14 |
+
Gradio App Interface Specification:
|
| 15 |
+
Inputs:
|
| 16 |
+
- prompt: Text Input. Description: 'Enter a prompt for image generation.'
|
| 17 |
+
- steps: Slider. Range: [1, 32]. value: 16. Description: 'Number of steps for image generation.'
|
| 18 |
+
- model: Dropdown. Options: ['TurboAnime.saftensors', 'OtherModel']. value: 'TurboAnime.saftensors'. Description: 'Select the model for image generation.'
|
| 19 |
+
- styles: CheckboxGroup. Options: ['RayORender', 'OtherStyle']. value: ['RayORender']. Description: 'Select styles for image generation.'
|
| 20 |
+
|
| 21 |
+
Outputs:
|
| 22 |
+
- image: Image. Description: 'Generated image based on the prompt.'
|
| 23 |
+
- log: Text. Description: 'Log of the image generation process.'
|
| 24 |
+
"""
|
| 25 |
+
|
| 26 |
+
import gradio as gr
|
| 27 |
+
import subprocess
|
| 28 |
+
import json
|
| 29 |
+
import base64
|
| 30 |
+
from PIL import Image
|
| 31 |
+
import io
|
| 32 |
+
import time
|
| 33 |
+
|
| 34 |
+
# π Start time for the entire script
|
| 35 |
+
start_time = time.time()
|
| 36 |
+
def analyze_all_images(custom_prompt):
|
| 37 |
+
global file_array
|
| 38 |
+
descriptions = []
|
| 39 |
+
for file_info in file_array:
|
| 40 |
+
file_path = find_file_by_hash(file_info["hash"])
|
| 41 |
+
if file_path:
|
| 42 |
+
with Image.open(file_path) as img:
|
| 43 |
+
description = get_image_description(img, custom_prompt)
|
| 44 |
+
save_text(file_info["hash"], description, "", "", True) # Save the description to the text file
|
| 45 |
+
descriptions.append(description)
|
| 46 |
+
return descriptions
|
| 47 |
+
|
| 48 |
+
def generate_status_message(index, total, file_name):
|
| 49 |
+
return f"Processing {index + 1}/{total}: {file_name}"
|
| 50 |
+
|
| 51 |
+
def analyze_thumbs_up_images(custom_prompt):
|
| 52 |
+
thumbs_up_images = load_thumbs_up_gallery() # Assuming this function returns full paths
|
| 53 |
+
total_images = len(thumbs_up_images)
|
| 54 |
+
descriptions = []
|
| 55 |
+
status_messages = []
|
| 56 |
+
for index, image_path in enumerate(thumbs_up_images):
|
| 57 |
+
with Image.open(image_path) as img:
|
| 58 |
+
description = get_image_description(img, custom_prompt)
|
| 59 |
+
descriptions.append((os.path.basename(image_path), description))
|
| 60 |
+
status_messages.append(generate_status_message(index, total_images, os.path.basename(image_path)))
|
| 61 |
+
save_text(file_info["hash"], description, "", "", True) # Save the description to the text file
|
| 62 |
+
return descriptions, status_messages
|
| 63 |
+
|
| 64 |
+
# π’ Log Status
|
| 65 |
+
def log_status(progress, message):
|
| 66 |
+
elapsed_time = time.time() - start_time
|
| 67 |
+
log_message = {"status": message, "progress": f"{progress}%", "time_elapsed": f"{elapsed_time:.2f} seconds"}
|
| 68 |
+
return json.dumps(log_message)
|
| 69 |
+
def process_files(file_info):
|
| 70 |
+
try:
|
| 71 |
+
if file_info:
|
| 72 |
+
return [_process_file(file_path) for file_path in file_info] if isinstance(file_info, list) else [_process_file(file_info)]
|
| 73 |
+
return []
|
| 74 |
+
except Exception as e:
|
| 75 |
+
print(f"Error processing files: {e}")
|
| 76 |
+
raise e
|
| 77 |
+
|
| 78 |
+
def clear_uploads_folder():
|
| 79 |
+
os.makedirs(recycle_bin_folder, exist_ok=True)
|
| 80 |
+
for file_name in os.listdir(_get_project_folder()):
|
| 81 |
+
dest_file_path = os.path.join(recycle_bin_folder, file_name)
|
| 82 |
+
if os.path.exists(dest_file_path):
|
| 83 |
+
base, extension = os.path.splitext(file_name)
|
| 84 |
+
i = 1
|
| 85 |
+
new_file_name = f"{base}_{i}{extension}"
|
| 86 |
+
new_dest_file_path = os.path.join(recycle_bin_folder, new_file_name)
|
| 87 |
+
while os.path.exists(new_dest_file_path):
|
| 88 |
+
i += 1
|
| 89 |
+
new_file_name = f"{base}_{i}{extension}"
|
| 90 |
+
new_dest_file_path = os.path.join(recycle_bin_folder, new_file_name)
|
| 91 |
+
dest_file_path = new_dest_file_path
|
| 92 |
+
shutil.move(os.path.join(_get_project_folder(), file_name), dest_file_path)
|
| 93 |
+
return "Uploads folder cleared!"
|
| 94 |
+
|
| 95 |
+
def undo_last_deletion():
|
| 96 |
+
file_list = os.listdir(recycle_bin_folder)
|
| 97 |
+
if file_list:
|
| 98 |
+
last_deleted_file = file_list[-1]
|
| 99 |
+
shutil.move(os.path.join(recycle_bin_folder, last_deleted_file), _get_project_folder())
|
| 100 |
+
return f"Restored: {last_deleted_file}"
|
| 101 |
+
return "No files to restore"
|
| 102 |
+
|
| 103 |
+
def next_session():
|
| 104 |
+
global project_index
|
| 105 |
+
project_index += 1
|
| 106 |
+
_init_project_directory()
|
| 107 |
+
return f"Switched to the next session! Current session index: {project_index}"
|
| 108 |
+
|
| 109 |
+
def previous_session():
|
| 110 |
+
global project_index
|
| 111 |
+
if project_index > 0: project_index -= 1
|
| 112 |
+
return f"Switched to the previous session! Current session index: {project_index}"
|
| 113 |
+
|
| 114 |
+
def get_next_image():
|
| 115 |
+
global current_image
|
| 116 |
+
images = get_images()
|
| 117 |
+
if images:
|
| 118 |
+
current_image = images[0] if current_image is None else images[(images.index(current_image) + 1) % len(images)]
|
| 119 |
+
else:
|
| 120 |
+
current_image = default_image
|
| 121 |
+
return current_image
|
| 122 |
+
|
| 123 |
+
def get_previous_image():
|
| 124 |
+
global current_image
|
| 125 |
+
images = get_images()
|
| 126 |
+
if images:
|
| 127 |
+
current_image = images[-1] if current_image is None else images[(images.index(current_image) - 1) % len(images)]
|
| 128 |
+
else:
|
| 129 |
+
current_image = default_image
|
| 130 |
+
return current_image
|
| 131 |
+
|
| 132 |
+
def process_all_zips():
|
| 133 |
+
for file_name in os.listdir(_get_project_folder()):
|
| 134 |
+
file_path = os.path.join(_get_project_folder(), file_name)
|
| 135 |
+
if zipfile.is_zipfile(file_path): _process_file(file_path)
|
| 136 |
+
return "All zip files processed!"
|
| 137 |
+
|
| 138 |
+
# π API Call
|
| 139 |
+
def make_api_call(url, payload):
|
| 140 |
+
try:
|
| 141 |
+
response = subprocess.run(["curl", "-X", "POST", url, "-H", "Content-Type: application/json", "--data", json.dumps(payload)], capture_output=True, text=True)
|
| 142 |
+
if response.returncode == 0:
|
| 143 |
+
return json.loads(response.stdout), None
|
| 144 |
+
else:
|
| 145 |
+
return None, log_status(progress, f"API call failed with return code: {response.returncode}")
|
| 146 |
+
except Exception as e:
|
| 147 |
+
return None, log_status(progress, f"API call failed with exception: {str(e)}")
|
| 148 |
|
| 149 |
+
# πΌοΈ Save Image
|
| 150 |
+
def save_image(image_data):
|
| 151 |
+
image = Image.open(io.BytesIO(base64.b64decode(image_data)))
|
| 152 |
+
return image
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 153 |
|
| 154 |
+
# π Main Execution Function
|
| 155 |
+
def generate_image(prompt, steps, model, styles):
|
| 156 |
+
base_url = "http://73.255.78.150:7909"
|
| 157 |
+
base_payload = {
|
| 158 |
+
"prompt": prompt,
|
| 159 |
+
"steps": steps,
|
| 160 |
+
"model": model,
|
| 161 |
+
"styles": styles,
|
| 162 |
+
"negative_prompt": "album, duplicate, crowded, multiple, stuff, messy, photo, collage, doll, caricature, render. mannequin.",
|
| 163 |
+
"seed": -1,
|
| 164 |
+
"height": 768,
|
| 165 |
+
"width": 1280,
|
| 166 |
+
"sampler_index": "DPM++ 2M SDE Karras",
|
| 167 |
+
"restore_faces": False,
|
| 168 |
+
"tiling": False,
|
| 169 |
+
"n_iter": 1,
|
| 170 |
+
"batch_size": 1,
|
| 171 |
+
"cfg_scale": 2.0,
|
| 172 |
+
"subseed": -1,
|
| 173 |
+
"subseed_strength": 0.0,
|
| 174 |
+
"seed_resize_from_h": -1,
|
| 175 |
+
"seed_resize_from_w": -1,
|
| 176 |
+
"seed_enable_extras": False,
|
| 177 |
+
"enable_hr": False,
|
| 178 |
+
"denoising_strength": 0.0,
|
| 179 |
+
"hr_scale": 2.0,
|
| 180 |
+
"hr_upscaler": "Latent",
|
| 181 |
+
"hr_second_pass_steps": 0,
|
| 182 |
+
"hr_resize_x": 0,
|
| 183 |
+
"hr_resize_y": 0,
|
| 184 |
+
"hr_sampler_index": "",
|
| 185 |
+
"hr_prompt": "",
|
| 186 |
+
"hr_negative_prompt": "",
|
| 187 |
+
"override_settings_texts": ""
|
| 188 |
+
|
| 189 |
+
}
|
| 190 |
|
| 191 |
+
progress = 0
|
| 192 |
+
log = log_status(progress, "Starting image generation...")
|
|
|
|
|
|
|
|
|
|
| 193 |
|
| 194 |
+
response, error_log = make_api_call(f"{base_url}/sdapi/v1/txt2img", base_payload)
|
| 195 |
+
if error_log:
|
| 196 |
+
return None, error_log
|
| 197 |
+
|
| 198 |
+
if response and 'images' in response:
|
| 199 |
+
image_data = response['images'][0]
|
| 200 |
+
image = save_image(image_data)
|
| 201 |
+
log = log_status(100, "Image generated successfully.")
|
| 202 |
+
return image, log
|
| 203 |
+
else:
|
| 204 |
+
log = log_status(progress, "Failed to generate image.")
|
| 205 |
+
return None, log
|
| 206 |
+
|
| 207 |
+
max_image_size = 768
|
| 208 |
+
image_folder = "/Users/gev7418/Library/CloudStorage/OneDrive-Personal/Gradio Script Building Blocks/HatchDuo-Gradio/Images"
|
| 209 |
+
thumbs_up_folder = os.path.join(image_folder, "Thumbs_Up")
|
| 210 |
+
thumbs_down_folder = os.path.join(image_folder, "Thumbs_Down")
|
| 211 |
+
allowed_extensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp']
|
| 212 |
+
folders_cycle = [image_folder, thumbs_up_folder, thumbs_down_folder]
|
| 213 |
+
# Set up logging to print to the terminal
|
| 214 |
+
logging.basicConfig(level=logging.INFO)
|
| 215 |
+
|
| 216 |
+
# OpenAI API Key
|
| 217 |
+
api_key = "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" # Replace with your OpenAI API Key
|
| 218 |
+
import subprocess
|
| 219 |
+
|
| 220 |
+
def convert_and_rename_files_in_directory(directory, original_extension, new_extension, new_base_name):
|
| 221 |
+
"""
|
| 222 |
+
Converts all files in the specified directory from the original extension to PNG, and renames them to a new base name followed by a number.
|
| 223 |
+
"""
|
| 224 |
+
files = [f for f in os.listdir(directory) if f.endswith(original_extension)]
|
| 225 |
+
for index, file in enumerate(sorted(files)):
|
| 226 |
+
new_name = f"{new_base_name}_{index}{new_extension}"
|
| 227 |
+
original_file_path = os.path.join(directory, file)
|
| 228 |
+
new_file_path = os.path.join(directory, new_name)
|
| 229 |
+
# Convert to PNG using a subprocess call to a command line tool like ImageMagick
|
| 230 |
+
subprocess.run(['convert', original_file_path, new_file_path])
|
| 231 |
+
os.rename(new_file_path, os.path.join(directory, new_name))
|
| 232 |
+
logging.info(f"All {original_extension} files in {directory} have been converted to PNG and renamed to {new_base_name} format.")
|
| 233 |
+
|
| 234 |
+
|
| 235 |
+
def encode_image(image):
|
| 236 |
+
"""
|
| 237 |
+
This function converts the image to bytes and returns the base64 encoding of the image file
|
| 238 |
+
"""
|
| 239 |
+
logging.info("Encoding image to base64")
|
| 240 |
+
image_bytes = io.BytesIO()
|
| 241 |
+
if image.mode == 'RGBA':
|
| 242 |
+
# Convert RGBA to RGB
|
| 243 |
+
image = image.convert('RGB')
|
| 244 |
+
image.save(image_bytes, format='JPEG')
|
| 245 |
+
image_bytes = image_bytes.getvalue()
|
| 246 |
+
base64_image = base64.b64encode(image_bytes).decode('utf-8')
|
| 247 |
+
|
| 248 |
+
return base64_image
|
| 249 |
|
| 250 |
def get_image_description(image, custom_prompt):
|
| 251 |
+
"""
|
| 252 |
+
This function sends the image to the OpenAI API and returns the response.
|
| 253 |
+
It now checks if there's custom prompt content before sending it to the API.
|
| 254 |
+
"""
|
| 255 |
+
logging.info("Getting image description from OpenAI API")
|
| 256 |
+
base64_image = encode_image(image)
|
| 257 |
+
headers = {"Content-Type": "application/json", "Authorization": f"Bearer {api_key}"}
|
| 258 |
+
|
| 259 |
+
# Check if custom_prompt is not empty, otherwise use a default prompt
|
| 260 |
if not custom_prompt.strip():
|
| 261 |
custom_prompt = "Describe this image"
|
| 262 |
+
|
| 263 |
+
payload = {
|
| 264 |
"model": "gpt-4-vision-preview",
|
| 265 |
+
"messages": [
|
| 266 |
+
{
|
| 267 |
+
"role": "user",
|
| 268 |
+
"content": [
|
| 269 |
+
{"type": "text", "text": custom_prompt},
|
| 270 |
+
{"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{base64_image}"}}
|
| 271 |
+
]
|
| 272 |
+
}
|
| 273 |
+
],
|
| 274 |
"max_tokens": 300
|
| 275 |
+
}
|
| 276 |
+
response = requests.post("https://api.openai.com/v1/chat/completions", headers=headers, json=payload)
|
| 277 |
+
response_payload = json.loads(response.text)
|
| 278 |
+
content = response_payload['choices'][0]['message']['content']
|
| 279 |
+
|
| 280 |
+
logging.info("Received response from OpenAI API")
|
| 281 |
+
return content
|
| 282 |
|
| 283 |
+
def create_directories():
|
| 284 |
+
print("Creating directories...")
|
| 285 |
+
os.makedirs(thumbs_up_folder, exist_ok=True)
|
| 286 |
+
os.makedirs(thumbs_down_folder, exist_ok=True)
|
| 287 |
+
|
| 288 |
+
create_directories()
|
| 289 |
+
|
| 290 |
+
def get_files(folder):
|
| 291 |
+
print(f"Getting files from {folder}...")
|
| 292 |
+
return [os.path.join(dp, f) for dp, dn, filenames in os.walk(folder) for f in filenames if os.path.splitext(f)[1].lower() in allowed_extensions]
|
| 293 |
+
|
| 294 |
+
def hash_image_pixels(file_path):
|
| 295 |
+
"""
|
| 296 |
+
Generates a hash for an image based on its pixel content.
|
| 297 |
+
"""
|
| 298 |
+
if os.path.splitext(file_path)[1].lower() in allowed_extensions:
|
| 299 |
+
with Image.open(file_path) as img:
|
| 300 |
+
# Convert the image to RGBA (to standardize if images are in different modes)
|
| 301 |
+
img_rgba = img.convert('RGBA')
|
| 302 |
+
# Calculate the new height and width to maintain aspect ratio
|
| 303 |
+
aspect_ratio = img_rgba.width / img_rgba.height
|
| 304 |
+
new_height = min(max_image_size, img_rgba.height)
|
| 305 |
+
new_width = int(aspect_ratio * new_height)
|
| 306 |
+
if img_rgba.height > max_image_size:
|
| 307 |
+
new_height = max_image_size
|
| 308 |
+
new_width = int(new_height * aspect_ratio)
|
| 309 |
+
# Use Image.Resampling.LANCZOS for better quality resizing
|
| 310 |
+
img_resized = img_rgba.resize((new_width, new_height), Image.Resampling.LANCZOS)
|
| 311 |
+
# Get the bytes of the resized image data
|
| 312 |
+
img_bytes = io.BytesIO()
|
| 313 |
+
img_resized.save(img_bytes, format='PNG') # PNG format to ensure consistency across platforms
|
| 314 |
+
img_bytes = img_bytes.getvalue()
|
| 315 |
+
# Generate a hash of the resized image bytes
|
| 316 |
+
hash_obj = hashlib.sha256(img_bytes)
|
| 317 |
+
return hash_obj.hexdigest()
|
| 318 |
+
else:
|
| 319 |
+
return None
|
| 320 |
+
|
| 321 |
+
# Global cache for hashes to file paths
|
| 322 |
+
hash_to_path_cache = {}
|
| 323 |
+
|
| 324 |
+
def update_hash_to_path_cache():
|
| 325 |
+
global hash_to_path_cache
|
| 326 |
+
hash_to_path_cache.clear()
|
| 327 |
+
for folder in folders_cycle:
|
| 328 |
+
for file_path in get_files(folder):
|
| 329 |
+
file_hash = hash_image_pixels(file_path)
|
| 330 |
+
hash_to_path_cache[file_hash] = file_path
|
| 331 |
+
|
| 332 |
+
def find_file_by_hash(file_hash):
|
| 333 |
+
# Use the cache to find the file path
|
| 334 |
+
file_path = hash_to_path_cache.get(file_hash, None)
|
| 335 |
+
if file_path and os.path.exists(file_path):
|
| 336 |
+
return file_path
|
| 337 |
+
# If the file was not found or doesn't exist at the cached location,
|
| 338 |
+
# search in the thumbs up and thumbs down folders
|
| 339 |
+
for folder in [thumbs_up_folder, thumbs_down_folder]:
|
| 340 |
+
for dp, dn, filenames in os.walk(folder):
|
| 341 |
+
for f in filenames:
|
| 342 |
+
potential_path = os.path.join(dp, f)
|
| 343 |
+
if os.path.splitext(f)[1].lower() in allowed_extensions:
|
| 344 |
+
if hash_image_pixels(potential_path) == file_hash:
|
| 345 |
+
# Update the cache with the new location
|
| 346 |
+
hash_to_path_cache[file_hash] = potential_path
|
| 347 |
+
return potential_path
|
| 348 |
+
# If the file is not found in any of the locations, return None
|
| 349 |
+
return None
|
| 350 |
+
|
| 351 |
+
def build_file_array():
|
| 352 |
+
print("Building file array...")
|
| 353 |
+
files = []
|
| 354 |
+
for folder in folders_cycle:
|
| 355 |
+
for file_path in get_files(folder):
|
| 356 |
+
file_hash = hash_image_pixels(file_path)
|
| 357 |
+
status = "π Rated Up" if folder == thumbs_up_folder else "π Rated Down" if folder == thumbs_down_folder else "β³ Pending"
|
| 358 |
+
files.append({"path": file_path, "hash": file_hash, "status": status, "date_modified": os.path.getmtime(file_path)})
|
| 359 |
+
|
| 360 |
+
# Create text files for any images missing their text file counterpart
|
| 361 |
+
text_file_path = file_path.replace(os.path.splitext(file_path)[1], '.txt')
|
| 362 |
+
if not os.path.exists(text_file_path):
|
| 363 |
+
with open(text_file_path, 'w') as text_file:
|
| 364 |
+
text_file.write("") # Create an empty text file
|
| 365 |
+
|
| 366 |
+
files = sorted(files, key=lambda x: x["date_modified"], reverse=True)
|
| 367 |
+
return files
|
| 368 |
+
|
| 369 |
+
def refresh_file_array_and_hashes():
|
| 370 |
+
global file_array, hash_list
|
| 371 |
+
file_array = build_file_array()
|
| 372 |
+
hash_list = [file['hash'] for file in file_array]
|
| 373 |
+
print("File array and hash list updated.")
|
| 374 |
+
|
| 375 |
+
update_hash_to_path_cache()
|
| 376 |
+
refresh_file_array_and_hashes()
|
| 377 |
+
current_index = 0
|
| 378 |
+
def save_text(file_hash, text, prepend_text="", append_text="", save_and_overwrite_changes=True):
|
| 379 |
+
if not save_and_overwrite_changes:
|
| 380 |
+
print("Skipping saving due to user preference.")
|
| 381 |
+
return
|
| 382 |
+
file_path = find_file_by_hash(file_hash)
|
| 383 |
+
if file_path:
|
| 384 |
+
text_file_path = file_path.replace(os.path.splitext(file_path)[1], '.txt')
|
| 385 |
+
final_text = ""
|
| 386 |
+
if not save_and_overwrite_changes and os.path.exists(text_file_path):
|
| 387 |
+
with open(text_file_path, 'r') as existing_file:
|
| 388 |
+
existing_content = existing_file.read()
|
| 389 |
+
final_text = (prepend_text + ", " if prepend_text else "") + existing_content + (", " + append_text if append_text else "")
|
| 390 |
+
else:
|
| 391 |
+
final_text = (prepend_text + ", " if prepend_text else "") + text + (", " + append_text if append_text else "")
|
| 392 |
+
print(f"Saving text for file hash {file_hash} to {text_file_path}...")
|
| 393 |
+
with open(text_file_path, 'w') as text_file:
|
| 394 |
+
text_file.write(final_text)
|
| 395 |
+
|
| 396 |
+
def get_text(file_hash):
|
| 397 |
+
file_path = find_file_by_hash(file_hash)
|
| 398 |
+
if file_path:
|
| 399 |
+
text_file_path = file_path.replace(os.path.splitext(file_path)[1], '.txt')
|
| 400 |
+
if os.path.exists(text_file_path):
|
| 401 |
+
print(f"Getting text for file hash {file_hash} from {text_file_path}...")
|
| 402 |
+
with open(text_file_path) as text_file:
|
| 403 |
+
return text_file.read()
|
| 404 |
+
return ""
|
| 405 |
+
|
| 406 |
+
def update_index_for_navigation(current_text, prepend_text, append_text, navigate_forward=True, save_and_overwrite_changes=False):
|
| 407 |
+
global current_index, file_array, hash_list
|
| 408 |
+
if current_text or not save_and_overwrite_changes: # Save only if there's something to save or if saving changes is not required
|
| 409 |
+
file_hash = hash_list[current_index]
|
| 410 |
+
save_text(file_hash, current_text, prepend_text, append_text, save_and_overwrite_changes)
|
| 411 |
+
if navigate_forward:
|
| 412 |
+
current_index = (current_index + 1) % len(hash_list) # Cycle to the first item if at the end
|
| 413 |
+
else:
|
| 414 |
+
current_index = (current_index - 1) % len(hash_list) # Cycle to the last item if at the beginning
|
| 415 |
+
def get_file(navigate_forward, current_text, prepend_text, append_text, pause_api_call, save_and_overwrite_changes, custom_prompt):
|
| 416 |
+
global current_index, file_array, hash_list
|
| 417 |
+
print(f"Getting file, navigate_forward: {navigate_forward}...")
|
| 418 |
+
update_index_for_navigation(current_text, prepend_text, append_text, navigate_forward, save_and_overwrite_changes)
|
| 419 |
+
if current_index < len(hash_list):
|
| 420 |
+
current_hash = hash_list[current_index]
|
| 421 |
+
file_info = next((item for item in file_array if item["hash"] == current_hash), None)
|
| 422 |
+
if file_info:
|
| 423 |
+
file_path = find_file_by_hash(current_hash)
|
| 424 |
+
if file_path:
|
| 425 |
+
with Image.open(file_path) as img:
|
| 426 |
+
# Calculate the new height and width to maintain aspect ratio, with a max height of 768 for display in gradio
|
| 427 |
+
aspect_ratio = img.width / img.height
|
| 428 |
+
new_height = min(768, img.height) # Set max height to 768 for gradio display
|
| 429 |
+
new_width = int(aspect_ratio * new_height)
|
| 430 |
+
# Use Image.Resampling.LANCZOS for better quality resizing
|
| 431 |
+
img_resized = img.resize((new_width, new_height), Image.Resampling.LANCZOS)
|
| 432 |
+
img_resized_bytes = io.BytesIO()
|
| 433 |
+
img_resized.save(img_resized_bytes, format='PNG')
|
| 434 |
+
img_resized_bytes = img_resized_bytes.getvalue()
|
| 435 |
+
text = get_text(current_hash) # Load text file contents into textbox
|
| 436 |
+
if not pause_api_call:
|
| 437 |
+
text = get_image_description(img, custom_prompt) # Get new description from OpenAI
|
| 438 |
+
save_text(current_hash, text, prepend_text, append_text, save_and_overwrite_changes) # Optionally save the new description
|
| 439 |
+
# Convert the resized image to a numpy array for display
|
| 440 |
+
img_resized_np = np.array(Image.open(io.BytesIO(img_resized_bytes)))
|
| 441 |
+
return img_resized_np, current_hash, file_info["status"], text, os.path.basename(file_path), file_path, os.path.relpath(file_path, start=image_folder), os.path.basename(file_path).replace(os.path.splitext(os.path.basename(file_path))[1], '.txt'), find_file_by_hash(current_hash).replace(os.path.splitext(find_file_by_hash(current_hash))[1], '.txt'), os.path.relpath(find_file_by_hash(current_hash).replace(os.path.splitext(find_file_by_hash(current_hash))[1], '.txt'), start=image_folder)
|
| 442 |
+
return None, "File not found", "β³ Pending", "", "", "", "", "", "", ""
|
| 443 |
+
def move_file(direction, current_text, prepend_text, append_text, pause_api_call, save_and_overwrite_changes, custom_prompt):
|
| 444 |
+
global current_index, file_array, hash_list
|
| 445 |
+
print(f"Moving file in direction {direction}...")
|
| 446 |
+
if current_index < len(hash_list):
|
| 447 |
+
current_hash = hash_list[current_index]
|
| 448 |
+
file_info = next((item for item in file_array if item["hash"] == current_hash), None)
|
| 449 |
+
if file_info:
|
| 450 |
+
source_file = find_file_by_hash(current_hash)
|
| 451 |
+
if source_file:
|
| 452 |
+
destination = thumbs_up_folder if direction == "up" else thumbs_down_folder if direction == "down" else None
|
| 453 |
+
new_status = "π Rated Up" if direction == "up" else "π Rated Down" if direction == "down" else None
|
| 454 |
+
if destination:
|
| 455 |
+
shutil.move(source_file, os.path.join(destination, os.path.basename(source_file)))
|
| 456 |
+
file_info["status"] = new_status
|
| 457 |
+
# Get new description and save it
|
| 458 |
+
with Image.open(source_file) as img:
|
| 459 |
+
description = get_image_description(img, custom_prompt)
|
| 460 |
+
save_text(current_hash, description, prepend_text, append_text, save_and_overwrite_changes)
|
| 461 |
+
return get_file(True, current_text, prepend_text, append_text, pause_api_call, save_and_overwrite_changes, custom_prompt)
|
| 462 |
+
return None, "Invalid direction or file not found", "β³ Pending", "", "", "", "", "", "", ""
|
| 463 |
+
|
| 464 |
+
def reset_files(current_text, prepend_text, append_text, pause_api_call, save_and_overwrite_changes, custom_prompt):
|
| 465 |
+
global file_array, current_index, hash_list
|
| 466 |
+
print("Resetting files and clearing text...")
|
| 467 |
+
for file_info in file_array:
|
| 468 |
+
source_file = find_file_by_hash(file_info["hash"])
|
| 469 |
+
if source_file and os.path.exists(source_file):
|
| 470 |
+
source_text = source_file.replace(os.path.splitext(source_file)[1], '.txt')
|
| 471 |
+
if os.path.exists(source_text):
|
| 472 |
+
shutil.move(source_text, os.path.join(image_folder, os.path.basename(source_text)))
|
| 473 |
+
shutil.move(source_file, os.path.join(image_folder, os.path.basename(source_file)))
|
| 474 |
+
with open(os.path.join(image_folder, os.path.basename(source_text)), 'w') as text_file:
|
| 475 |
+
text_file.write("")
|
| 476 |
+
file_info["status"] = "β³ Pending"
|
| 477 |
+
file_array = build_file_array()
|
| 478 |
+
hash_list = [file['hash'] for file in file_array]
|
| 479 |
+
update_hash_to_path_cache()
|
| 480 |
+
return get_file(True, current_text, prepend_text, append_text, pause_api_call, save_and_overwrite_changes, custom_prompt)
|
| 481 |
+
|
| 482 |
+
def delete_file(current_text, prepend_text, append_text, pause_api_call, save_and_overwrite_changes, custom_prompt):
|
| 483 |
+
global current_index, file_array, hash_list
|
| 484 |
+
print("Deleting file...")
|
| 485 |
+
if current_index < len(hash_list):
|
| 486 |
+
current_hash = hash_list[current_index]
|
| 487 |
+
source_file = find_file_by_hash(current_hash)
|
| 488 |
+
if source_file:
|
| 489 |
+
source_text = source_file.replace(os.path.splitext(source_file)[1], '.txt')
|
| 490 |
+
os.remove(source_file)
|
| 491 |
+
os.remove(source_text)
|
| 492 |
+
hash_list.remove(current_hash) # Remove the hash from the hash_list
|
| 493 |
+
file_array = [file for file in file_array if file["hash"] != current_hash] # Rebuild file_array without the deleted file
|
| 494 |
+
if current_index >= len(hash_list): current_index = len(hash_list) - 1
|
| 495 |
+
update_hash_to_path_cache()
|
| 496 |
+
return get_file(True, current_text, prepend_text, append_text, pause_api_call, save_and_overwrite_changes, custom_prompt)
|
| 497 |
+
|
| 498 |
+
def load_image_details():
|
| 499 |
+
print("Loading image details...")
|
| 500 |
+
image_details = []
|
| 501 |
+
for folder in folders_cycle:
|
| 502 |
+
for file_path in get_files(folder):
|
| 503 |
+
file_hash = hash_image_pixels(file_path)
|
| 504 |
+
status = "π Rated Up" if folder == thumbs_up_folder else "π Rated Down" if folder == thumbs_down_folder else "β³ Pending"
|
| 505 |
+
text_file_path = file_path.replace(os.path.splitext(file_path)[1], '.txt')
|
| 506 |
+
text_content = ""
|
| 507 |
+
if os.path.exists(text_file_path):
|
| 508 |
+
with open(text_file_path, 'r') as text_file:
|
| 509 |
+
text_content = text_file.read()
|
| 510 |
+
image_details.append({
|
| 511 |
+
"Text Content": text_content,
|
| 512 |
+
"Rating Status": status,
|
| 513 |
+
"File Hash": file_hash,
|
| 514 |
+
"Image Path": file_path,
|
| 515 |
+
"Text Path": text_file_path if os.path.exists(text_file_path) else "N/A"
|
| 516 |
+
})
|
| 517 |
+
return pd.DataFrame(image_details)
|
| 518 |
+
|
| 519 |
+
def load_text_files_as_df():
|
| 520 |
+
print("Loading text files into dataframe...")
|
| 521 |
+
text_files = []
|
| 522 |
+
for file in os.listdir(image_folder):
|
| 523 |
+
if file.endswith('.txt'):
|
| 524 |
+
file_path = os.path.join(image_folder, file)
|
| 525 |
+
with open(file_path, 'r') as text_file:
|
| 526 |
+
text_content = text_file.read()
|
| 527 |
+
text_files.append({
|
| 528 |
+
"File Name": file.replace('.txt', ''),
|
| 529 |
+
"Content": text_content,
|
| 530 |
+
"Date Modified": datetime.fromtimestamp(os.path.getmtime(file_path)).strftime('%Y-%m-%d %H:%M:%S')
|
| 531 |
+
})
|
| 532 |
+
return pd.DataFrame(text_files)
|
| 533 |
+
|
| 534 |
+
# Function to merge text_files_df and image_details_df into a single dataframe
|
| 535 |
+
def load_combined_details():
|
| 536 |
+
print("Loading text file details...")
|
| 537 |
+
text_df = load_text_files_as_df()
|
| 538 |
+
image_details_df = load_image_details()
|
| 539 |
+
# Ensure the 'File Name' column exists in image_details_df by extracting it from 'Image Path'
|
| 540 |
+
image_details_df['File Name'] = image_details_df['Image Path'].apply(lambda x: os.path.basename(x).replace(os.path.splitext(os.path.basename(x))[1], ''))
|
| 541 |
+
combined_df = pd.merge(text_df, image_details_df, on="File Name", how="outer")
|
| 542 |
+
# Reorder dataframe fields according to specified order: Date Modified, Rating Status, File Name, Text Content, File Hash, Text Path, Image Path
|
| 543 |
+
combined_df = combined_df[['Date Modified', 'Rating Status', 'File Name', 'Text Content', 'File Hash', 'Text Path', 'Image Path']]
|
| 544 |
+
return combined_df
|
| 545 |
+
|
| 546 |
+
def load_gallery():
|
| 547 |
+
print("Loading gallery...")
|
| 548 |
+
return sorted([os.path.join(image_folder, f) for f in os.listdir(image_folder) if os.path.splitext(f)[1].lower() in allowed_extensions], key=lambda x: os.path.basename(x).lower())
|
| 549 |
+
|
| 550 |
+
def load_thumbs_up_gallery():
|
| 551 |
+
print("Loading Thumbs Up gallery...")
|
| 552 |
+
return sorted([os.path.join(thumbs_up_folder, f) for f in os.listdir(thumbs_up_folder) if os.path.splitext(f)[1].lower() in allowed_extensions], key=lambda x: os.path.basename(x).lower())
|
| 553 |
|
| 554 |
+
def load_thumbs_down_gallery():
|
| 555 |
+
print("Loading Thumbs Down gallery...")
|
| 556 |
+
return sorted([os.path.join(thumbs_down_folder, f) for f in os.listdir(thumbs_down_folder) if os.path.splitext(f)[1].lower() in allowed_extensions], key=lambda x: os.path.basename(x).lower())
|
| 557 |
+
|
| 558 |
+
def load_all_folders_gallery():
|
| 559 |
+
print("Loading all folders gallery...")
|
| 560 |
+
all_images = []
|
| 561 |
+
for folder in folders_cycle:
|
| 562 |
+
all_images.extend(sorted([os.path.join(folder, f) for f in os.listdir(folder) if os.path.splitext(f)[1].lower() in allowed_extensions], key=lambda x: os.path.basename(x).lower()))
|
| 563 |
+
return all_images
|
| 564 |
+
|
| 565 |
+
def load_text_files():
|
| 566 |
+
print("Loading text files...")
|
| 567 |
+
return sorted([[file, open(os.path.join(image_folder, file),'r').read()] for file in os.listdir(image_folder) if file.endswith('.txt')], key=lambda x: x[0].lower())
|
| 568 |
+
|
| 569 |
+
def update_text_content(df):
|
| 570 |
+
global text_files_df
|
| 571 |
+
print("Updating text content...")
|
| 572 |
+
for row in df:
|
| 573 |
+
if len(row) == 3:
|
| 574 |
+
file_name, new_content, date_added = row
|
| 575 |
+
file_path = os.path.join(image_folder, file_name)
|
| 576 |
+
if os.path.exists(file_path):
|
| 577 |
+
file_hash = hash_file(file_path)
|
| 578 |
+
save_text(file_hash, new_content)
|
| 579 |
+
else:
|
| 580 |
+
print("Error: Unexpected number of values in row. Expected 3 values per row.")
|
| 581 |
+
|
| 582 |
+
# Step 1: Define a function to update the dataframe
|
| 583 |
+
def refresh_text_files():
|
| 584 |
+
print("Refreshing text files...")
|
| 585 |
+
updated_text_files = sorted([[file, open(os.path.join(image_folder, file),'r').read()] for file in os.listdir(image_folder) if file.endswith('.txt')], key=lambda x: x[0].lower())
|
| 586 |
+
return updated_text_files
|
| 587 |
+
def save_uploaded_image(image_file):
|
| 588 |
+
"""
|
| 589 |
+
Attempts to save the uploaded image to the designated image folder. Returns the path of the saved image or None if an error occurs.
|
| 590 |
+
"""
|
| 591 |
+
try:
|
| 592 |
+
os.makedirs(image_folder, exist_ok=True) # Ensure the image folder exists
|
| 593 |
+
image_path = os.path.join(image_folder, image_file.name)
|
| 594 |
+
with open(image_path, "wb") as file:
|
| 595 |
+
file.write(image_file.content) # Write the byte content of the file
|
| 596 |
+
print(f"Image saved successfully: {image_path}")
|
| 597 |
+
return image_path
|
| 598 |
+
except Exception as e:
|
| 599 |
+
print(f"Error saving image: {e}")
|
| 600 |
+
return None
|
| 601 |
+
|
| 602 |
+
def create_text_file_for_image(image_path):
|
| 603 |
+
"""
|
| 604 |
+
Generates an empty text file corresponding to an uploaded image, using the same base name.
|
| 605 |
+
"""
|
| 606 |
text_file_path = f"{os.path.splitext(image_path)[0]}.txt"
|
| 607 |
+
open(text_file_path, 'w').close() # Efficiently create an empty text file
|
| 608 |
+
return text_file_path
|
| 609 |
+
|
| 610 |
+
def handle_image_upload(uploaded_files):
|
| 611 |
+
status_messages = []
|
| 612 |
+
for uploaded_file in uploaded_files:
|
| 613 |
+
file_extension = os.path.splitext(uploaded_file.name)[1].lower()
|
| 614 |
+
if file_extension in allowed_extensions:
|
| 615 |
+
# Ensure the image folder exists
|
| 616 |
+
os.makedirs(image_folder, exist_ok=True)
|
| 617 |
+
# Save the file with a unique name based on its hash
|
| 618 |
+
unique_name = hashlib.sha256(uploaded_file.name.encode()).hexdigest() + file_extension
|
| 619 |
+
save_path = os.path.join(image_folder, unique_name)
|
| 620 |
+
with open(save_path, "wb") as file:
|
| 621 |
+
file.write(uploaded_file.content)
|
| 622 |
+
# Optionally, create a corresponding text file
|
| 623 |
+
text_file_path = save_path + ".txt"
|
| 624 |
+
with open(text_file_path, "w") as text_file:
|
| 625 |
+
text_file.write(f"Image file: {unique_name} uploaded successfully.")
|
| 626 |
+
status_messages.append(f"Uploaded and saved {uploaded_file.name} successfully.")
|
| 627 |
+
else:
|
| 628 |
+
status_messages.append(f"File {uploaded_file.name} has an unsupported extension ({file_extension}) and was not uploaded.")
|
| 629 |
+
return "\n".join(status_messages)
|
| 630 |
+
|
| 631 |
+
def refresh_image_description(current_text, prepend_text, append_text, pause_api_call, save_and_overwrite_changes, custom_prompt):
|
| 632 |
+
global current_index, file_array
|
| 633 |
+
if not pause_api_call:
|
| 634 |
+
file_info = file_array[current_index]
|
| 635 |
+
file_path = find_file_by_hash(file_info["hash"])
|
| 636 |
+
if file_path:
|
| 637 |
+
with Image.open(file_path) as img:
|
| 638 |
+
# Use the custom_prompt parameter when calling get_image_description
|
| 639 |
+
text = get_image_description(img, custom_prompt)
|
| 640 |
+
save_text(file_info["hash"], text, prepend_text, append_text, save_and_overwrite_changes)
|
| 641 |
+
return np.array(img), file_info["hash"], file_info["status"], text, os.path.basename(file_path), file_path, os.path.relpath(file_path, start=image_folder), os.path.basename(file_path).replace(os.path.splitext(os.path.basename(file_path))[1], '.txt'), find_file_by_hash(file_info["hash"]).replace(os.path.splitext(find_file_by_hash(file_info["hash"]))[1], '.txt'), os.path.relpath(find_file_by_hash(file_info["hash"]).replace(os.path.splitext(find_file_by_hash(file_info["hash"]))[1], '.txt'), start=image_folder)
|
| 642 |
+
# If API call is paused or file not found, return current state without changes
|
| 643 |
+
return None, file_info["hash"], file_info["status"], current_text, os.path.basename(file_path), file_path, os.path.relpath(file_path, start=image_folder), os.path.basename(file_path).replace(os.path.splitext(os.path.basename(file_path))[1], '.txt'), find_file_by_hash(file_info["hash"]).replace(os.path.splitext(find_file_by_hash(file_info["hash"]))[1], '.txt'), os.path.relpath(find_file_by_hash(file_info["hash"]).replace(os.path.splitext(find_file_by_hash(file_info["hash"]))[1], '.txt'), start=image_folder)
|
| 644 |
+
# Backup functionality for successful app launches
|
| 645 |
+
backup_folder = "Backup_Scripts"
|
| 646 |
+
os.makedirs(backup_folder, exist_ok=True)
|
| 647 |
+
|
| 648 |
+
def backup_script():
|
| 649 |
+
"""
|
| 650 |
+
This function creates a backup of the current script in the designated backup folder.
|
| 651 |
+
"""
|
| 652 |
+
current_script_path = os.path.realpath(__file__)
|
| 653 |
+
backup_script_path = os.path.join(backup_folder, f"backup_{os.path.basename(current_script_path)}_{datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}.py")
|
| 654 |
+
shutil.copy2(current_script_path, backup_script_path)
|
| 655 |
+
print(f"Backup of the script created at {backup_script_path}")
|
| 656 |
+
|
| 657 |
+
def app_launch_success():
|
| 658 |
+
"""
|
| 659 |
+
This function is called when the app successfully launches.
|
| 660 |
+
It triggers the backup of the current script.
|
| 661 |
+
"""
|
| 662 |
+
print("App successfully launched. Creating a backup of the script...")
|
| 663 |
+
backup_script()
|
| 664 |
+
|
| 665 |
+
def refresh_all():
|
| 666 |
+
combined_details = load_combined_details()
|
| 667 |
+
image_gallery_content = load_gallery()
|
| 668 |
+
thumbs_up_gallery_content = load_thumbs_up_gallery()
|
| 669 |
+
# Reinitialize the hash array and the index for new images
|
| 670 |
+
update_hash_to_path_cache()
|
| 671 |
+
refresh_file_array_and_hashes()
|
| 672 |
+
current_index = 0 # Reset the index to start from the first image
|
| 673 |
+
return combined_details, image_gallery_content, thumbs_up_gallery_content
|
| 674 |
+
|
| 675 |
+
def combined_action(prompt, steps, model, styles, custom_prompt):
|
| 676 |
+
# Trigger the OpenAI API for description and wait for the response
|
| 677 |
+
description, status = trigger_openai_api(custom_prompt)
|
| 678 |
+
if status == "success":
|
| 679 |
+
# Once the response is received, generate the image based on the prompt and other parameters
|
| 680 |
+
generated_image, log = generate_image(prompt, steps, model, styles)
|
| 681 |
+
else:
|
| 682 |
+
generated_image, log = None, "Failed to generate image due to API call failure."
|
| 683 |
+
return generated_image, log, description
|
| 684 |
+
|
| 685 |
+
|
| 686 |
+
# π Setup Environment π
|
| 687 |
+
import gradio as gr
|
| 688 |
+
import os
|
| 689 |
+
from pathlib import Path
|
| 690 |
+
import subprocess
|
| 691 |
+
|
| 692 |
+
# Define the directory to store uploaded images
|
| 693 |
+
image_folder = "./Images"
|
| 694 |
+
os.makedirs(image_folder, exist_ok=True) # Create the directory if it doesn't exist
|
| 695 |
+
|
| 696 |
+
# π Function Definitions π
|
| 697 |
+
def save_and_show_images(uploaded_files):
|
| 698 |
+
images_to_display = []
|
| 699 |
+
# Process each uploaded file
|
| 700 |
+
for index, uploaded_file in enumerate(uploaded_files):
|
| 701 |
+
# Define a base file name with index
|
| 702 |
+
base_file_name = f"Img-{index}"
|
| 703 |
+
# Check for existing files and increment index to avoid overwriting
|
| 704 |
+
existing_files = [f for f in Path(image_folder).rglob('*') if f.is_file() and f.suffix in ['.jpg', '.png', '.txt']]
|
| 705 |
+
while any(base_file_name in file.name for file in existing_files):
|
| 706 |
+
index += 1
|
| 707 |
+
base_file_name = f"Img-{index}"
|
| 708 |
+
|
| 709 |
+
# Determine the file extension (jpg or png)
|
| 710 |
+
file_extension = "jpg" if uploaded_file[:3] == b'\xff\xd8\xff' else "png"
|
| 711 |
+
final_file_name = f"{base_file_name}.{file_extension}"
|
| 712 |
+
image_path = os.path.join(image_folder, final_file_name)
|
| 713 |
+
|
| 714 |
+
# Write the bytes to a new file in the specified directory
|
| 715 |
+
with open(image_path, "wb") as file:
|
| 716 |
+
file.write(uploaded_file)
|
| 717 |
+
|
| 718 |
+
# Create a corresponding text file for the image
|
| 719 |
+
text_file_path = os.path.join(image_folder, f"{base_file_name}.txt")
|
| 720 |
+
with open(text_file_path, "w") as text_file:
|
| 721 |
+
text_file.write(f"Image file: {final_file_name}")
|
| 722 |
+
|
| 723 |
+
# Add the path (or ideally, a URL to the file) to the list to display
|
| 724 |
+
images_to_display.append(image_path)
|
| 725 |
+
|
| 726 |
+
# Ensure all images have a corresponding text file
|
| 727 |
+
for image_file_path in Path(image_folder).rglob('*'):
|
| 728 |
+
if image_file_path.suffix in ['.jpg', '.png']:
|
| 729 |
+
base_name = os.path.splitext(image_file_path.name)[0]
|
| 730 |
+
text_file_path = os.path.join(image_folder, f"{base_name}.txt")
|
| 731 |
+
if not os.path.exists(text_file_path):
|
| 732 |
+
with open(text_file_path, "w") as text_file:
|
| 733 |
+
text_file.write(f"Image file: {image_file_path.name}")
|
| 734 |
+
|
| 735 |
+
return images_to_display
|
| 736 |
+
|
| 737 |
+
|
| 738 |
|
| 739 |
with gr.Blocks() as app:
|
| 740 |
with gr.Row():
|
| 741 |
upload_btn = gr.File(label="Upload Images", type="binary", file_count='multiple')
|
| 742 |
gallery = gr.Gallery(label="Uploaded Images Gallery")
|
| 743 |
+
upload_btn.change(fn=save_and_show_images, inputs=upload_btn, outputs=gallery)
|
| 744 |
+
with gr.Row():
|
| 745 |
+
with gr.Column():
|
| 746 |
+
gr.Markdown("## Image Viewer")
|
| 747 |
+
with gr.Column():
|
| 748 |
+
# Add an upload button for uploading files to the images folder
|
| 749 |
+
|
| 750 |
+
image = gr.Image(height=768, label="Current Image", image_mode="RGBA", width="max", elem_id="current_image", type="numpy")
|
| 751 |
+
with gr.Row():
|
| 752 |
+
thumbs_down_btn = gr.Button("π Rate Down")
|
| 753 |
+
thumbs_up_btn = gr.Button("π Rate Up")
|
| 754 |
+
with gr.Row():
|
| 755 |
+
prev_btn = gr.Button("β¬
Previous")
|
| 756 |
+
next_btn = gr.Button("Next β‘")
|
| 757 |
+
with gr.Row():
|
| 758 |
+
status_display = gr.Textbox(label="Rating Status", interactive=False)
|
| 759 |
+
image_path_display = gr.Textbox(label="Image Path", interactive=False)
|
| 760 |
+
|
| 761 |
+
|
| 762 |
+
|
| 763 |
+
with gr.Column():
|
| 764 |
+
# Existing setup for checkboxes
|
| 765 |
+
with gr.Row():
|
| 766 |
+
pause_api_call_checkbox = gr.Checkbox(label="Pause OpenAI API Calls", value=True)
|
| 767 |
+
save_and_overwrite_changes_checkbox = gr.Checkbox(label="Save and Overwrite Changes", value=True)
|
| 768 |
+
|
| 769 |
+
# New textbox for custom OpenAI API instructions
|
| 770 |
+
custom_instructions = gr.Textbox(label="Custom Instructions", value="Use the art of deduction and creativity to generate a persona profile and 3 inspiration words to describe the image without describing the subject. Wrap it up with a concise 1 sentence caption of the image with the subject in high detail. JSON Format needed: Futuristic Persona Profile: The subject exudes a sense of readiness and authority, dressed in attire that hints at a future dominated by advanced technology and interstellar travel. This character could be envisioned as a commander or a pioneer in a futuristic saga, marked by their composed nature and the streamlined design of their gear. Futuristic Caption: A resolute figure of tomorrow, standing firm with a serene resolve, garbed in a sleek, technologically superior suit that narrates tales of distant realms and adventures. Poised Persona Profile: The individual appears as a beacon of confidence and tactical acumen. Their outfit suggests a world of progressive technology and potential space conquests. This persona might be a strategist or a guardian in a speculative fiction setting, distinguished by their steady presence and the modernistic cut of their uniform. Poised Caption: A visionary sentinel of the cosmos, poised with a calm yet assertive demeanor, dressed in an advanced, form-enhancing suit that hints at the mysteries of the universe yet to unfold. Advanced Persona Profile: The figure stands as a symbol of assurance and innovation, clad in a costume that forecasts an era of sophisticated technology and cosmic exploration. This character could represent an expert or a defender in a futuristic tale, highlighted by their tranquil posture and the elegant configuration of their attire. Advanced Caption: An unwavering pioneer of the future, the individual poses with a composed assurance, enveloped in a cutting-edge suit that speaks of advanced civilizations and uncharted frontiers.", placeholder="Enter custom instructions...", lines=2, max_lines=5)
|
| 771 |
+
with gr.Accordion("π Thumbs Up Gallery", open=False):
|
| 772 |
+
thumbs_up_gallery = gr.Gallery(label="Thumbs Up Image Gallery", value=load_thumbs_up_gallery(), every=5, columns=3, rows=1, object_fit="contain", height="auto")
|
| 773 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 774 |
|
| 775 |
+
with gr.Row():
|
| 776 |
+
text_display = prompt = gr.Textbox(label="Image Analysis", lines=3, max_lines=10, interactive=True, placeholder="API call paused. Manually enter description.")
|
| 777 |
+
output_image = gr.Image(type="pil", label="Visual Analysis Analog")
|
| 778 |
+
|
| 779 |
+
with gr.Row():
|
| 780 |
+
trigger_api_btn = gr.Button("Analyze Aesthetic!")
|
| 781 |
+
combined_btn = gr.Button("Analyze & Generate") # New combined action button
|
| 782 |
+
generate_btn = gr.Button("Generate")
|
| 783 |
+
|
| 784 |
+
analyze_all_btn = gr.Button("Analyze All Thumbs Up")
|
| 785 |
+
descriptions_display = gr.Dataframe()
|
| 786 |
+
status_display = gr.Textbox(label="Status", lines=10, interactive=False)
|
| 787 |
+
analyze_all_btn.click(analyze_thumbs_up_images, inputs=[custom_instructions], outputs=[descriptions_display, status_display])
|
| 788 |
+
|
| 789 |
+
with gr.Row():
|
| 790 |
+
analyze_everything_btn = gr.Button("Analyze All Images")
|
| 791 |
+
|
| 792 |
+
analyze_all_btn.click(analyze_all_images, inputs=[custom_instructions], outputs=[descriptions_display, status_display])
|
| 793 |
+
analyze_everything_btn.click(analyze_all_images, inputs=[custom_instructions], outputs=[descriptions_display, status_display])
|
| 794 |
+
|
| 795 |
+
|
| 796 |
+
with gr.Row():
|
| 797 |
+
gr.Image(type="pil")
|
| 798 |
+
gr.Image(type="pil")
|
| 799 |
+
gr.Image(type="pil")
|
| 800 |
+
|
| 801 |
+
with gr.Accordion("Append / Prepend", open=False):
|
| 802 |
+
with gr.Row():
|
| 803 |
+
prepend_text = gr.Textbox(label="Prepend", lines=2, max_lines=5, placeholder="Enter text to prepend...")
|
| 804 |
+
append_text = gr.Textbox(label="Append", lines=2, max_lines=5, placeholder="Enter text to append...")
|
| 805 |
+
|
| 806 |
+
|
| 807 |
+
def trigger_openai_api(custom_prompt):
|
| 808 |
+
global current_index, file_array
|
| 809 |
+
if current_index < len(file_array):
|
| 810 |
+
file_info = file_array[current_index]
|
| 811 |
+
file_path = find_file_by_hash(file_info["hash"])
|
| 812 |
+
if file_path:
|
| 813 |
+
with Image.open(file_path) as img:
|
| 814 |
+
# Use the custom_prompt parameter when calling get_image_description
|
| 815 |
+
text = get_image_description(img, custom_prompt)
|
| 816 |
+
save_text(file_info["hash"], text, "", "", True) # Assuming you want to save and overwrite changes by default
|
| 817 |
+
return text, "Triggered OpenAI API successfully."
|
| 818 |
+
return "", "Failed to trigger OpenAI API."
|
| 819 |
+
trigger_api_btn.click(trigger_openai_api, inputs=[custom_instructions], outputs=[text_display, status_display])
|
| 820 |
+
|
| 821 |
+
|
| 822 |
+
with gr.Row():
|
| 823 |
+
delete_btn = gr.Button("ποΈ Delete")
|
| 824 |
+
reset_btn = gr.Button("π Reset All Ratings ππ")
|
| 825 |
+
|
| 826 |
+
with gr.Accordion(label="Edit Project", open=False):
|
| 827 |
+
with gr.Column(scale=0):
|
| 828 |
+
file_input = gr.File(file_count="multiple", type="binary", label="Upload Images or Zip Files")
|
| 829 |
+
with gr.Row():
|
| 830 |
+
previous_session_button = gr.Button("π Previous Project")
|
| 831 |
+
next_session_button = gr.Button("Next Projectπ")
|
| 832 |
+
with gr.Row():
|
| 833 |
+
next_img = gr.Button("πΌοΈ Show Next Image")
|
| 834 |
+
prev_img = gr.Button("πΌοΈ Show Previous Image")
|
| 835 |
+
with gr.Row():
|
| 836 |
+
with gr.Row():
|
| 837 |
+
clear_button = gr.Button("ποΈ Clear Uploads Folder")
|
| 838 |
+
undo_button = gr.Button("β©οΈ Undo Last Deletion")
|
| 839 |
+
process_zip_button = gr.Button("π Process Zip Files")
|
| 840 |
+
with gr.Column():
|
| 841 |
+
randomize_checkbox = gr.Checkbox(label="π Randomize Every 2 Seconds", value=True)
|
| 842 |
+
refresh_time_input = gr.Number(label="β±οΈ Refresh Time", value=2)
|
| 843 |
+
index_display = gr.Textbox(value=str(project_index), label="π’ Session Index", every=5)
|
| 844 |
+
file_input.change(process_files, inputs=[file_input], outputs=[])
|
| 845 |
+
clear_button.click(clear_uploads_folder, inputs=[], outputs=[])
|
| 846 |
+
undo_button.click(undo_last_deletion, inputs=[], outputs=[])
|
| 847 |
+
next_session_button.click(next_session, inputs=[], outputs=[index_display])
|
| 848 |
+
previous_session_button.click(previous_session, inputs=[], outputs=[index_display])
|
| 849 |
+
next_img.click(get_next_image, inputs=[], outputs=[gallery])
|
| 850 |
+
prev_img.click(get_previous_image, inputs=[], outputs=[gallery])
|
| 851 |
+
process_zip_button.click(process_all_zips, inputs=[], outputs=[])
|
| 852 |
+
|
| 853 |
+
with gr.Accordion("Advanced Generation Settings", open=False):
|
| 854 |
+
with gr.Column():
|
| 855 |
+
steps = gr.Slider(minimum=1, maximum=32, value=16, label="Steps")
|
| 856 |
+
model = gr.Dropdown(choices=['TurboAnime.saftensors', 'OtherModel'], value='TurboAnime.saftensors', label="Model")
|
| 857 |
+
styles = gr.CheckboxGroup(choices=['RayORender', 'OtherStyle'], value=['RayORender'], label="Styles")
|
| 858 |
+
output_log = gr.Textbox(label="Log")
|
| 859 |
+
# Step 2: Add a button to trigger the update
|
| 860 |
+
|
| 861 |
+
generate_btn.click(fn=generate_image, inputs=[prompt, steps, model, styles], outputs=[output_image, output_log])
|
| 862 |
+
|
| 863 |
+
# Set the click action for the combined button
|
| 864 |
+
combined_btn.click(combined_action, inputs=[prompt, steps, model, styles, custom_instructions], outputs=[output_image, output_log, text_display])
|
| 865 |
+
|
| 866 |
+
|
| 867 |
+
with gr.Accordion("Training Data", open=True):
|
| 868 |
refresh_btn = gr.Button("Refresh")
|
| 869 |
+
with gr.Row():
|
| 870 |
+
combined_details_df = gr.Dataframe(label="Combined Text and Image Details", value=load_combined_details(), headers=["Date Modified", "Rating Status", "File Name", "Text Content", "File Hash", "Text Path", "Image Path"], datatype=["str", "str", "str", "str", "str", "str", "str"], every=5)
|
| 871 |
+
gallery = gr.Gallery(label="Image Gallery", value=load_gallery(), every=5)
|
| 872 |
+
with gr.Accordion("File Info", open=False):
|
| 873 |
+
file_hash_display = gr.Textbox(label="File Hash", interactive=False)
|
| 874 |
+
text_path_display = gr.Textbox(label="Text Path", interactive=False)
|
| 875 |
+
def delete_all_text_files_content():
|
| 876 |
+
text_files = [os.path.join(image_folder, f) for f in os.listdir(image_folder) if f.endswith('.txt')]
|
| 877 |
+
for file_path in text_files:
|
| 878 |
+
with open(file_path, 'w') as f:
|
| 879 |
+
f.write('') # Clear the content of the text file
|
| 880 |
+
return "All text files' content deleted."
|
| 881 |
+
with gr.Row():
|
| 882 |
+
# Add a button to manually trigger a backup of the script
|
| 883 |
+
backup_btn = gr.Button("Backup Script")
|
| 884 |
+
backup_btn.click(backup_script, inputs=[], outputs=[])
|
| 885 |
+
|
| 886 |
+
delete_all_text_btn = gr.Button("Delete All Text Files Content")
|
| 887 |
+
delete_all_text_btn.click(delete_all_text_files_content, inputs=[], outputs=status_display)
|
| 888 |
+
|
| 889 |
+
# Modify the button click actions to include the pause_api_call_checkbox state and the save_and_overwrite_changes_checkbox state as arguments
|
| 890 |
+
reset_btn.click(lambda t, pt, at, p, s, ci: reset_files(t, pt, at, p, s, ci), inputs=[text_display, prepend_text, append_text, pause_api_call_checkbox, save_and_overwrite_changes_checkbox, custom_instructions], outputs=[image, file_hash_display, status_display, text_display, image_path_display, text_path_display])
|
| 891 |
+
prev_btn.click(lambda t, pt, at, p, s, ci: get_file(False, t, pt, at, p, s, ci), inputs=[text_display, prepend_text, append_text, pause_api_call_checkbox, save_and_overwrite_changes_checkbox, custom_instructions], outputs=[image, file_hash_display, status_display, text_display, image_path_display, text_path_display])
|
| 892 |
+
next_btn.click(lambda t, pt, at, p, s, ci: get_file(True, t, pt, at, p, s, ci), inputs=[text_display, prepend_text, append_text, pause_api_call_checkbox, save_and_overwrite_changes_checkbox, custom_instructions], outputs=[image, file_hash_display, status_display, text_display, image_path_display, text_path_display])
|
| 893 |
+
thumbs_up_btn.click(lambda t, pt, at, p, s, ci: move_file("up", t, pt, at, p, s, ci), inputs=[text_display, prepend_text, append_text, pause_api_call_checkbox, save_and_overwrite_changes_checkbox, custom_instructions], outputs=[image, file_hash_display, status_display, text_display, image_path_display, text_path_display])
|
| 894 |
+
thumbs_down_btn.click(lambda t, pt, at, p, s, ci: move_file("down", t, pt, at, p, s, ci), inputs=[text_display, prepend_text, append_text, pause_api_call_checkbox, save_and_overwrite_changes_checkbox, custom_instructions], outputs=[image, file_hash_display, status_display, text_display, image_path_display, text_path_display])
|
| 895 |
+
delete_btn.click(lambda t, pt, at, p, s, ci: delete_file(t, pt, at, p, s, ci), inputs=[text_display, prepend_text, append_text, pause_api_call_checkbox, save_and_overwrite_changes_checkbox, custom_instructions], outputs=[image, file_hash_display, status_display, text_display, image_path_display, text_path_display])
|
| 896 |
+
|
| 897 |
+
refresh_btn.click(refresh_all, inputs=[], outputs=[combined_details_df, gallery, thumbs_up_gallery])
|
| 898 |
+
|
| 899 |
+
|
| 900 |
+
# Check for successful app launch and backup the script
|
| 901 |
+
try:
|
| 902 |
+
app.launch(share=True, server_port=7866, server_name="0.0.0.0")
|
| 903 |
+
app_launch_success()
|
| 904 |
+
except Exception as e:
|
| 905 |
+
print(f"Error launching the app: {e}")
|
| 906 |
+
|
| 907 |
+
|
| 908 |
+
|
| 909 |
+
|
| 910 |
+
|
| 911 |
+
======
|
| 912 |
+
|
| 913 |
+
refactor using programmer golf. keep all hardcoded values, inputs, outputs, and features. Optimize for UI / UX intuitiveness. move all hardcoded values to the top of the script without breaking anything. refactor and simplify with the goal of brininging ui ux principles to coding
|
| 914 |
|
| 915 |
+
Use ui as guide
|