Update app.py
Browse files
app.py
CHANGED
@@ -459,59 +459,133 @@ def _fallback_image_analysis(prompt: str, review_guidelines: str) -> str:
|
|
459 |
"original_prompt": prompt
|
460 |
})
|
461 |
|
462 |
-
def generate_and_review_marketing_image(prompt: str, style: str = "realistic", review_guidelines: str = "") -> str:
|
463 |
"""
|
464 |
-
Complete workflow: Generate a marketing image and provide quality review.
|
465 |
|
466 |
Args:
|
467 |
prompt (str): Description of the marketing image to generate
|
468 |
style (str): Art style for the image (realistic, artistic, cartoon, photographic, illustration)
|
469 |
review_guidelines (str): Specific guidelines for marketing review
|
|
|
|
|
470 |
|
471 |
Returns:
|
472 |
str: JSON string containing image, review, and recommendations
|
473 |
"""
|
474 |
logger.info(f"π Starting complete marketing workflow for: {prompt}")
|
|
|
|
|
|
|
|
|
|
|
475 |
|
476 |
try:
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
488 |
|
489 |
-
# Combine results
|
490 |
workflow_result = {
|
491 |
"success": True,
|
492 |
"image": {
|
493 |
-
"url":
|
494 |
-
"data":
|
495 |
"prompt": prompt,
|
496 |
"style": style
|
497 |
},
|
498 |
"review": {
|
499 |
-
"quality_score":
|
500 |
-
"final_status":
|
501 |
-
"iterations":
|
502 |
-
"passed":
|
503 |
-
"recommendations": analysis_data.get("recommendations", []),
|
504 |
-
"analysis_details": analysis_data
|
|
|
505 |
},
|
506 |
"metadata": {
|
507 |
-
"generation_method": generation_data.get("generation_method", "unknown"),
|
508 |
-
"real_ai_generation": generation_data.get("real_ai_generation", False),
|
509 |
-
"review_method": analysis_data.get("analysis_method", "unknown"),
|
510 |
-
"workflow_type": "gradio_mcp_server"
|
|
|
|
|
511 |
}
|
512 |
}
|
513 |
|
514 |
-
logger.info("β
Complete marketing workflow successful!")
|
515 |
return json.dumps(workflow_result)
|
516 |
|
517 |
except Exception as e:
|
@@ -618,14 +692,20 @@ def process_generated_image_and_results(api_response_str: str) -> Tuple[Image.Im
|
|
618 |
except Exception as e:
|
619 |
return None, f"β Error processing results: {str(e)}"
|
620 |
|
621 |
-
def gradio_generate_marketing_image(prompt: str, style: str, review_guidelines: str) -> Tuple[Image.Image, str]:
|
622 |
-
"""Gradio interface wrapper for complete marketing image generation"""
|
623 |
if not prompt.strip():
|
624 |
return None, "β οΈ Please enter a prompt to generate an image."
|
625 |
|
626 |
try:
|
627 |
-
# Use the complete workflow function
|
628 |
-
result_json = generate_and_review_marketing_image(
|
|
|
|
|
|
|
|
|
|
|
|
|
629 |
return process_generated_image_and_results(result_json)
|
630 |
except Exception as e:
|
631 |
error_message = f"β Error: {str(e)}"
|
|
|
459 |
"original_prompt": prompt
|
460 |
})
|
461 |
|
462 |
+
def generate_and_review_marketing_image(prompt: str, style: str = "realistic", review_guidelines: str = "", max_retries: int = 3, review_threshold: float = 0.8) -> str:
|
463 |
"""
|
464 |
+
Complete workflow: Generate a marketing image and provide quality review with iterations.
|
465 |
|
466 |
Args:
|
467 |
prompt (str): Description of the marketing image to generate
|
468 |
style (str): Art style for the image (realistic, artistic, cartoon, photographic, illustration)
|
469 |
review_guidelines (str): Specific guidelines for marketing review
|
470 |
+
max_retries (int): Maximum number of generation attempts
|
471 |
+
review_threshold (float): Minimum quality score required for approval
|
472 |
|
473 |
Returns:
|
474 |
str: JSON string containing image, review, and recommendations
|
475 |
"""
|
476 |
logger.info(f"π Starting complete marketing workflow for: {prompt}")
|
477 |
+
logger.info(f"π Max retries: {max_retries}, Review threshold: {review_threshold}")
|
478 |
+
|
479 |
+
workflow_history = []
|
480 |
+
best_result = None
|
481 |
+
best_score = 0.0
|
482 |
|
483 |
try:
|
484 |
+
for iteration in range(1, max_retries + 1):
|
485 |
+
logger.info(f"π Iteration {iteration} of {max_retries}")
|
486 |
+
|
487 |
+
# Step 1: Generate the image
|
488 |
+
generation_response = generate_marketing_image(prompt, style)
|
489 |
+
generation_data = json.loads(generation_response)
|
490 |
+
|
491 |
+
if not generation_data.get("success", False):
|
492 |
+
logger.error(f"Generation failed on iteration {iteration}: {generation_data.get('error')}")
|
493 |
+
workflow_history.append({
|
494 |
+
"iteration": iteration,
|
495 |
+
"generation_status": "failed",
|
496 |
+
"review_score": 0.0,
|
497 |
+
"error": generation_data.get('error', 'Unknown error')
|
498 |
+
})
|
499 |
+
continue
|
500 |
+
|
501 |
+
# Step 2: Analyze the generated image with Gemini Vision
|
502 |
+
image_url = generation_data.get("image_url", "")
|
503 |
+
analysis_response = analyze_marketing_image_with_gemini(image_url, prompt, review_guidelines)
|
504 |
+
analysis_data = json.loads(analysis_response)
|
505 |
+
|
506 |
+
current_score = analysis_data.get("overall_score", 0.0)
|
507 |
+
logger.info(f"π Iteration {iteration} score: {current_score:.2f} (threshold: {review_threshold})")
|
508 |
+
|
509 |
+
# Record this iteration
|
510 |
+
workflow_history.append({
|
511 |
+
"iteration": iteration,
|
512 |
+
"generation_status": "success",
|
513 |
+
"review_score": current_score,
|
514 |
+
"review_method": analysis_data.get("analysis_method", "unknown"),
|
515 |
+
"recommendations": analysis_data.get("recommendations", [])[:3] # Top 3 for history
|
516 |
+
})
|
517 |
+
|
518 |
+
# Create result for this iteration
|
519 |
+
current_result = {
|
520 |
+
"generation_data": generation_data,
|
521 |
+
"analysis_data": analysis_data,
|
522 |
+
"image_url": image_url,
|
523 |
+
"score": current_score,
|
524 |
+
"iteration": iteration
|
525 |
+
}
|
526 |
+
|
527 |
+
# Keep track of best result
|
528 |
+
if current_score > best_score:
|
529 |
+
best_result = current_result
|
530 |
+
best_score = current_score
|
531 |
+
|
532 |
+
# Check if threshold is met
|
533 |
+
if current_score >= review_threshold:
|
534 |
+
logger.info(f"β
Quality threshold met on iteration {iteration}! Score: {current_score:.2f}")
|
535 |
+
best_result = current_result # Use this result since it passes threshold
|
536 |
+
break
|
537 |
+
else:
|
538 |
+
logger.info(f"β οΈ Score {current_score:.2f} below threshold {review_threshold}. {'Retrying...' if iteration < max_retries else 'Max attempts reached.'}")
|
539 |
+
|
540 |
+
# Enhance prompt for next iteration based on feedback
|
541 |
+
if iteration < max_retries:
|
542 |
+
missing_elements = analysis_data.get("missing_elements", [])
|
543 |
+
violations = analysis_data.get("violations", [])
|
544 |
+
if missing_elements:
|
545 |
+
prompt += f" Including: {', '.join(missing_elements[:2])}"
|
546 |
+
if violations and "english" in review_guidelines.lower():
|
547 |
+
prompt += " with English signage and text"
|
548 |
+
|
549 |
+
# Use best result if we have one
|
550 |
+
if not best_result:
|
551 |
+
return json.dumps({
|
552 |
+
"success": False,
|
553 |
+
"error": "All generation attempts failed",
|
554 |
+
"workflow_history": workflow_history
|
555 |
+
})
|
556 |
+
|
557 |
+
# Build final result
|
558 |
+
final_passed = best_result["score"] >= review_threshold
|
559 |
+
final_status = "passed" if final_passed else "needs_improvement"
|
560 |
|
|
|
561 |
workflow_result = {
|
562 |
"success": True,
|
563 |
"image": {
|
564 |
+
"url": best_result["image_url"],
|
565 |
+
"data": best_result["image_url"],
|
566 |
"prompt": prompt,
|
567 |
"style": style
|
568 |
},
|
569 |
"review": {
|
570 |
+
"quality_score": best_result["score"],
|
571 |
+
"final_status": final_status,
|
572 |
+
"iterations": len(workflow_history),
|
573 |
+
"passed": final_passed,
|
574 |
+
"recommendations": best_result["analysis_data"].get("recommendations", []),
|
575 |
+
"analysis_details": best_result["analysis_data"],
|
576 |
+
"workflow_history": workflow_history
|
577 |
},
|
578 |
"metadata": {
|
579 |
+
"generation_method": best_result["generation_data"].get("generation_method", "unknown"),
|
580 |
+
"real_ai_generation": best_result["generation_data"].get("real_ai_generation", False),
|
581 |
+
"review_method": best_result["analysis_data"].get("analysis_method", "unknown"),
|
582 |
+
"workflow_type": "gradio_mcp_server",
|
583 |
+
"best_iteration": best_result["iteration"],
|
584 |
+
"threshold_met": final_passed
|
585 |
}
|
586 |
}
|
587 |
|
588 |
+
logger.info(f"β
Complete marketing workflow successful! Best score: {best_score:.2f} from iteration {best_result['iteration']}")
|
589 |
return json.dumps(workflow_result)
|
590 |
|
591 |
except Exception as e:
|
|
|
692 |
except Exception as e:
|
693 |
return None, f"β Error processing results: {str(e)}"
|
694 |
|
695 |
+
def gradio_generate_marketing_image(prompt: str, style: str, max_retries: int, review_threshold: float, review_guidelines: str) -> Tuple[Image.Image, str]:
|
696 |
+
"""Gradio interface wrapper for complete marketing image generation with iterations"""
|
697 |
if not prompt.strip():
|
698 |
return None, "β οΈ Please enter a prompt to generate an image."
|
699 |
|
700 |
try:
|
701 |
+
# Use the complete workflow function with iteration parameters
|
702 |
+
result_json = generate_and_review_marketing_image(
|
703 |
+
prompt=prompt,
|
704 |
+
style=style,
|
705 |
+
review_guidelines=review_guidelines,
|
706 |
+
max_retries=max_retries,
|
707 |
+
review_threshold=review_threshold
|
708 |
+
)
|
709 |
return process_generated_image_and_results(result_json)
|
710 |
except Exception as e:
|
711 |
error_message = f"β Error: {str(e)}"
|