Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,63 +1,146 @@
|
|
|
|
|
| 1 |
import gradio as gr
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 20 |
)
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
)
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
break
|
| 42 |
-
#
|
| 43 |
defaults = [
|
| 44 |
-
"-
|
| 45 |
-
"-
|
| 46 |
-
"-
|
| 47 |
-
"-
|
| 48 |
-
"-
|
| 49 |
]
|
| 50 |
-
for
|
| 51 |
-
if len(
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 61 |
|
| 62 |
if __name__ == "__main__":
|
|
|
|
| 63 |
demo.launch()
|
|
|
|
| 1 |
+
import re
|
| 2 |
import gradio as gr
|
| 3 |
+
import torch
|
| 4 |
+
from PIL import Image
|
| 5 |
+
from transformers import (
|
| 6 |
+
pipeline,
|
| 7 |
+
AutoProcessor,
|
| 8 |
+
AutoModelForVision2Seq,
|
| 9 |
+
AutoTokenizer,
|
| 10 |
+
AutoModelForCausalLM,
|
| 11 |
+
)
|
| 12 |
+
|
| 13 |
+
# Auto-detect CPU/GPU
|
| 14 |
+
DEVICE = 0 if torch.cuda.is_available() else -1
|
| 15 |
+
|
| 16 |
+
# Load BLIP for image captioning
|
| 17 |
+
processor = AutoProcessor.from_pretrained("Salesforce/blip-image-captioning-large")
|
| 18 |
+
blip_model = AutoModelForVision2Seq.from_pretrained("Salesforce/blip-image-captioning-large")
|
| 19 |
+
caption_pipe = pipeline(
|
| 20 |
+
task="image-to-text",
|
| 21 |
+
model=blip_model,
|
| 22 |
+
tokenizer=processor.tokenizer,
|
| 23 |
+
image_processor=processor.image_processor,
|
| 24 |
+
device=DEVICE,
|
| 25 |
+
)
|
| 26 |
+
|
| 27 |
+
# Load Mistral-7B-Instruct for text tasks
|
| 28 |
+
INSTRUCT_MODEL = "mistralai/Mistral-7B-Instruct-v0.2"
|
| 29 |
+
instr_tokenizer = AutoTokenizer.from_pretrained(INSTRUCT_MODEL)
|
| 30 |
+
instr_model = AutoModelForCausalLM.from_pretrained(INSTRUCT_MODEL)
|
| 31 |
+
instr_pipe = pipeline(
|
| 32 |
+
"text-generation",
|
| 33 |
+
model=instr_model,
|
| 34 |
+
tokenizer=instr_tokenizer,
|
| 35 |
+
device=DEVICE,
|
| 36 |
+
max_new_tokens=256,
|
| 37 |
+
temperature=0.5, # Lowered temp for less repetition
|
| 38 |
+
do_sample=True,
|
| 39 |
+
repetition_penalty=1.2, # Discourage repetition
|
| 40 |
+
)
|
| 41 |
+
|
| 42 |
+
def get_recommendations():
|
| 43 |
+
return [
|
| 44 |
+
"https://i.imgur.com/InC88PP.jpeg",
|
| 45 |
+
"https://i.imgur.com/7BHfv4T.png",
|
| 46 |
+
"https://i.imgur.com/wp3Wzc4.jpeg",
|
| 47 |
+
"https://i.imgur.com/5e2xOA4.jpeg",
|
| 48 |
+
"https://i.imgur.com/txjRk98.jpeg",
|
| 49 |
+
"https://i.imgur.com/rQ4AYl0.jpeg",
|
| 50 |
+
"https://i.imgur.com/bDzwD04.jpeg",
|
| 51 |
+
"https://i.imgur.com/fLMngXI.jpeg",
|
| 52 |
+
"https://i.imgur.com/nYEJzxt.png",
|
| 53 |
+
"https://i.imgur.com/Xj92Cjv.jpeg",
|
| 54 |
+
]
|
| 55 |
+
|
| 56 |
+
def process(image: Image):
|
| 57 |
+
if image is None:
|
| 58 |
+
return "", "", "", get_recommendations()
|
| 59 |
+
# 1. BLIP caption
|
| 60 |
+
caption_res = caption_pipe(image, max_new_tokens=64)
|
| 61 |
+
desc = caption_res[0]["generated_text"].strip()
|
| 62 |
+
|
| 63 |
+
# 2. Category (via instruct model)
|
| 64 |
+
cat_prompt = f"<s>[INST] The following is an ad: {desc}\nWhat is the concise category of this ad (e.g. Food, Fitness, Tech, Fashion, Travel, etc)? Respond with one word. [/INST]"
|
| 65 |
+
cat_out = instr_pipe(cat_prompt)[0]['generated_text'].split("\n")[0].strip()
|
| 66 |
+
|
| 67 |
+
# 3. Analysis (via instruct model)
|
| 68 |
+
ana_prompt = (
|
| 69 |
+
f"<s>[INST] Here is an ad description: {desc}\n"
|
| 70 |
+
"Write five sentences analyzing the ad. Cover: 1) What product or service is advertised, 2) Main visual elements, 3) The target audience, 4) The marketing message, 5) The emotional appeal or persuasion technique. Each sentence should be informative and not repeat. [/INST]"
|
| 71 |
)
|
| 72 |
+
ana_raw = instr_pipe(ana_prompt)[0]['generated_text']
|
| 73 |
+
ana_sentences = re.split(r'(?<=[.!?])\s+', ana_raw.strip())
|
| 74 |
+
analysis = " ".join(ana_sentences[:5])
|
| 75 |
+
|
| 76 |
+
# 4. Five suggestions (via instruct model, filter repetitions)
|
| 77 |
+
sug_prompt = (
|
| 78 |
+
f"<s>[INST] Given this ad analysis: {analysis}\n"
|
| 79 |
+
"Suggest five practical, unique improvements for the ad. Each should address a different aspect (message, visuals, call-to-action, targeting, layout, or design). Each suggestion must be one sentence, not repeat, and start with '- '. [/INST]"
|
| 80 |
)
|
| 81 |
+
sug_raw = instr_pipe(sug_prompt)[0]['generated_text']
|
| 82 |
+
bullets = []
|
| 83 |
+
seen = set()
|
| 84 |
+
for line in sug_raw.splitlines():
|
| 85 |
+
if line.startswith("-"):
|
| 86 |
+
suggestion = line.strip()
|
| 87 |
+
if suggestion not in seen and suggestion:
|
| 88 |
+
bullets.append(suggestion)
|
| 89 |
+
seen.add(suggestion)
|
| 90 |
+
elif line.strip():
|
| 91 |
+
suggestion = "- " + line.strip()
|
| 92 |
+
if suggestion not in seen and suggestion:
|
| 93 |
+
bullets.append(suggestion)
|
| 94 |
+
seen.add(suggestion)
|
| 95 |
+
if len(bullets) == 5:
|
| 96 |
break
|
| 97 |
+
# Add generic suggestions only if needed
|
| 98 |
defaults = [
|
| 99 |
+
"- Make the main headline more eye-catching.",
|
| 100 |
+
"- Add a clear and visible call-to-action button.",
|
| 101 |
+
"- Use contrasting colors for better readability.",
|
| 102 |
+
"- Highlight the unique selling point of the product.",
|
| 103 |
+
"- Simplify the design to reduce clutter."
|
| 104 |
]
|
| 105 |
+
for default in defaults:
|
| 106 |
+
if len(bullets) < 5 and default not in seen:
|
| 107 |
+
bullets.append(default)
|
| 108 |
+
suggestions = "\n".join(bullets[:5])
|
| 109 |
+
|
| 110 |
+
return cat_out, analysis, suggestions, get_recommendations()
|
| 111 |
+
|
| 112 |
+
def main():
|
| 113 |
+
with gr.Blocks(title="Smart Ad Analyzer") as demo:
|
| 114 |
+
gr.Markdown("## π’ Smart Ad Analyzer")
|
| 115 |
+
gr.Markdown(
|
| 116 |
+
"""
|
| 117 |
+
**Upload your ad image below and instantly get expert feedback.**
|
| 118 |
+
|
| 119 |
+
This AI tool will analyze your ad and provide:
|
| 120 |
+
- π **Category** β What type of ad is this?
|
| 121 |
+
- π **In-depth Analysis** β Five detailed sentences covering message, visuals, emotional impact, and more.
|
| 122 |
+
- π **Improvement Suggestions** β Five actionable, unique ways to make your ad better.
|
| 123 |
+
- πΈ **Inspiration Gallery** β See other effective ads for ideas.
|
| 124 |
+
|
| 125 |
+
Perfect for marketers, founders, designers, and anyone looking to boost ad performance with actionable insights!
|
| 126 |
+
"""
|
| 127 |
+
)
|
| 128 |
+
with gr.Row():
|
| 129 |
+
inp = gr.Image(type='pil', label='Upload Ad Image')
|
| 130 |
+
with gr.Column():
|
| 131 |
+
cat_out = gr.Textbox(label='π Ad Category', interactive=False)
|
| 132 |
+
ana_out = gr.Textbox(label='π Ad Analysis', lines=5, interactive=False)
|
| 133 |
+
sug_out = gr.Textbox(label='π Improvement Suggestions', lines=5, interactive=False)
|
| 134 |
+
btn = gr.Button('Analyze Ad', variant='primary')
|
| 135 |
+
gallery = gr.Gallery(label='Example Ads')
|
| 136 |
+
btn.click(
|
| 137 |
+
fn=process,
|
| 138 |
+
inputs=[inp],
|
| 139 |
+
outputs=[cat_out, ana_out, sug_out, gallery],
|
| 140 |
+
)
|
| 141 |
+
gr.Markdown('Made by Simon Thalmay')
|
| 142 |
+
return demo
|
| 143 |
|
| 144 |
if __name__ == "__main__":
|
| 145 |
+
demo = main()
|
| 146 |
demo.launch()
|