Spaces:
Running
Running
| import streamlit as st | |
| import asyncio | |
| from workflows_v2 import startup_validation_workflow | |
| import time | |
| # Real-time progress tracking class | |
| class StreamlitProgressTracker: | |
| def __init__(self): | |
| self.progress_container = None | |
| self.status_text = None | |
| self.progress_bar = None | |
| self.log_container = None | |
| self.current_phase = 0 | |
| self.total_phases = 4 | |
| def setup_ui(self): | |
| self.progress_container = st.container() | |
| with self.progress_container: | |
| self.status_text = st.empty() | |
| self.progress_bar = st.progress(0) | |
| self.log_container = st.container() | |
| def update_progress(self, message): | |
| """Called by workflow for each progress update""" | |
| # Track phases based on message content | |
| if "PHASE 1:" in message: | |
| self.current_phase = 1 | |
| elif "PHASE 2:" in message: | |
| self.current_phase = 2 | |
| elif "PHASE 3:" in message: | |
| self.current_phase = 3 | |
| elif "PHASE 4:" in message: | |
| self.current_phase = 4 | |
| # Update progress bar | |
| progress = (self.current_phase / self.total_phases) * 100 | |
| self.progress_bar.progress(int(progress)) | |
| # Update status | |
| if "PHASE" in message and ":" in message: | |
| self.status_text.info(f"π {message}") | |
| elif "β " in message: | |
| self.status_text.success(f"{message}") | |
| else: | |
| self.status_text.info(f"π {message}") | |
| # Add to log (skip the "=" separator lines) | |
| if message and message.strip() and not all(c == '=' for c in message.strip()): | |
| with self.log_container: | |
| st.text(message) | |
| def complete(self): | |
| self.progress_bar.progress(100) | |
| self.status_text.success("β Validation completed!") | |
| def main(): | |
| st.set_page_config( | |
| page_title="StartupScan", | |
| page_icon="π", | |
| layout="wide", | |
| initial_sidebar_state="expanded" | |
| ) | |
| # Custom CSS for better styling | |
| st.markdown(""" | |
| <style> | |
| .main-header { | |
| font-size: 3rem; | |
| font-weight: bold; | |
| text-align: center; | |
| margin-bottom: 2rem; | |
| background: linear-gradient(90deg, #667eea 0%, #764ba2 100%); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| } | |
| .stButton > button { | |
| background: linear-gradient(90deg, #667eea 0%, #764ba2 100%); | |
| color: white; | |
| border: none; | |
| padding: 0.5rem 2rem; | |
| border-radius: 10px; | |
| font-weight: bold; | |
| } | |
| .result-section { | |
| background-color: #f8f9fa; | |
| padding: 2rem; | |
| border-radius: 15px; | |
| border-left: 5px solid #667eea; | |
| margin: 2rem 0; | |
| } | |
| .log-container { | |
| background-color: #f1f3f4; | |
| padding: 1rem; | |
| border-radius: 8px; | |
| font-family: monospace; | |
| font-size: 0.9rem; | |
| max-height: 300px; | |
| overflow-y: auto; | |
| border: 1px solid #ddd; | |
| } | |
| .header-buttons { | |
| display: flex; | |
| justify-content: center; | |
| gap: 15px; | |
| margin: 1.5rem 0; | |
| flex-wrap: wrap; | |
| } | |
| .header-btn { | |
| display: inline-block; | |
| padding: 12px 24px; | |
| background: linear-gradient(135deg, #17a2b8 0%, #138496 100%); | |
| color: white !important; | |
| text-decoration: none !important; | |
| border-radius: 25px; | |
| font-weight: 600; | |
| font-size: 0.95rem; | |
| transition: all 0.3s ease; | |
| box-shadow: 0 4px 15px rgba(23, 162, 184, 0.3); | |
| border: none; | |
| cursor: pointer; | |
| } | |
| .header-btn:hover { | |
| transform: translateY(-2px); | |
| box-shadow: 0 6px 20px rgba(23, 162, 184, 0.4); | |
| color: white !important; | |
| text-decoration: none !important; | |
| } | |
| .header-btn:visited { | |
| color: white !important; | |
| text-decoration: none !important; | |
| } | |
| .header-btn:link { | |
| color: white !important; | |
| text-decoration: none !important; | |
| } | |
| .header-btn.secondary { | |
| background: linear-gradient(135deg, #fd7e14 0%, #e55b13 100%); | |
| box-shadow: 0 4px 15px rgba(253, 126, 20, 0.3); | |
| color: white !important; | |
| } | |
| .header-btn.secondary:hover { | |
| box-shadow: 0 6px 20px rgba(253, 126, 20, 0.4); | |
| color: white !important; | |
| } | |
| .header-btn.secondary:visited { | |
| color: white !important; | |
| text-decoration: none !important; | |
| } | |
| .header-btn.secondary:link { | |
| color: white !important; | |
| text-decoration: none !important; | |
| } | |
| .header-btn .emoji { | |
| margin-right: 8px; | |
| } | |
| </style> | |
| """, unsafe_allow_html=True) | |
| # Header | |
| st.markdown('<h1 class="main-header">π StartupScan</h1>', unsafe_allow_html=True) | |
| # Subtitle with demo and guide links | |
| st.markdown(""" | |
| <div class="header-buttons"> | |
| <a href="https://demo.atla-ai.com/app/atla-demo-802mg?startDate=2025-08-05" target="_blank" class="header-btn"> | |
| <span class="emoji">π</span>View your traces on Atla | |
| </a> | |
| <a href="https://www.agno.com/?utm_source=atla&utm_medium=partner-content&utm_campaign=partner-technical&utm_content=atla" target="_blank" class="header-btn secondary"> | |
| <span class="emoji">π οΈ</span>Built with Agno | |
| </a> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| st.markdown("---") | |
| # Sidebar with information | |
| with st.sidebar: | |
| st.markdown("## π About This Tool") | |
| st.markdown(""" | |
| This agentic tool validates your startup idea through: | |
| π― **Idea Clarification Agent** | |
| - Originality assessment | |
| - Mission definition | |
| - Objective setting | |
| π **Market Research Agent** | |
| - TAM/SAM/SOM analysis | |
| - Customer segmentation | |
| - Market trends | |
| π’ **Competitor Analysis Agent** | |
| - SWOT analysis | |
| - Positioning assessment | |
| - Market gaps | |
| π **Validation Report Agent** | |
| - Executive summary | |
| - Strategic recommendations | |
| - Next steps | |
| """) | |
| st.markdown("---") | |
| st.markdown("π‘ **Tip:** Be as specific as possible about your startup idea for better results!") | |
| # Main content area | |
| col1, col2 = st.columns([2, 1]) | |
| with col1: | |
| st.markdown("## π‘ Tell us about your startup idea") | |
| # Input form | |
| with st.form("startup_form", clear_on_submit=False): | |
| # Get default value from session state if an example was selected | |
| default_value = st.session_state.get('selected_example', '') | |
| startup_idea = st.text_area( | |
| "Describe your startup idea in detail:", | |
| value=default_value, | |
| height=150, | |
| placeholder="e.g., A marketplace for Christmas Ornaments made from leather that connects artisans with customers looking for unique holiday decorations...", | |
| help="The more detailed your description, the better the validation will be." | |
| ) | |
| # Model selection toggle | |
| model_id = st.selectbox( | |
| "π€ Model to use:", | |
| options=["gpt-4o", "gpt-4o-mini", "o1", "o3-mini"], | |
| index=0, # Default to gpt-4o | |
| help="Choose which AI model to use for the validation analysis" | |
| ) | |
| submitted = st.form_submit_button("π Validate My Idea", use_container_width=True) | |
| with col2: | |
| st.markdown("## π― Quick Examples") | |
| st.markdown("*Click any example to populate the idea field*") | |
| examples = [ | |
| "AI-powered personal finance coach for millennials", | |
| "Sustainable packaging solutions for e-commerce", | |
| "Virtual reality fitness platform for remote workers", | |
| "Marketplace for local artisan food products", | |
| "Smart home energy optimization system" | |
| ] | |
| for i, example in enumerate(examples): | |
| if st.button(f"π‘ {example}", key=f"example_{i}", help="Click to populate the startup idea field"): | |
| st.session_state.selected_example = example | |
| st.rerun() | |
| # Clear the selected example from session state after form renders | |
| if 'selected_example' in st.session_state and startup_idea: | |
| if startup_idea == st.session_state.selected_example: | |
| # Example has been loaded into the form, show success message | |
| st.success(f"β Example loaded: {startup_idea[:50]}...") | |
| # Keep the example in session state until form is submitted | |
| # Process the form submission | |
| if submitted and startup_idea and model_id: | |
| # Clear the selected example when submitting | |
| if 'selected_example' in st.session_state: | |
| del st.session_state.selected_example | |
| st.markdown("---") | |
| st.markdown("## π Real-time Validation Progress") | |
| # Initialize progress tracker | |
| tracker = StreamlitProgressTracker() | |
| tracker.setup_ui() | |
| try: | |
| # Prepare the message | |
| message = "Please validate this startup idea with comprehensive market research and competitive analysis" | |
| # Run the workflow with real-time progress | |
| async def run_validation(): | |
| return await startup_validation_workflow.arun( | |
| message=message, | |
| startup_idea=startup_idea, | |
| model_id=model_id, # Pass the selected model | |
| progress_callback=tracker.update_progress # Pass the real-time callback | |
| ) | |
| # Execute the async workflow | |
| result = asyncio.run(run_validation()) | |
| # Complete progress | |
| tracker.complete() | |
| # Display results with improved formatting | |
| st.markdown("---") | |
| st.markdown("## π Validation Results") | |
| # Extract clean content from WorkflowRunResponse | |
| validation_content = "" | |
| if hasattr(result, 'content') and result.content: | |
| validation_content = result.content | |
| elif hasattr(result, 'response') and result.response: | |
| validation_content = result.response | |
| else: | |
| validation_content = str(result) | |
| # Clean up content if needed | |
| if validation_content: | |
| validation_content = validation_content.replace('\\n', '\n') | |
| validation_content = validation_content.replace('\\"', '"') | |
| # Display in a formatted code block for consistent appearance | |
| st.code(validation_content, language="markdown") | |
| # Add download button for the report | |
| st.download_button( | |
| label="π₯ Download Report", | |
| data=validation_content, | |
| file_name=f"startup_validation_{startup_idea[:30].replace(' ', '_')}.md", | |
| mime="text/markdown" | |
| ) | |
| except Exception as e: | |
| st.error(f"β An error occurred during validation: {str(e)}") | |
| st.error("Please check your environment variables and try again.") | |
| # Display error details in expander | |
| with st.expander("π Error Details"): | |
| st.code(str(e)) | |
| elif submitted and not startup_idea: | |
| st.warning("β οΈ Please enter a startup idea before submitting.") | |
| # Footer | |
| st.markdown("---") | |
| st.markdown(""" | |
| <div style='text-align: center; color: #666; font-size: 0.9rem;'> | |
| <p>π¬ Powered by AI agents and comprehensive market research</p> | |
| <p>β οΈ This validation is for informational purposes only. Conduct additional due diligence before making investment decisions.</p> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| if __name__ == "__main__": | |
| main() |