import gradio as gr import asyncio import os import time from app.models.pitch_input import PitchInput, InvestorType from app.services.openai_agents import OpenAIAgentService from app.utils.aws_storage import AWSS3Storage # Initialize agent service agent_service = OpenAIAgentService() # Initialize AWS S3 storage s3_storage = AWSS3Storage() # Define a function to process the form data async def generate_pitch( investor_type, startup_name, problem_description, solution_description, target_customer, business_model, current_stage, competitors, differentiators, market_impact, funding_details, progress=gr.Progress() ): # Create PitchInput object pitch_input = PitchInput( investor_type=InvestorType(investor_type), startup_name=startup_name, problem_description=problem_description, solution_description=solution_description, target_customer=target_customer, business_model=business_model, current_stage=current_stage, competitors=competitors, differentiators=differentiators, market_impact=market_impact, funding_details=funding_details ) # Process through the RAG pipeline with progress updates progress(0, "Starting the RAG pipeline...") # Step 1: Market insights from Perplexity progress(0.1, "Step 1/3: Gathering market insights from Perplexity...") # Step 2: Business angle from Gemini progress(0.4, "Step 2/3: Refining business angle with Gemini...") # Step 3: Generate pitch with OpenAI progress(0.7, "Step 3/3: Generating pitch scripts with OpenAI...") # Generate the pitch based on investor type if investor_type == "Angel Investor": pitch_output = await agent_service.create_angel_investor_agent(pitch_input) else: pitch_output = await agent_service.create_vc_investor_agent(pitch_input) progress(0.9, "Saving pitch data to AWS S3...") # Format competitors for display competitors_md = "## Competitor Analysis\n\n" for competitor in pitch_output.identified_competitors: competitors_md += f"### {competitor.name}\n" competitors_md += f"{competitor.description}\n\n" competitors_md += "**Strengths:**\n" for strength in competitor.strengths: competitors_md += f"- {strength}\n" competitors_md += "\n**Weaknesses:**\n" for weakness in competitor.weaknesses: competitors_md += f"- {weakness}\n" competitors_md += "\n\n" # Format market insights market_insights_md = "## Market Insights\n\n" + pitch_output.market_insights if pitch_output.market_insights else "" # Save to AWS S3 storage_result = s3_storage.save_pitch_data( script_id=pitch_output.script_id, elevator_pitch=pitch_output.elevator_pitch, full_pitch=pitch_output.full_pitch, competitors_data=competitors_md, market_insights=market_insights_md ) # Update script_id display with storage status script_id_display = f"Script ID: {pitch_output.script_id}" if storage_result["success"]: script_id_display += f" (Saved to S3: {storage_result['s3_path']})" else: script_id_display += f" (Warning: Failed to save to S3 - {storage_result['message']})" progress(1.0, "Pitch generation complete!") # Return the results return ( script_id_display, pitch_output.elevator_pitch, pitch_output.full_pitch, competitors_md, market_insights_md ) # Define the Gradio interface with gr.Blocks(title="StartupPal - Pitch Generator", theme=gr.themes.Monochrome()) as demo: gr.Markdown("# StartupPal RAG Module") gr.Markdown("### Generate tailored startup pitch scripts with our AI pipeline") with gr.Tabs(): with gr.TabItem("Generate Pitch"): with gr.Row(): with gr.Column(scale=1): gr.Markdown("## Startup Information") gr.Markdown("Fill in the details about your startup to generate a customized pitch") investor_type = gr.Radio( ["Angel Investor", "Venture Capitalist"], label="1. Investor Type", info="Who is this pitch for?", value="Angel Investor" ) startup_name = gr.Textbox( label="2. Startup Name", info="The name of your startup", placeholder="EcoShip" ) problem_description = gr.Textbox( label="3. Problem Description", info="What problem does your startup solve?", placeholder="The shipping industry contributes significantly to global carbon emissions with inefficient packaging and routes.", lines=3 ) solution_description = gr.Textbox( label="4. Solution Description", info="How does your product or solution work?", placeholder="Our platform uses AI to optimize packaging dimensions and shipping routes to reduce carbon footprint.", lines=3 ) target_customer = gr.Textbox( label="5. Target Customer", info="Who are your target customers?", placeholder="E-commerce businesses that ship more than 1000 packages monthly" ) business_model = gr.Textbox( label="6. Business Model", info="How will you make money?", placeholder="SaaS subscription with tiered pricing based on shipping volume" ) with gr.Column(scale=1): gr.Markdown("## Additional Details") current_stage = gr.Textbox( label="7. Current Stage", info="What stage is your startup at?", placeholder="MVP with 3 beta customers" ) competitors = gr.Textbox( label="8. Competitors", info="Who are your main competitors?", placeholder="ShipGreen, EcoLogistics, Traditional shipping optimizers", lines=2 ) differentiators = gr.Textbox( label="9. Differentiators", info="What makes your solution better?", placeholder="Our solution combines both packaging and route optimization, while competitors focus on only one aspect", lines=3 ) market_impact = gr.Textbox( label="10. Market Impact", info="What impact will your startup have?", placeholder="We aim to reduce e-commerce shipping emissions by 30% within 5 years", lines=2 ) funding_details = gr.Textbox( label="11. Funding Details", info="How much funding are you seeking and for what?", placeholder="$500K for engineering team expansion and marketing to initial target segments" ) generate_btn = gr.Button("Generate Pitch", variant="primary") with gr.Row(): with gr.Column(): script_id = gr.Textbox(label="Script ID", interactive=False) gr.Markdown("## Elevator Pitch (1 minute)") elevator_pitch = gr.Textbox(lines=6, label="", interactive=False) gr.Markdown("## Full Pitch (3 minutes)") full_pitch = gr.Textbox(lines=15, label="", interactive=False) gr.Markdown("## Analysis") with gr.Accordion("Competitor Analysis", open=False): competitors_md = gr.Markdown() with gr.Accordion("Market Insights", open=False): market_insights_md = gr.Markdown() with gr.TabItem("View Saved Pitches"): gr.Markdown("## Retrieve Saved Pitches") with gr.Row(): script_id_input = gr.Textbox( label="Script ID", placeholder="Enter a Script ID to retrieve", interactive=True ) retrieve_btn = gr.Button("Retrieve Pitch", variant="primary") with gr.Row(): retrieved_status = gr.Textbox(label="Status", interactive=False) with gr.Row(): with gr.Column(): gr.Markdown("## Retrieved Elevator Pitch") retrieved_elevator_pitch = gr.Textbox(lines=6, label="", interactive=False) gr.Markdown("## Retrieved Full Pitch") retrieved_full_pitch = gr.Textbox(lines=15, label="", interactive=False) with gr.Accordion("Additional Data", open=False): retrieved_additional_data = gr.JSON() with gr.TabItem("About"): gr.Markdown(""" # StartupPal RAG Module This application uses a multi-model Retrieval-Augmented Generation (RAG) pipeline to generate high-quality startup pitch scripts: 1. **Perplexity API** - Retrieves market insights and competitor analysis 2. **Gemini API** - Refines business positioning and strategy 3. **OpenAI API** - Generates the final pitch scripts using the aggregated data ## How it works ``` Input: Startup details │ ├─> Perplexity API │ └─> Market research & competitor analysis │ │ │ ├─> Gemini API │ │ └─> Business angle refinement & market positioning │ │ │ │ │ └─> OpenAI API │ │ └─> Final pitch script generation │ Output: Elevator pitch & full presentation scripts ``` ## API Model Configuration The models used in this application can be customized in the `.env` file: ``` OPENAI_MODEL=gpt-4o GEMINI_MODEL=gemini-1.5-pro ``` ## Data Storage All generated pitches are automatically saved to an AWS S3 bucket for later retrieval. You can access previously generated pitches using the "View Saved Pitches" tab. """) # Function to retrieve saved pitch data def retrieve_pitch(script_id): if not script_id: return "Please enter a valid Script ID", "", "", None result = s3_storage.get_pitch_data(script_id) if result["success"]: data = result["data"] status = f"Successfully retrieved pitch: {script_id}" return ( status, data.get("elevator_pitch", ""), data.get("full_pitch", ""), data ) else: return ( f"Error: {result.get('message', 'Failed to retrieve pitch')}", "", "", None ) # Set up the form submission generate_btn.click( fn=generate_pitch, inputs=[ investor_type, startup_name, problem_description, solution_description, target_customer, business_model, current_stage, competitors, differentiators, market_impact, funding_details ], outputs=[ script_id, elevator_pitch, full_pitch, competitors_md, market_insights_md ] ) # Set up the retrieve button retrieve_btn.click( fn=retrieve_pitch, inputs=[script_id_input], outputs=[ retrieved_status, retrieved_elevator_pitch, retrieved_full_pitch, retrieved_additional_data ] ) # Main function to launch the app def main(): # Get port from environment variable or use default range port = os.environ.get("GRADIO_SERVER_PORT") if port: try: port = int(port) print(f"Using port {port} from environment variable") demo.launch(server_name="0.0.0.0", server_port=port) except ValueError: print(f"Invalid port in environment variable: {port}") demo.launch(server_name="0.0.0.0") else: # Try a range of ports starting from 8091 for port in range(8091, 8100): try: print(f"Attempting to start on port {port}...") demo.launch(server_name="0.0.0.0", server_port=port) print(f"Successfully started on port {port}") break except OSError: print(f"Port {port} is in use, trying next port...") else: # If all ports are taken, let Gradio choose a port print("All specified ports are in use. Letting Gradio choose an available port...") demo.launch(server_name="0.0.0.0") if __name__ == "__main__": demo.launch(server_name="0.0.0.0") # No custom port logic!