Harshdhsvguyt's picture
Update app.py
19be839 verified
import streamlit as st
import os
import json
import uuid
from datetime import datetime, timezone
from pathlib import Path
from providers.pollinations_provider import PollinationsProvider
from providers.hf_provider import HuggingFaceProvider
from providers.stub_provider import StubProvider
from dotenv import load_dotenv
load_dotenv()
# ==============================================
# PATHS & CONFIGURATION
# ==============================================
BASE_DIR = Path(__file__).parent
STORAGE_DIR = BASE_DIR / "storage"
PROJECTS_DIR = BASE_DIR / "projects"
PROMPT_HISTORY = BASE_DIR / "prompt_history.json"
FEEDBACK_DB = BASE_DIR / "feedback_db.json"
# Create directories
STORAGE_DIR.mkdir(exist_ok=True)
PROJECTS_DIR.mkdir(exist_ok=True)
# Initialize JSON files
if not PROMPT_HISTORY.exists():
PROMPT_HISTORY.write_text("[]")
if not FEEDBACK_DB.exists():
FEEDBACK_DB.write_text("[]")
# ==============================================
# PROVIDERS CONFIGURATION
# ==============================================
PROVIDERS = {
"FLUX (Pollinations - FREE)": ("pollinations", "flux"),
"Turbo (Pollinations - FREE)": ("pollinations", "turbo"),
"Stable Diffusion 1.4 (HF)": ("huggingface", "CompVis/stable-diffusion-v1-4"),
"Stable Diffusion 1.5 (HF)": ("huggingface", "runwayml/stable-diffusion-v1-5"),
"Demo Mode": ("stub", "demo"),
}
VIDEO_PROVIDERS = {
"RunwayML Gen-2 β€” Demo": ("stub", "runway_gen2"),
"Stable Video Diffusion β€” Demo": ("stub", "svd"),
"Pika Labs β€” Coming Soon": ("stub", "pika"),
}
MODEL_3D_PROVIDERS = {
"Shap-E (OpenAI) β€” Demo": ("stub", "shap_e"),
"Point-E β€” Demo": ("stub", "point_e"),
"DreamFusion β€” Coming Soon": ("stub", "dreamfusion"),
}
def get_provider(kind, model):
"""Factory function to get appropriate provider"""
if kind == "huggingface":
return HuggingFaceProvider(model=model)
elif kind == "pollinations":
return PollinationsProvider(model=model)
elif kind == "stub":
return StubProvider(name=model)
else:
return StubProvider(name="Unknown")
# ==============================================
# HELPER FUNCTIONS
# ==============================================
def save_to_history(asset_type, prompt, negative_prompt, provider, model_name, results, metadata=None):
"""Save generation to history"""
try:
history_content = PROMPT_HISTORY.read_text()
history = json.loads(history_content) if history_content else []
except json.JSONDecodeError:
history = []
entry = {
"id": uuid.uuid4().hex,
"asset_type": asset_type,
"prompt": prompt,
"negative_prompt": negative_prompt,
"provider": provider,
"model_name": model_name,
"timestamp": datetime.now(timezone.utc).isoformat(),
"results": results,
"metadata": metadata or {},
"feedback": []
}
history.insert(0, entry)
PROMPT_HISTORY.write_text(json.dumps(history, indent=2))
return entry["id"]
def add_feedback(entry_id, feedback_text, rating):
"""Add feedback to a generation"""
try:
history = json.loads(PROMPT_HISTORY.read_text())
except json.JSONDecodeError:
return
for entry in history:
if entry["id"] == entry_id:
entry["feedback"].append({
"text": feedback_text,
"rating": rating,
"timestamp": datetime.now(timezone.utc).isoformat()
})
PROMPT_HISTORY.write_text(json.dumps(history, indent=2))
def create_project(name, brief):
"""Create a new project"""
project = {
"id": uuid.uuid4().hex,
"name": name,
"brief": brief,
"created_at": datetime.now(timezone.utc).isoformat(),
"assets": []
}
project_file = PROJECTS_DIR / f"{project['id']}.json"
project_file.write_text(json.dumps(project, indent=2))
return project
# ==============================================
# STREAMLIT UI CONFIGURATION
# ==============================================
st.set_page_config(
page_title="AI Studio β€” Creative Workflow Platform",
layout="wide",
initial_sidebar_state="expanded"
)
# Custom CSS
st.markdown("""
<style>
.stTabs [data-baseweb="tab-list"] {
gap: 24px;
}
.stTabs [data-baseweb="tab"] {
height: 50px;
padding-left: 20px;
padding-right: 20px;
}
.asset-card {
border: 1px solid #ddd;
border-radius: 8px;
padding: 16px;
margin: 8px 0;
}
</style>
""", unsafe_allow_html=True)
# ==============================================
# SIDEBAR
# ==============================================
st.sidebar.title("🎨 AI Studio Platform")
st.sidebar.markdown("### Creative Workflow Builder")
# Project selection
st.sidebar.markdown("---")
st.sidebar.subheader("Current Project")
project_name = st.sidebar.text_input("Project Name", value="Luxury Real Estate Campaign")
project_brief = st.sidebar.text_area("Creative Brief",
value="High-end real estate marketing campaign targeting luxury buyers. Focus on premium aesthetics, lifestyle, and architectural excellence.")
if st.sidebar.button("Create New Project"):
proj = create_project(project_name, project_brief)
st.sidebar.success(f"Project created: {proj['name']}")
# ==============================================
# EXCEL UPLOAD MODULE
# ==============================================
st.sidebar.markdown("---")
st.sidebar.subheader("πŸ“Š Excel Batch Import")
uploaded_file = st.sidebar.file_uploader("Upload Excel", type=['xlsx', 'xls'])
if uploaded_file is not None:
try:
from utils.prompt_enhancer import load_excel_to_projects
# Save uploaded file temporarily
temp_path = STORAGE_DIR / "temp_upload.xlsx"
with open(temp_path, "wb") as f:
f.write(uploaded_file.getbuffer())
# Load projects
projects = load_excel_to_projects(temp_path)
st.session_state['uploaded_projects'] = projects
st.sidebar.success(f"βœ… Loaded {len(projects)} projects")
# Project selector
if projects:
project_names = [f"{p.get('org_name', 'Unknown')} - {p.get('asset_type', 'N/A')}"
for p in projects]
selected_idx = st.sidebar.selectbox(
"Select Project",
range(len(project_names)),
format_func=lambda x: project_names[x]
)
st.session_state['selected_project'] = projects[selected_idx]
st.sidebar.info(f"**Prompt:** {projects[selected_idx].get('prompt', '')[:50]}...")
except Exception as e:
st.sidebar.error(f"Error loading Excel: {e}")
# ==============================================
# MAIN TABS
# ==============================================
tab1, tab2, tab3, tab4, tab5, tab6, tab7 = st.tabs([
"🎯 Ideation Board",
"πŸ–ΌοΈ Image Generator",
"🎬 Video Generator",
"🧱 3D Creator",
"πŸ“ Library",
"πŸ“œ History & Feedback",
"πŸ”„ Pipeline & Export"
])
# ==============================================
# TAB 1: IDEATION BOARD
# ==============================================
with tab1:
st.header("🎯 Ideation & Prompt Board")
st.markdown("**Brainstorm and refine prompts before generation**")
col1, col2 = st.columns([2, 1])
with col1:
st.subheader("Prompt Ideas")
# Preset templates for luxury real estate
template = st.selectbox("Load Template", [
"Custom",
"Luxury Villa Exterior",
"Penthouse Interior",
"Aerial Property Tour",
"3D Furniture Asset"
])
if template == "Luxury Villa Exterior":
idea_prompt = "Ultra-modern luxury villa at golden hour, infinity pool with crystal reflections, sleek glass facade, lush tropical landscaping, ocean view, photorealistic, architectural photography"
elif template == "Penthouse Interior":
idea_prompt = "Spacious penthouse interior, floor-to-ceiling windows, panoramic city skyline, designer furniture, marble floors, ambient lighting, wide-angle, luxury lifestyle"
elif template == "Aerial Property Tour":
idea_prompt = "Cinematic aerial drone footage of modern beachfront estate, golden hour lighting, smooth gimbal motion, reveal shot from ocean to property"
elif template == "3D Furniture Asset":
idea_prompt = "High-detail 3D model of contemporary outdoor lounge chair, teak wood frame, white weather-resistant cushions, for architectural visualization"
else:
idea_prompt = ""
# Check if project is selected from Excel
if 'selected_project' in st.session_state:
proj = st.session_state['selected_project']
idea_prompt = proj.get('prompt', idea_prompt)
st.info(f"πŸ“‹ Auto-filled from: {proj.get('org_name', 'Excel')}")
idea_text = st.text_area("Prompt Concept", value=idea_prompt, height=150, key="idea_text")
# PROMPT ENHANCER
if idea_text and len(idea_text) > 10:
st.markdown("### πŸš€ Prompt Enhancer")
# Helper to simulate enhancer if utils missing
try:
from utils.prompt_enhancer import enhance_prompt
enhanced = enhance_prompt(idea_text)
except ImportError:
enhanced = {
"Cinematic": f"Cinematic shot of {idea_text}, 8k, highly detailed",
"Photorealistic": f"Photorealistic photo of {idea_text}, canon eos r5, 50mm",
"Artistic": f"Digital art of {idea_text}, trending on artstation"
}
enhanced_choice = st.radio(
"Select Enhanced Version:",
list(enhanced.keys()),
key="idea_enhancer"
)
st.text_area(
"Enhanced Prompt Preview",
value=enhanced[enhanced_choice],
height=100,
disabled=True,
key="idea_enhanced_preview"
)
st.session_state['ideation_final_prompt'] = enhanced[enhanced_choice]
# Prompt versioning
st.markdown("**Prompt Versions**")
version = st.number_input("Version", min_value=1, value=1, step=1)
if st.button("Save to Prompt Library"):
st.success("Prompt saved to library with version tracking!")
with col2:
st.subheader("Prompt Strategy")
st.markdown("""
**Elements to Include:**
- Subject/Scene
- Lighting conditions
- Camera angle
- Style keywords
- Quality modifiers
**Best Practices:**
- Be specific about materials
- Mention atmosphere/mood
- Include technical details
- Specify use case
""")
st.markdown("---")
st.info("πŸ’‘ **Tip:** Test prompts with image generator first before scaling to video/3D")
# ==============================================
# TAB 2: IMAGE GENERATOR
# ==============================================
with tab2:
st.header("πŸ–ΌοΈ Image Generator")
col1, col2 = st.columns([3, 1])
with col1:
selected_model = st.selectbox("Select Model", list(PROVIDERS.keys()), key="img_model")
kind, model_name = PROVIDERS[selected_model]
# Auto-fill from Excel if available
default_prompt = "Ultra-modern luxury villa at sunset, glass faΓ§ade, infinity pool, palm trees, ocean view, photorealistic, high detail"
if 'selected_project' in st.session_state:
proj = st.session_state['selected_project']
if proj.get('asset_type', '').lower() in ['image', 'img']:
default_prompt = proj.get('prompt', default_prompt)
st.info(f"πŸ“‹ Auto-filled from: {proj.get('org_name', 'Excel')}")
prompt = st.text_area(
"Image Prompt",
height=120,
value=default_prompt,
key="img_prompt"
)
# PROMPT ENHANCER - MANDATORY
final_prompt = prompt # Default
if prompt and len(prompt) > 10:
st.markdown("### πŸš€ Select Enhanced Prompt (Required)")
try:
from utils.prompt_enhancer import enhance_prompt
enhanced = enhance_prompt(prompt)
except ImportError:
enhanced = {
"Cinematic": f"Cinematic shot of {prompt}, 8k, highly detailed",
"Photorealistic": f"Photorealistic photo of {prompt}, canon eos r5, 50mm",
"Artistic": f"Digital art of {prompt}, trending on artstation"
}
# Show all three options with their full text
st.markdown("**Choose one enhancement:**")
for idx, (title, enhanced_text) in enumerate(enhanced.items(), 1):
st.markdown(f"**Option {idx}: {title}**")
st.info(enhanced_text)
enhanced_choice = st.radio(
"Select your preferred version:",
list(enhanced.keys()),
key="img_enhancer",
label_visibility="collapsed"
)
final_prompt = enhanced[enhanced_choice]
st.success(f"βœ… Selected: **{enhanced_choice}**")
col_neg, col_num = st.columns(2)
with col_neg:
negative_prompt = st.text_input("Negative Prompt", value="low quality, blurry, distorted", key="img_neg")
with col_num:
n_images = st.slider("Number of Images", 1, 4, 2, key="img_count")
# Advanced settings
with st.expander("Advanced Settings"):
col_adv1, col_adv2 = st.columns(2)
with col_adv1:
steps = st.slider("Inference Steps", 20, 50, 30)
guidance = st.slider("Guidance Scale", 5.0, 15.0, 7.5, 0.5)
with col_adv2:
width = st.selectbox("Width", [512, 768, 1024], index=2)
height = st.selectbox("Height", [512, 768, 1024], index=2)
if st.button("🎨 Generate Images", type="primary", key="gen_img"):
provider = get_provider(kind, model_name)
try:
with st.spinner(f"Generating images using {selected_model}..."):
outputs = provider.generate(
final_prompt,
negative_prompt,
n_images=n_images,
steps=steps,
guidance=guidance
)
# Save generated images
saved = []
for img in outputs:
fname = f"img_{uuid.uuid4().hex[:8]}.png"
fpath = STORAGE_DIR / fname
img.save(fpath)
saved.append(str(fpath))
# Save to history
entry_id = save_to_history(
"image", final_prompt, negative_prompt, selected_model, model_name,
saved, {"steps": steps, "guidance": guidance, "resolution": f"{width}x{height}"}
)
st.success(f"βœ… Generated {len(saved)} images!")
# Display results
cols = st.columns(min(len(saved), 3))
for idx, (c, path) in enumerate(zip(cols, saved)):
with c:
# FIXED: Changed use_container_width to use_column_width
c.image(path, use_column_width=True)
c.download_button(
"Download",
data=open(path, "rb"),
file_name=f"image_{idx+1}.png",
mime="image/png",
key=f"dl_img_{idx}"
)
except Exception as e:
st.error(f"❌ Generation failed: {e}")
with col2:
st.subheader("Quick Guide")
st.markdown("""
**Image Prompt Tips:**
1. **Composition**
- Camera angle
- Framing
- Rule of thirds
2. **Lighting**
- Time of day
- Light direction
- Atmosphere
3. **Style**
- Photorealistic
- Architectural
- Cinematic
4. **Quality**
- High detail
- 8K resolution
- Professional
""")
# ==============================================
# TAB 3: VIDEO GENERATOR
# ==============================================
with tab3:
st.header("🎬 Video Generator")
st.info("🚧 Video generation pipeline - Currently in demo mode")
col1, col2 = st.columns([3, 1])
with col1:
video_model = st.selectbox("Select Video Model", list(VIDEO_PROVIDERS.keys()))
# Auto-fill from Excel if available
default_video_prompt = "Aerial drone video fly-through of modern seaside estate, golden hour, lush landscaping, cinematic, smooth motion, 10 seconds"
if 'selected_project' in st.session_state:
proj = st.session_state['selected_project']
if proj.get('asset_type', '').lower() == 'video':
default_video_prompt = proj.get('prompt', default_video_prompt)
st.info(f"πŸ“‹ Auto-filled from: {proj.get('org_name', 'Excel')}")
video_prompt = st.text_area(
"Video Prompt",
height=120,
value=default_video_prompt,
key="vid_prompt"
)
# PROMPT ENHANCER - MANDATORY
final_video_prompt = video_prompt # Default
if video_prompt and len(video_prompt) > 10:
st.markdown("### πŸš€ Select Enhanced Prompt (Required)")
try:
from utils.prompt_enhancer import enhance_prompt
enhanced = enhance_prompt(video_prompt)
except ImportError:
enhanced = {
"Cinematic Motion": f"{video_prompt}, cinematic camera movement, smooth stabilization",
"Dynamic Action": f"{video_prompt}, dynamic angle, fast paced",
"Slow Mo": f"{video_prompt}, slow motion, 60fps, detailed"
}
enhanced_choice = st.radio(
"Choose one enhancement:",
list(enhanced.keys()),
key="vid_enhancer"
)
final_video_prompt = enhanced[enhanced_choice]
st.text_area(
"Final Prompt to Generate",
value=final_video_prompt,
height=80,
disabled=True,
key="vid_final_preview"
)
col_dur, col_fps = st.columns(2)
with col_dur:
duration = st.slider("Duration (seconds)", 5, 30, 10)
with col_fps:
fps = st.selectbox("FPS", [24, 30, 60], index=1)
motion_intensity = st.slider("Motion Intensity", 1, 10, 5)
if st.button("🎬 Generate Video", type="primary"):
st.warning("Video generation requires RunwayML or Stable Video Diffusion API. Demo mode active.")
st.info(f"**Would generate with prompt:** {final_video_prompt}")
with col2:
st.subheader("Video Strategy")
st.markdown("""
**Key Elements:**
- Camera movement
- Shot duration
- Transitions
- Pacing
**Types:**
- Property walkthrough
- Aerial tour
- Detail shots
- Time-lapse
""")
# ==============================================
# TAB 4: 3D CREATOR
# ==============================================
with tab4:
st.header("🧱 3D Asset Creator")
st.info("🚧 3D generation pipeline - Currently in demo mode")
col1, col2 = st.columns([3, 1])
with col1:
model_3d = st.selectbox("Select 3D Model", list(MODEL_3D_PROVIDERS.keys()))
asset_prompt = st.text_area(
"3D Asset Prompt",
height=120,
value="High-detail 3D model of contemporary outdoor lounge chair, teak wood and white cushions, clean geometry, for architectural visualization",
key="3d_prompt"
)
col_poly, col_tex = st.columns(2)
with col_poly:
poly_count = st.selectbox("Poly Count", ["Low (5K)", "Medium (20K)", "High (50K)"])
with col_tex:
texture_res = st.selectbox("Texture Resolution", ["1K", "2K", "4K"])
export_format = st.multiselect(
"Export Formats",
["FBX", "OBJ", "GLTF", "USD", "Blender (.blend)"],
default=["FBX", "Blender (.blend)"]
)
if st.button("🧱 Generate 3D Asset", type="primary"):
st.warning("3D generation requires Shap-E or similar 3D generation API. Demo mode active.")
with st.spinner("Simulating 3D generation..."):
import time
time.sleep(2)
st.success("βœ… 3D asset generation placeholder complete!")
st.info("**Blender Integration:** Assets can be exported to `.blend` format for direct import")
with col2:
st.subheader("3D Workflow")
st.markdown("""
**Pipeline:**
1. Generate base mesh
2. Apply textures
3. Optimize topology
4. Export to Blender
5. Final rendering
**Blender Integration:**
- Direct .blend export
- Material nodes
- Scene composition
""")
# ==============================================
# TAB 5: LIBRARY
# ==============================================
with tab5:
st.header("πŸ“ Project Library & Asset Management")
# Filter options
col_f1, col_f2, col_f3 = st.columns(3)
with col_f1:
filter_type = st.selectbox("Asset Type", ["All", "Images", "Videos", "3D Models"])
with col_f2:
sort_by = st.selectbox("Sort By", ["Newest First", "Oldest First", "Most Feedback"])
with col_f3:
st.write("") # Spacer
show_grid = st.checkbox("Grid View", value=True)
files = sorted(STORAGE_DIR.glob("*.png"), reverse=True)
if not files:
st.info("No generated assets yet. Start creating in the generator tabs!")
else:
if show_grid:
# Grid layout
cols_per_row = 3
for i in range(0, len(files), cols_per_row):
cols = st.columns(cols_per_row)
for idx, f in enumerate(files[i:i+cols_per_row]):
with cols[idx]:
# FIXED: Changed use_container_width to use_column_width
st.image(str(f), use_column_width=True)
st.caption(f.name)
col_dl, col_fb = st.columns(2)
with col_dl:
st.download_button(
"⬇️",
data=open(f, "rb"),
file_name=f.name,
mime="image/png",
key=f"lib_dl_{f.name}"
)
with col_fb:
if st.button("πŸ’¬", key=f"lib_fb_{f.name}"):
st.info("Feedback panel would open here")
else:
# List layout
for f in files:
col1, col2, col3 = st.columns([3, 1, 1])
with col1:
# FIXED: Changed width parameter logic for compatibility
st.image(str(f), width=300)
with col2:
st.write(f"**{f.name}**")
st.caption(f"Size: {f.stat().st_size // 1024}KB")
with col3:
st.download_button(
"Download",
data=open(f, "rb"),
file_name=f.name,
mime="image/png",
key=f"list_dl_{f.name}"
)
# ==============================================
# TAB 6: HISTORY & FEEDBACK
# ==============================================
with tab6:
st.header("πŸ“œ Prompt History & Feedback System")
try:
history = json.loads(PROMPT_HISTORY.read_text())
except json.JSONDecodeError:
history = []
if not history:
st.info("No generation history yet.")
else:
for item in history:
# Handle both old and new format
asset_type = item.get('asset_type', 'image').upper()
with st.expander(f"{asset_type}: {item['prompt'][:80]}...", expanded=False):
col1, col2 = st.columns([2, 1])
with col1:
st.markdown(f"**Prompt:** {item['prompt']}")
st.caption(f"Provider: {item['provider']} | {item['timestamp']}")
if item.get("negative_prompt"):
st.markdown(f"**Negative:** {item['negative_prompt']}")
# Show results
if item["results"]:
result_cols = st.columns(min(len(item['results']), 3))
for idx, (col, path) in enumerate(zip(result_cols, item['results'])):
if Path(path).exists():
# FIXED: Changed use_container_width to use_column_width
col.image(path, use_column_width=True)
with col2:
st.markdown("**Feedback & Iteration**")
# Add feedback
rating = st.select_slider(
"Quality Rating",
options=[1, 2, 3, 4, 5],
value=3,
key=f"rating_{item['id']}"
)
feedback_text = st.text_area(
"Feedback Notes",
placeholder="What would improve this?",
key=f"feedback_{item['id']}",
height=100
)
if st.button("Submit Feedback", key=f"submit_{item['id']}"):
add_feedback(item['id'], feedback_text, rating)
st.success("Feedback saved!")
# Show existing feedback
if item.get("feedback"):
st.markdown("**Previous Feedback:**")
for fb in item["feedback"]:
st.caption(f"⭐ {fb['rating']}/5: {fb['text']}")
st.markdown("---")
# ==============================================
# TAB 7: PIPELINE & EXPORT
# ==============================================
with tab7:
st.header("πŸ”„ Integration Pipeline & Export")
st.markdown("""
## Workflow: Concept to Campaign-Ready Asset
This pipeline shows how assets flow from ideation to final delivery:
""")
# Visual workflow
st.markdown("""
```
1. Creative Brief Submission
↓
2. Ideation Board β†’ Prompt Refinement β†’ Version Control
↓
3. Asset Generation (Image/Video/3D)
↓
4. Team Review & Feedback Loop
↓
5. Iteration & Refinement
↓
6. Export & Integration:
β€’ Images β†’ Marketing materials
β€’ 3D Assets β†’ Blender for rendering
β€’ 3D Assets β†’ Unity for interactive tours
β€’ Videos β†’ Campaign distribution
↓
7. Final Review & Campaign Launch
```
""")
st.markdown("---")
# Export options
st.subheader("Export & Integration Tools")
col1, col2 = st.columns(2)
with col1:
st.markdown("### Blender Integration")
st.code("""
# Python script for Blender export
import bpy
def export_to_blender(asset_path):
bpy.ops.import_scene.fbx(filepath=asset_path)
# Set up materials, lighting
bpy.ops.wm.save_as_mainfile(
filepath="scene_output.blend"
)
""", language="python")
if st.button("Generate Blender Export Script"):
st.download_button(
"Download Script",
data="""import bpy\n# Your export script""",
file_name="blender_export.py",
mime="text/plain"
)
with col2:
st.markdown("### Unity Integration")
st.code("""
// C# script for Unity import
using UnityEngine;
public class AssetImporter : MonoBehaviour
{
void ImportAsset(string path) {
GameObject asset =
AssetDatabase.LoadAssetAtPath<GameObject>(path);
Instantiate(asset);
}
}
""", language="csharp")
if st.button("Generate Unity Script"):
st.download_button(
"Download Script",
data="""using UnityEngine;\n// Your import script""",
file_name="AssetImporter.cs",
mime="text/plain"
)
st.markdown("---")
# API Integration pseudocode
st.subheader("API Workflow (Pseudocode)")
st.code("""
def generate_campaign_asset(brief, prompt_type, iterations=3):
\"\"\"
Complete workflow from brief to final asset
\"\"\"
# Step 1: Create prompt from brief
prompt = create_prompt(brief, prompt_type)
# Step 2: Generate initial asset
ai_output = call_ai_tool(prompt)
# Step 3: Iteration loop with feedback
for i in range(iterations):
feedback = get_team_feedback(ai_output)
if feedback['approved']:
break
prompt = refine_prompt(prompt, feedback)
ai_output = call_ai_tool(prompt)
# Step 4: Export based on asset type
if prompt_type == "3D":
exported = import_to_blender(ai_output)
elif prompt_type == "video":
exported = save_to_library(ai_output)
elif prompt_type == "image":
exported = optimize_for_web(ai_output)
# Step 5: Save to project
save_to_project(brief['project_id'], exported)
return exported
# Example usage
brief = {
'project_id': 'luxury_realestate_q4',
'description': 'High-end villa marketing campaign',
'target_audience': 'Ultra-high-net-worth individuals',
'style': 'Photorealistic, cinematic'
}
image = generate_campaign_asset(brief, 'image')
video = generate_campaign_asset(brief, 'video')
model_3d = generate_campaign_asset(brief, '3D')
""", language="python")
st.markdown("---")
st.success("βœ… Complete workflow pipeline ready for presentation!")
# ==============================================
# FOOTER
# ==============================================
st.sidebar.markdown("---")
st.sidebar.markdown("### πŸ“Š System Status")
st.sidebar.success("βœ… Image Generation: Active")
st.sidebar.warning("⚠️ Video Generation: Demo Mode")
st.sidebar.warning("⚠️ 3D Generation: Demo Mode")
st.sidebar.info("πŸ’‘ Tip: Complete image pipeline first, then add video/3D APIs")