Compare commits

...

3 Commits

Author SHA1 Message Date
d344674e02 bump tag 0.1.7 2025-05-19 11:15:04 +01:00
b1646a4c6e select model on create page 2025-05-19 11:14:03 +01:00
0b74672844 select model on create page 2025-05-18 21:16:11 +01:00
5 changed files with 92 additions and 49 deletions

View File

@ -1,5 +1,5 @@
[tool.bumpversion] [tool.bumpversion]
current_version = "0.1.6" current_version = "0.1.7"
parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)" parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
serialize = ["{major}.{minor}.{patch}"] serialize = ["{major}.{minor}.{patch}"]
search = "{current_version}" search = "{current_version}"

View File

@ -9,7 +9,7 @@ import os
import time import time
import threading import threading
from apscheduler.schedulers.background import BackgroundScheduler from apscheduler.schedulers.background import BackgroundScheduler
from libs.generic import load_config, load_recent_prompts, get_details_from_png, get_current_version from libs.generic import load_config, load_recent_prompts, get_details_from_png, get_current_version, load_models_from_config
from libs.comfyui import cancel_current_job, create_image from libs.comfyui import cancel_current_job, create_image
from libs.ollama import create_prompt_on_openwebui from libs.ollama import create_prompt_on_openwebui
@ -100,12 +100,14 @@ def create() -> str:
str: Redirect to the main page or a JSON response. str: Redirect to the main page or a JSON response.
""" """
prompt = request.form.get("prompt") if request.method == "POST" else None prompt = request.form.get("prompt") if request.method == "POST" else None
model = request.form.get("model") if request.method == "POST" else "Random"
if prompt is None: if prompt is None:
prompt = create_prompt_on_openwebui(user_config["comfyui"]["prompt"]) prompt = create_prompt_on_openwebui(user_config["comfyui"]["prompt"])
def create_image_in_background(): def create_image_in_background():
create_image(prompt) create_image(prompt, model)
threading.Thread(target=create_image_in_background).start() threading.Thread(target=create_image_in_background).start()
return render_template('image_queued.html', prompt=prompt) return render_template('image_queued.html', prompt=prompt)
@ -122,8 +124,11 @@ def create_image_endpoint() -> str:
Renders the create image template with image and prompt. Renders the create image template with image and prompt.
""" """
models = load_models_from_config()
models.insert(0, "Random")
return render_template( return render_template(
"create_image.html" "create_image.html", models=models
) )

View File

