webringai/ideation-agent
0
1import gradio as gr2import re3import random4import json5from dotenv import load_dotenv6import os7from openai import OpenAI8 9# 🔐 Load API Key from .env10load_dotenv()11api_key = os.getenv("OPENAI_API_KEY")12client = OpenAI(api_key=api_key)13 14# 1) Load your product catalog once at startup15def load_product_catalog(path="products.json"):16 with open(path, "r", encoding="utf-8") as f:17 data = json.load(f)18 # Expecting products_desc to be a dict: { "iboothme X": "…", … }19 return data["products_desc"]20 21PRODUCT_CATALOG = load_product_catalog()22 23# 2) Helper to pull full descriptions for a list of product names24def get_product_descriptions(product_names: list[str]) -> str:25 entries = []26 for name in product_names:27 desc = PRODUCT_CATALOG.get(name)28 if desc:29 entries.append(f"**{name}**\n{desc}")30 return "\n\n".join(entries)31 32# Keyword extraction from the paragraph33def extract_keywords(paragraph: str) -> list[str]:34 prompt = f"""35You are an expert in experiential event planning.36 37Extract 5-10 short, specific, and thematic keywords or concepts from the event description below. These will be used to inspire immersive, tech-powered event ideas.38 39Each keyword should be 2-4 words long and describe a concrete idea or theme (e.g., "photo booths", "smart vending", "interactive storytelling").40 41Event Description:42\"{paragraph}\"43 44Return the keywords as a comma-separated list.45"""46 response = client.chat.completions.create(47 model="gpt-4",48 messages=[{"role": "user", "content": prompt}],49 temperature=0.7,50 max_tokens=20051 )52 raw = response.choices[0].message.content53 return [kw.strip().lower() for kw in re.split(r'[,\n]', raw) if kw.strip()]54 55# (Optional) Keyword extraction from titles/links56def extract_keywords_from_title_and_link(title: str, link: str) -> list[str]:57 prompt = f"""58You are an expert in event innovation.59 60Given the title and link below, extract 3-5 short, specific, and meaningful keywords or themes (2-4 words each) that describe what the page is about.61 62Title: {title}63Link: {link}64 65Return the keywords as a comma-separated list.66"""67 response = client.chat.completions.create(68 model="gpt-4",69 messages=[{"role": "user", "content": prompt}],70 temperature=0.6,71 max_tokens=15072 )73 raw = response.choices[0].message.content74 return [kw.strip().lower() for kw in re.split(r'[,\n]', raw) if kw.strip()]75 76# (Optional) Web search for inspiration77def search_similar_events_and_products_openai(keywords: list[str]) -> list[tuple[str,str]]:78 input_text = f"Generate 10 useful URLs for experiential event ideas or iboothme.com inspiration related to the keywords: {', '.join(keywords)}"79 try:80 response = client.responses.create(81 model="gpt-4.1",82 tools=[{"type": "web_search_preview"}],83 input=input_text84 )85 content = response.output_text86 results = []87 for line in content.split("\n"):88 if "http" in line:89 parts = line.split(" - ", 1)90 if len(parts) == 2:91 results.append((parts[0].strip(), parts[1].strip()))92 else:93 url = line.strip()94 results.append((url, url))95 return results[:10]96 except Exception as e:97 print("Search failed:", e)98 return []99 100# Core idea generation, enriched with random product descriptions101def generate_event_ideas(102 paragraph: str,103 product_info: str,104 search_links: list[tuple[str,str]],105 all_keywords: list[str],106 idea_count: int107) -> str:108 search_summary = "\n".join([f"- {title}: {url}" for title, url in search_links])109 include_games = any("game" in kw for kw in all_keywords)110 game_instruction = "Include at least two game-related ideas (e.g., quiz game, vending challenge)." if include_games else ""111 112 prompt = f"""113You are an expert event strategist for iboothme, a company offering creative experiences like AI photo booths, smart vending machines, audio booths, personalization stations, and immersive visual storytelling.114 115Below are full descriptions of three randomly selected iboothme products, to keep all ideas on-brand:116{product_info}117 118Based on the event description below, generate {idea_count} unique and diverse iboothme-powered event ideas.119Make sure that the syntax of the brand is always "iboothme" (all lowercase).120 121**Event Description:**122{paragraph}123 124**Inspiration from Related Ideas:**125{search_summary}126 127💡 **Your Task:**128Create ideas that are immersive, memorable, and creatively use iboothme's photo, video, and audio-based technologies. Do not use AR, VR, projection mapping, or other tech-heavy elements.129 130You must include:131- At least two game-related ideas132- Studio Ghibli-inspired visuals in one idea133- Personalized giveaways (e.g., custom t-shirts, stickers, Labibu dolls)134{game_instruction}135 136❗ Important:137- Avoid AR, VR, holograms, or projection domes138- Do not repeat photo‑booth formats139- Every idea should have a creative title140- Each idea should be described in a paragraph141- Immediately after, write a second paragraph describing the user journey flow142 143Return **only** the final ideas in markdown format.144"""145 resp = client.chat.completions.create(146 model="gpt-4",147 messages=[{"role": "user", "content": prompt}],148 temperature=0.95,149 max_tokens=1500150 )151 return resp.choices[0].message.content152 153# Main orchestration154def main_workflow(paragraph: str) -> str:155 print("main_workflow called with paragraph:", paragraph)156 if not paragraph.strip():157 print("No paragraph provided.")158 return "❌ Please enter an event description."159 160 # 1. Randomly pick 3 products from your catalog161 try:162 gadget_names = random.sample(list(PRODUCT_CATALOG.keys()), k=4)163 print("Randomly selected products:", gadget_names)164 product_info = get_product_descriptions(gadget_names)165 except Exception as e:166 print("Error selecting products:", e)167 return f"❌ Error selecting products: {e}"168 169 # 2. Gather keywords + optional web search170 try:171 base_kw = extract_keywords(paragraph)172 print("Extracted base keywords:", base_kw)173 links = search_similar_events_and_products_openai(base_kw)174 print("Found links:", links)175 link_kw = []176 for t, u in links:177 kws = extract_keywords_from_title_and_link(t, u)178 print(f"Extracted keywords from link ({t}, {u}):", kws)179 link_kw.extend(kws)180 all_kw = sorted(set(base_kw + link_kw))181 print("All keywords:", all_kw)182 except Exception as e:183 print("Error in keyword extraction or web search:", e)184 return f"❌ Error in keyword extraction or web search: {e}"185 186 # 3. Generate ideas187 try:188 idea_count = random.choice([5,6,7,8])189 print("Idea count:", idea_count)190 ideas_md = generate_event_ideas(paragraph, product_info, links, all_kw, idea_count)191 print("Generated ideas markdown.")192 except Exception as e:193 print("Error generating ideas:", e)194 return f"❌ Error generating ideas: {e}"195 196 # 4. Summarize top keywords197 summaries = []198 for kw in all_kw[:10]:199 try:200 print(f"Summarizing keyword: {kw}")201 r = client.chat.completions.create(202 model="gpt-4",203 messages=[{"role": "user", "content": f"Give a short one-line event idea description using the keyword: {kw}"}],204 temperature=0.6,205 max_tokens=60206 )207 desc = r.choices[0].message.content.strip()208 summaries.append(f"- **{kw.title()}**: {desc}")209 except Exception as e:210 print(f"Error summarizing keyword {kw}:", e)211 summaries.append(f"- **{kw.title()}**")212 213 summary_md = "\n".join(summaries)214 print("Returning final markdown output.")215 return f"""216🌐 **Relevant Keywords Summary:** 217{summary_md}218 219{ideas_md}220"""221# 8) Styling and Gradio interface222custom_theme = gr.themes.Base(223 primary_hue="purple",224 secondary_hue="purple",225 neutral_hue="gray"226).set(227 body_background_fill="white",228 block_background_fill="white",229 block_border_width="2px",230 block_border_color="#a18cd1",231 button_primary_background_fill="linear-gradient(90deg, #a18cd1 0%, #fbc2eb 100%)",232 button_primary_text_color="white",233 input_background_fill="white",234 input_border_color="#a18cd1"235)236 237custom_css = """238#iboothme-heading {239 font-weight: 900 !important;240 font-size: 2.5rem !important;241 background: linear-gradient(90deg, #a18cd1 0%, #fbc2eb 100%);242 -webkit-background-clip: text;243 -webkit-text-fill-color: black;244 margin-bottom: 0.5em;245 text-align: center;246 letter-spacing: 1px;247}248#desc-subheading {249 text-align: center;250 font-size: 1.15rem;251 font-weight: 500;252 color: #6d4fa7;253 margin-bottom: 2em;254}255.gradio-container { min-height: 100vh; background: white !important; }256.gr-box, .gr-input, .gr-button, .gr-markdown, .gr-textbox, .gr-column, .gr-row {257 border-radius: 18px !important;258}259#event-desc-box, #output-box {260 border: 2px solid #a18cd1 !important;261 box-shadow: 0 4px 24px 0 rgba(161,140,209,0.10) !important;262 background: white !important;263}264#generate-btn {265 font-weight: bold;266 font-size: 1.1rem;267 background: linear-gradient(90deg, #a18cd1 0%, #fbc2eb 100%) !important;268 color: white !important;269 border-radius: 12px !important;270 box-shadow: 0 2px 8px 0 rgba(161,140,209,0.10) !important;271 margin-top: 1.5em;272}273"""274 275with gr.Blocks(theme=custom_theme, css=custom_css, title="iboothme Event Ideation App") as demo:276 gr.Markdown(277 "<div id='iboothme-heading'>🎉 <b>iboothme Event Idea Generator</b></div>"278 "<div id='desc-subheading'>Describe your event goal and receive interactive, tech‑powered ideas!</div>"279 )280 with gr.Row():281 with gr.Column(scale=2):282 paragraph = gr.Textbox(283 label="📝 Describe Your Event (e.g. Women’s Day, Product Launch)",284 lines=4,285 elem_id="event-desc-box"286 )287 with gr.Column(scale=1, min_width=220):288 submit_btn = gr.Button("🚀 Generate Event Concepts", elem_id="generate-btn")289 output = gr.Markdown(elem_id="output-box")290 291 submit_btn.click(292 fn=main_workflow,293 inputs=[paragraph],294 outputs=output,295 show_progress=True296 )297 298demo.launch(inline=False, share=True)