feat: Integrate metadata collection in RecipeRoutes and simplify saveRecipeDirectly function

This commit is contained in:
Will Miao
2025-04-16 22:15:46 +08:00
parent d4b2dd0ec1
commit 4c69d8d3a8
2 changed files with 16 additions and 41 deletions

View File

@@ -11,7 +11,8 @@ from ..utils.recipe_parsers import RecipeParserFactory
from ..utils.constants import CARD_PREVIEW_WIDTH from ..utils.constants import CARD_PREVIEW_WIDTH
from ..config import config from ..config import config
from ..workflow.parser import WorkflowParser from ..metadata_collector import get_metadata # Add MetadataCollector import
from ..metadata_collector.metadata_processor import MetadataProcessor # Add MetadataProcessor import
from ..utils.utils import download_civitai_image from ..utils.utils import download_civitai_image
from ..services.service_registry import ServiceRegistry # Add ServiceRegistry import from ..services.service_registry import ServiceRegistry # Add ServiceRegistry import
@@ -24,7 +25,7 @@ class RecipeRoutes:
# Initialize service references as None, will be set during async init # Initialize service references as None, will be set during async init
self.recipe_scanner = None self.recipe_scanner = None
self.civitai_client = None self.civitai_client = None
self.parser = WorkflowParser() # Remove WorkflowParser instance
# Pre-warm the cache # Pre-warm the cache
self._init_cache_task = None self._init_cache_task = None
@@ -786,25 +787,13 @@ class RecipeRoutes:
# Ensure services are initialized # Ensure services are initialized
await self.init_services() await self.init_services()
reader = await request.multipart() # Get metadata using the metadata collector instead of workflow parsing
raw_metadata = get_metadata()
metadata_dict = MetadataProcessor.to_dict(raw_metadata)
# Process form data # Check if we have valid metadata
workflow_json = None if not metadata_dict:
return web.json_response({"error": "No generation metadata found"}, status=400)
while True:
field = await reader.next()
if field is None:
break
if field.name == 'workflow_json':
workflow_text = await field.text()
try:
workflow_json = json.loads(workflow_text)
except:
return web.json_response({"error": "Invalid workflow JSON"}, status=400)
if not workflow_json:
return web.json_response({"error": "Missing workflow JSON"}, status=400)
# Find the latest image in the temp directory # Find the latest image in the temp directory
temp_dir = config.temp_directory temp_dir = config.temp_directory
@@ -822,14 +811,8 @@ class RecipeRoutes:
image_files.sort(key=lambda x: x[1], reverse=True) image_files.sort(key=lambda x: x[1], reverse=True)
latest_image_path = image_files[0][0] latest_image_path = image_files[0][0]
# Parse the workflow to extract generation parameters and loras # Get the lora stack from the metadata
parsed_workflow = self.parser.parse_workflow(workflow_json) lora_stack = metadata_dict.get("loras", "")
if not parsed_workflow:
return web.json_response({"error": "Could not extract parameters from workflow"}, status=400)
# Get the lora stack from the parsed workflow
lora_stack = parsed_workflow.get("loras", "")
# Parse the lora stack format: "<lora:name:strength> <lora:name2:strength2> ..." # Parse the lora stack format: "<lora:name:strength> <lora:name2:strength2> ..."
import re import re
@@ -837,7 +820,7 @@ class RecipeRoutes:
# Check if any loras were found # Check if any loras were found
if not lora_matches: if not lora_matches:
return web.json_response({"error": "No LoRAs found in the workflow"}, status=400) return web.json_response({"error": "No LoRAs found in the generation metadata"}, status=400)
# Generate recipe name from the first 3 loras (or less if fewer are available) # Generate recipe name from the first 3 loras (or less if fewer are available)
loras_for_name = lora_matches[:3] # Take at most 3 loras for the name loras_for_name = lora_matches[:3] # Take at most 3 loras for the name
@@ -922,8 +905,8 @@ class RecipeRoutes:
"created_date": time.time(), "created_date": time.time(),
"base_model": most_common_base_model, "base_model": most_common_base_model,
"loras": loras_data, "loras": loras_data,
"checkpoint": parsed_workflow.get("checkpoint", ""), "checkpoint": metadata_dict.get("checkpoint", ""),
"gen_params": {key: value for key, value in parsed_workflow.items() "gen_params": {key: value for key, value in metadata_dict.items()
if key not in ['checkpoint', 'loras']}, if key not in ['checkpoint', 'loras']},
"loras_stack": lora_stack # Include the original lora stack string "loras_stack": lora_stack # Include the original lora stack string
} }

View File

@@ -966,9 +966,6 @@ export function addLorasWidget(node, name, opts, callback) {
// Function to directly save the recipe without dialog // Function to directly save the recipe without dialog
async function saveRecipeDirectly(widget) { async function saveRecipeDirectly(widget) {
try { try {
// Get the workflow data from the ComfyUI app
const prompt = await app.graphToPrompt();
// Show loading toast // Show loading toast
if (app && app.extensionManager && app.extensionManager.toast) { if (app && app.extensionManager && app.extensionManager.toast) {
app.extensionManager.toast.add({ app.extensionManager.toast.add({
@@ -979,14 +976,9 @@ async function saveRecipeDirectly(widget) {
}); });
} }
// Prepare the data - only send workflow JSON // Send the request to the backend API without workflow data
const formData = new FormData();
formData.append('workflow_json', JSON.stringify(prompt.output));
// Send the request
const response = await fetch('/api/recipes/save-from-widget', { const response = await fetch('/api/recipes/save-from-widget', {
method: 'POST', method: 'POST'
body: formData
}); });
const result = await response.json(); const result = await response.json();