@ -71,6 +71,7 @@ def generate_image(
save_param: str = "filename_prefix", save_param: str = "filename_prefix",
model_node: Optional[str] = "Load Checkpoint", model_node: Optional[str] = "Load Checkpoint",
model_param: Optional[str] = "ckpt_name", model_param: Optional[str] = "ckpt_name",
model: Optional[str] = "None",
) -> None: ) -> None:
"""Generates an image using the Comfy API with configurable workflow settings.""" """Generates an image using the Comfy API with configurable workflow settings."""
try: try:
@ -100,20 +101,6 @@ def generate_image(
user_config["comfyui"]["height"], user_config["comfyui"]["height"],
) )
# Conditionally set model if node and param are provided
if model_node and model_param:
if "FLUX" in workflow_path:
valid_models = user_config["comfyui:flux"]["models"].split(",")
else:
available_model_list = user_config["comfyui"]["models"].split(",")
valid_models = list(
set(get_available_models()) & set(available_model_list)
)
if not valid_models:
raise Exception("No valid models available.")
model = random.choice(valid_models)
wf.set_node_param(model_node, model_param, model) wf.set_node_param(model_node, model_param, model)
# Generate image # Generate image
@ -136,24 +123,29 @@ def generate_image(
raise raise
def create_image(prompt: str | None = None) -> None: def create_image(prompt: str | None = None, model: str = "Random") -> None:
"""Main function for generating images.""" """Generate an image with a chosen workflow (Random, FLUX*, or SDXL*)."""
if prompt is None: if prompt is None:
prompt = create_prompt_on_openwebui(user_config["comfyui"]["prompt"]) prompt = create_prompt_on_openwebui(user_config["comfyui"]["prompt"])
if not prompt: if not prompt:
logging.error("No prompt generated.") logging.error("No prompt generated.")
return return
save_prompt(prompt) save_prompt(prompt)
use_flux = json.loads(user_config["comfyui"].get("FLUX", "false").lower())
use_flux = json.loads((user_config["comfyui"].get("FLUX", False)).lower()) only_flux = json.loads(user_config["comfyui"].get("ONLY_FLUX", "false").lower())
only_flux = json.loads((user_config["comfyui"].get("ONLY_FLUX", False)).lower()) if model == "Random":
selected_workflow = "FLUX" if (use_flux and (only_flux or random.choice([True, False]))) else "SDXL"
elif "flux" in model.lower():
selected_workflow = "FLUX"
else:
selected_workflow = "SDXL" selected_workflow = "SDXL"
if use_flux:
selected_workflow = "FLUX" if only_flux else random.choice(["FLUX", "SDXL"])
if selected_workflow == "FLUX": if selected_workflow == "FLUX":
if model == "Random":
valid_models = user_config["comfyui:flux"]["models"].split(",")
model = random.choice(valid_models)
generate_image( generate_image(
file_name="image", file_name="image",
comfy_prompt=prompt, comfy_prompt=prompt,
@ -165,9 +157,14 @@ def create_image(prompt: str | None = None) -> None:
save_param="filename", save_param="filename",
model_node="CivitAI Image Saver", model_node="CivitAI Image Saver",
model_param="modelname", model_param="modelname",
model=model
) )
else: else: # SDXL
generate_image("image", prompt) if model == "Random":
available_model_list = user_config["comfyui"]["models"].split(",")
valid_models = list(set(get_available_models()) & set(available_model_list))
model = random.choice(valid_models)
generate_image("image", comfy_prompt=prompt, model=model)
logging.info(f"{selected_workflow} generation started with prompt: {prompt}") logging.info(f"{selected_workflow} generation started with prompt: {prompt}")

View File

@ -98,6 +98,12 @@ def get_current_version():
print("Error running bump-my-version:", e) print("Error running bump-my-version:", e)
return None return None
def load_models_from_config():
flux_models = user_config["comfyui:flux"]["models"].split(",")
sdxl_models = user_config["comfyui"]["models"].split(",")
all_models = flux_models + sdxl_models
return all_models
user_config = load_config() user_config = load_config()
output_folder = user_config["comfyui"]["output_dir"] output_folder = user_config["comfyui"]["output_dir"]

View File

@ -1,15 +1,14 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Create An Image</title> <title>Create An Image</title>
<style> <style>
* { /* ---------- reset ---------- */
margin: 0; * { margin: 0; padding: 0; box-sizing: border-box; }
padding: 0;
box-sizing: border-box; /* ---------- layout ---------- */
}
body { body {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -37,8 +36,9 @@
.button-group { .button-group {
display: flex; display: flex;
gap: 20px; gap: 20px;
align-items: center;
} }
button { button, select {
background: #333; background: #333;
color: white; color: white;
border: none; border: none;
@ -48,9 +48,8 @@
cursor: pointer; cursor: pointer;
transition: background 0.3s; transition: background 0.3s;
} }
button:hover { button:hover,
background: #555; select:hover { background: #555; }
}
/* ---------- spinner ---------- */ /* ---------- spinner ---------- */
#spinner-overlay { #spinner-overlay {
@ -60,7 +59,7 @@
align-items: center; align-items: center;
justify-content: center; justify-content: center;
background: rgba(0, 0, 0, 0.6); background: rgba(0, 0, 0, 0.6);
visibility: hidden; /* toggled in JS */ visibility: hidden;
z-index: 1000; z-index: 1000;
} }
.spinner { .spinner {
@ -76,11 +75,24 @@
</head> </head>
<body> <body>
<h1 style="margin-bottom: 20px;">Create An Image</h1> <h1 style="margin-bottom: 20px;">Create An Image</h1>
<textarea id="prompt-box" placeholder="Enter your custom prompt here..."></textarea> <textarea id="prompt-box" placeholder="Enter your custom prompt here..."></textarea>
<div class="button-group"> <div class="button-group">
<button onclick="showSpinner(); location.href='/'">Back</button> <button onclick="showSpinner(); location.href='/'">Back</button>
<button onclick="sendPrompt()">Send Prompt</button> <button onclick="sendPrompt()">Send Prompt</button>
<button onclick="showSpinner(); location.href='/create'">Random Prompt</button>
<button onclick="randomPrompt()">Random Prompt</button>
<!-- new model selector -->
<select id="model-select">
{% for m in models %}
<option value="{{ m }}">{{ m }}</option>
{% endfor %}
</select>
</div> </div>
<!-- waiting overlay --> <!-- waiting overlay -->
@ -90,15 +102,17 @@
<script> <script>
const overlay = document.getElementById('spinner-overlay'); const overlay = document.getElementById('spinner-overlay');
function showSpinner() {
overlay.style.visibility = 'visible'; function showSpinner() { overlay.style.visibility = 'visible'; }
}
function sendPrompt() { function sendPrompt() {
showSpinner(); showSpinner();
const prompt = document.getElementById('prompt-box').value; const prompt = document.getElementById('prompt-box').value;
const model = document.getElementById('model-select').value;
const formData = new URLSearchParams(); const formData = new URLSearchParams();
formData.append('prompt', prompt); formData.append('prompt', prompt);
formData.append('model', model);
fetch('/create', { fetch('/create', {
method: 'POST', method: 'POST',
@ -106,14 +120,35 @@
body: formData.toString() body: formData.toString()
}) })
.then(response => { .then(response => {
// If server redirects, follow it; otherwise go to /create
window.location.href = response.redirected ? response.url : '/create'; window.location.href = response.redirected ? response.url : '/create';
}) })
.catch(error => { .catch(error => {
overlay.style.visibility = 'hidden'; // hide spinner on failure overlay.style.visibility = 'hidden';
alert("Error sending prompt: " + error); alert("Error sending prompt: " + error);
}); });
} }
// wrapper for Random Prompt button so it also sends the model
function randomPrompt() {
showSpinner();
const model = document.getElementById('model-select').value;
const formData = new URLSearchParams();
formData.append('model', model);
fetch('/create', {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: formData.toString()
})
.then(response => {
window.location.href = response.redirected ? response.url : '/create';
})
.catch(error => {
overlay.style.visibility = 'hidden';
alert("Error requesting random prompt: " + error);
});
}
</script> </script>
</body> </body>
</html> </html>