Refactor recipe metadata processing in RecipeRoutes

- Introduced a new RecipeParserFactory to streamline the parsing of recipe metadata from user comments, supporting multiple formats.
- Removed legacy metadata extraction logic from RecipeRoutes, delegating responsibilities to the new parser classes.
- Enhanced error handling for cases where no valid parser is found, ensuring graceful responses.
- Updated the RecipeScanner to improve the handling of LoRA metadata and reduce logging verbosity for better performance.
This commit is contained in:
Will Miao
2025-03-18 18:54:22 +08:00
parent 4264dd19a8
commit e2191ab4b4
4 changed files with 373 additions and 284 deletions

View File

@@ -58,77 +58,6 @@ class ExifUtils:
except Exception as e:
logger.error(f"Error updating EXIF data in {image_path}: {e}")
return image_path
@staticmethod
def parse_recipe_metadata(user_comment: str) -> Dict[str, Any]:
"""Parse recipe metadata from UserComment"""
try:
# Split by 'Negative prompt:' to get the prompt
parts = user_comment.split('Negative prompt:', 1)
prompt = parts[0].strip()
# Initialize metadata with prompt
metadata = {"prompt": prompt, "loras": [], "checkpoint": None}
# Extract additional fields if available
if len(parts) > 1:
negative_and_params = parts[1]
# Extract negative prompt
if "Steps:" in negative_and_params:
neg_prompt = negative_and_params.split("Steps:", 1)[0].strip()
metadata["negative_prompt"] = neg_prompt
# Extract key-value parameters (Steps, Sampler, CFG scale, etc.)
param_pattern = r'([A-Za-z ]+): ([^,]+)'
params = re.findall(param_pattern, negative_and_params)
for key, value in params:
clean_key = key.strip().lower().replace(' ', '_')
metadata[clean_key] = value.strip()
# Extract Civitai resources
if 'Civitai resources:' in user_comment:
resources_part = user_comment.split('Civitai resources:', 1)[1]
if '],' in resources_part:
resources_json = resources_part.split('],', 1)[0] + ']'
try:
resources = json.loads(resources_json)
# Filter loras and checkpoints
for resource in resources:
if resource.get('type') == 'lora':
# 确保 weight 字段被正确保留
lora_entry = resource.copy()
# 如果找不到 weight默认为 1.0
if 'weight' not in lora_entry:
lora_entry['weight'] = 1.0
# Ensure modelVersionName is included
if 'modelVersionName' not in lora_entry:
lora_entry['modelVersionName'] = ''
metadata['loras'].append(lora_entry)
elif resource.get('type') == 'checkpoint':
metadata['checkpoint'] = resource
except json.JSONDecodeError:
pass
return metadata
except Exception as e:
logger.error(f"Error parsing recipe metadata: {e}")
return {"prompt": user_comment, "loras": [], "checkpoint": None}
@staticmethod
def extract_recipe_metadata(user_comment: str) -> Optional[Dict]:
"""Extract recipe metadata section from UserComment if it exists"""
try:
# Look for recipe metadata section
recipe_match = re.search(r'Recipe metadata: (\{.*\})', user_comment, re.IGNORECASE | re.DOTALL)
if not recipe_match:
return None
recipe_json = recipe_match.group(1)
return json.loads(recipe_json)
except Exception as e:
logger.error(f"Error extracting recipe metadata: {e}")
return None
@staticmethod
def append_recipe_metadata(image_path, recipe_data) -> str: