Spaces:
Sleeping
Sleeping
| 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") |