Spaces:
Running
Running
Commit
·
8ba42b4
1
Parent(s):
d594c0d
Enhance image analysis and generation with improved error handling, format normalization, and user guidance
Browse files
app_pages/image_analyser.py
CHANGED
|
@@ -48,6 +48,7 @@ def render_image_analyser_page(uid: str) -> None:
|
|
| 48 |
"Upload image",
|
| 49 |
type=["jpg", "jpeg", "png", "webp"],
|
| 50 |
key="ia_upload",
|
|
|
|
| 51 |
)
|
| 52 |
|
| 53 |
img_bytes, img_ext, file_name, thumb_b64 = None, "jpg", None, ""
|
|
@@ -57,6 +58,9 @@ def render_image_analyser_page(uid: str) -> None:
|
|
| 57 |
file_name = uploaded.name
|
| 58 |
if "." in file_name:
|
| 59 |
img_ext = file_name.rsplit(".", 1)[-1].lower()
|
|
|
|
|
|
|
|
|
|
| 60 |
|
| 61 |
thumb_b64 = base64.b64encode(img_bytes).decode("utf-8")
|
| 62 |
st.caption("Preview")
|
|
@@ -78,12 +82,28 @@ def render_image_analyser_page(uid: str) -> None:
|
|
| 78 |
try:
|
| 79 |
with st.spinner("Analyzing image..."):
|
| 80 |
result = get_analysis(img_bytes, img_ext)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 81 |
st.session_state["analysis_result"] = result
|
| 82 |
st.session_state["file_name"] = file_name
|
| 83 |
st.session_state["thumb_b64"] = thumb_b64
|
| 84 |
st.session_state["category"] = category
|
| 85 |
except Exception as e:
|
| 86 |
st.error(f"Analysis failed: {e}")
|
|
|
|
| 87 |
|
| 88 |
|
| 89 |
|
|
|
|
| 48 |
"Upload image",
|
| 49 |
type=["jpg", "jpeg", "png", "webp"],
|
| 50 |
key="ia_upload",
|
| 51 |
+
help="Supported formats: JPG, JPEG, PNG, WEBP"
|
| 52 |
)
|
| 53 |
|
| 54 |
img_bytes, img_ext, file_name, thumb_b64 = None, "jpg", None, ""
|
|
|
|
| 58 |
file_name = uploaded.name
|
| 59 |
if "." in file_name:
|
| 60 |
img_ext = file_name.rsplit(".", 1)[-1].lower()
|
| 61 |
+
# Normalize jpg to jpeg for consistency
|
| 62 |
+
if img_ext == "jpg":
|
| 63 |
+
img_ext = "jpeg"
|
| 64 |
|
| 65 |
thumb_b64 = base64.b64encode(img_bytes).decode("utf-8")
|
| 66 |
st.caption("Preview")
|
|
|
|
| 82 |
try:
|
| 83 |
with st.spinner("Analyzing image..."):
|
| 84 |
result = get_analysis(img_bytes, img_ext)
|
| 85 |
+
|
| 86 |
+
# Validate result to ensure no N/A values
|
| 87 |
+
if result and isinstance(result, dict):
|
| 88 |
+
# Check for common N/A patterns and replace them
|
| 89 |
+
def clean_na_values(obj):
|
| 90 |
+
if isinstance(obj, dict):
|
| 91 |
+
return {k: clean_na_values(v) for k, v in obj.items()}
|
| 92 |
+
elif isinstance(obj, list):
|
| 93 |
+
return [clean_na_values(item) for item in obj]
|
| 94 |
+
elif isinstance(obj, str) and obj.upper() in ['N/A', 'NOT AVAILABLE', 'NA']:
|
| 95 |
+
return "Analysis not available - please try with a clearer image"
|
| 96 |
+
return obj
|
| 97 |
+
|
| 98 |
+
result = clean_na_values(result)
|
| 99 |
+
|
| 100 |
st.session_state["analysis_result"] = result
|
| 101 |
st.session_state["file_name"] = file_name
|
| 102 |
st.session_state["thumb_b64"] = thumb_b64
|
| 103 |
st.session_state["category"] = category
|
| 104 |
except Exception as e:
|
| 105 |
st.error(f"Analysis failed: {e}")
|
| 106 |
+
st.error("Please try uploading a different image or check if the image format is supported.")
|
| 107 |
|
| 108 |
|
| 109 |
|
app_pages/image_generation.py
CHANGED
|
@@ -138,14 +138,18 @@ def render_bulk_image_generator(uid: str, prefix: str = "ig_img"):
|
|
| 138 |
|
| 139 |
if demo_btn or gen_all_btn:
|
| 140 |
if zip_file and category and user_prompt:
|
|
|
|
|
|
|
|
|
|
| 141 |
with st.spinner(" Generating image variations..."):
|
| 142 |
temp_dir = tempfile.mkdtemp()
|
| 143 |
try:
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
|
| 148 |
-
|
|
|
|
| 149 |
with open(temp_path, "wb") as f:
|
| 150 |
f.write(zip_file.read())
|
| 151 |
|
|
@@ -161,7 +165,7 @@ def render_bulk_image_generator(uid: str, prefix: str = "ig_img"):
|
|
| 161 |
platform,
|
| 162 |
num_images,
|
| 163 |
demo_btn,
|
| 164 |
-
gallery
|
| 165 |
blur,
|
| 166 |
uid,
|
| 167 |
)
|
|
@@ -176,7 +180,7 @@ def render_bulk_image_generator(uid: str, prefix: str = "ig_img"):
|
|
| 176 |
platform,
|
| 177 |
num_images,
|
| 178 |
demo_btn,
|
| 179 |
-
gallery
|
| 180 |
blur,
|
| 181 |
uid,
|
| 182 |
selected_model_key,
|
|
|
|
| 138 |
|
| 139 |
if demo_btn or gen_all_btn:
|
| 140 |
if zip_file and category and user_prompt:
|
| 141 |
+
# Clear previous images when starting new generation
|
| 142 |
+
st.session_state[gallery_key] = []
|
| 143 |
+
|
| 144 |
with st.spinner(" Generating image variations..."):
|
| 145 |
temp_dir = tempfile.mkdtemp()
|
| 146 |
try:
|
| 147 |
+
# Use original filename for single files, or generate unique name for zip
|
| 148 |
+
if zip_file.name.lower().endswith(".zip"):
|
| 149 |
+
temp_path = os.path.join(temp_dir, zip_file.name)
|
| 150 |
+
else:
|
| 151 |
+
# Use original filename to preserve uniqueness
|
| 152 |
+
temp_path = os.path.join(temp_dir, zip_file.name)
|
| 153 |
with open(temp_path, "wb") as f:
|
| 154 |
f.write(zip_file.read())
|
| 155 |
|
|
|
|
| 165 |
platform,
|
| 166 |
num_images,
|
| 167 |
demo_btn,
|
| 168 |
+
None, # Pass None instead of gallery to avoid appending
|
| 169 |
blur,
|
| 170 |
uid,
|
| 171 |
)
|
|
|
|
| 180 |
platform,
|
| 181 |
num_images,
|
| 182 |
demo_btn,
|
| 183 |
+
None, # Pass None instead of gallery to avoid appending
|
| 184 |
blur,
|
| 185 |
uid,
|
| 186 |
selected_model_key,
|
generator_function/image_processor.py
CHANGED
|
@@ -46,7 +46,8 @@ def process_zip_and_generate_images(
|
|
| 46 |
for u in all_urls:
|
| 47 |
if u not in seen:
|
| 48 |
seen.add(u); deduped.append(u)
|
| 49 |
-
|
|
|
|
| 50 |
except Exception:
|
| 51 |
logger.exception(f"Global error during processing file: {zip_path}")
|
| 52 |
return existing_images or []
|
|
|
|
| 46 |
for u in all_urls:
|
| 47 |
if u not in seen:
|
| 48 |
seen.add(u); deduped.append(u)
|
| 49 |
+
# Return only new images, not appended to existing ones
|
| 50 |
+
return deduped
|
| 51 |
except Exception:
|
| 52 |
logger.exception(f"Global error during processing file: {zip_path}")
|
| 53 |
return existing_images or []
|
generator_function/multimodel_image_processor.py
CHANGED
|
@@ -55,7 +55,8 @@ def process_zip_and_generate_images_multimodel(
|
|
| 55 |
for u in all_urls:
|
| 56 |
if u not in seen:
|
| 57 |
seen.add(u); deduped.append(u)
|
| 58 |
-
|
|
|
|
| 59 |
except Exception:
|
| 60 |
logger.exception(f"Global error during processing file: {zip_path}")
|
| 61 |
return existing_images or []
|
|
|
|
| 55 |
for u in all_urls:
|
| 56 |
if u not in seen:
|
| 57 |
seen.add(u); deduped.append(u)
|
| 58 |
+
# Return only new images, not appended to existing ones
|
| 59 |
+
return deduped
|
| 60 |
except Exception:
|
| 61 |
logger.exception(f"Global error during processing file: {zip_path}")
|
| 62 |
return existing_images or []
|
prompt/image_analyzer_prompt.py
CHANGED
|
@@ -1,11 +1,15 @@
|
|
| 1 |
SYSTEM_PROMPT = """
|
| 2 |
-
You are a senior performance-creative analyst who
|
| 3 |
Rules:
|
| 4 |
- Be precise and concise. Avoid generic fluff.
|
| 5 |
- When unsure, infer cautiously and note uncertainty.
|
| 6 |
- Explain "why it matters" in business terms (CTR, CPC, CVR, RPM, bounce, fatigue, policy).
|
| 7 |
- Do not invent medical claims or promises; flag policy risks instead.
|
| 8 |
- Keep color names human-readable (e.g., "pure orange", "purple", "yellow").
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
"""
|
| 10 |
|
| 11 |
USER_PROMPT_TEMPLATE = """
|
|
@@ -22,4 +26,8 @@ Task: Analyze the attached image ad and produce a structured breakdown:
|
|
| 22 |
Constraints:
|
| 23 |
- Use crisp, decision-ready language.
|
| 24 |
- If text is in Spanish or another language, keep your summaries in English but preserve original CTA text.
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
"""
|
|
|
|
| 1 |
SYSTEM_PROMPT = """
|
| 2 |
+
You are a senior performance-creative analyst who analyzes a SINGLE image ad. Do not include explanations, markdown, or extra keys.
|
| 3 |
Rules:
|
| 4 |
- Be precise and concise. Avoid generic fluff.
|
| 5 |
- When unsure, infer cautiously and note uncertainty.
|
| 6 |
- Explain "why it matters" in business terms (CTR, CPC, CVR, RPM, bounce, fatigue, policy).
|
| 7 |
- Do not invent medical claims or promises; flag policy risks instead.
|
| 8 |
- Keep color names human-readable (e.g., "pure orange", "purple", "yellow").
|
| 9 |
+
- NEVER use "N/A" or "Not Available" - always provide specific analysis based on what you can observe.
|
| 10 |
+
- If you cannot determine a specific value, provide your best professional assessment based on visual cues.
|
| 11 |
+
- For text analysis, if text is not clearly visible, state "Text not clearly visible" rather than "N/A".
|
| 12 |
+
- For color analysis, describe what you can see rather than using "N/A".
|
| 13 |
"""
|
| 14 |
|
| 15 |
USER_PROMPT_TEMPLATE = """
|
|
|
|
| 26 |
Constraints:
|
| 27 |
- Use crisp, decision-ready language.
|
| 28 |
- If text is in Spanish or another language, keep your summaries in English but preserve original CTA text.
|
| 29 |
+
- Provide specific, actionable insights for each section.
|
| 30 |
+
- Avoid using "N/A", "Not Available", or similar placeholder text.
|
| 31 |
+
- If information is not clearly visible, describe what you can observe and make reasonable inferences.
|
| 32 |
+
- Focus on actionable insights that can improve ad performance.
|
| 33 |
"""
|