import os import gradio as gr from groq import Groq import reportlab.lib.pagesizes as pagesizes from reportlab.pdfgen import canvas from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer from reportlab.lib.units import inch from io import BytesIO import docx from docx.shared import Pt, Inches from docx.enum.text import WD_ALIGN_PARAGRAPH import time import tempfile # Initialize the Groq client GROQ_API_KEY = os.getenv('GROQ_API_KEY') GROQ_MODEL = "llama-3.3-70b-versatile" client = Groq(api_key=GROQ_API_KEY) # Custom CSS for styling custom_css = """ .generate-btn { margin: 0 auto !important; display: block !important; } .output-box { background-color: black !important; border-radius: 8px !important; padding: 20px !important; box-shadow: 0 2px 5px rgba(0,0,0,0.1) !important; margin-top: 20px !important; color: white !important; } .app-header { text-align: center !important; margin-bottom: 20px !important; } /* Fix text visibility */ .gradio-container input[type=text], .gradio-container textarea { color: #000000 !important; background-color: #ffffff !important; border: 1px solid #cccccc !important; } /* Make sure placeholder text is visible but distinct */ .gradio-container input::placeholder, .gradio-container textarea::placeholder { color: #888888 !important; opacity: 1; } /* Ensure the output text is clearly visible */ .output-box, .markdown-text { color: #000000 !important; } /* Loading indicator styling */ .loading-indicator { text-align: center; padding: 20px; font-style: italic; color: #555; } """ def generate_opt_framework(topic): """Generate an OPT framework for the given topic using Groq API""" if not topic: return "Please enter a topic to generate an OPT framework." prompt = f""" Generate an OPT (Objectives, Products, Tasks) framework for: {topic} Format your response as follows: # OPT Framework for: {topic} ## Objectives Clear, high-level goals that define what success looks like for this topic/project. ## Products Specific, tangible deliverables that will help achieve the objectives. ## Tasks Detailed, actionable steps required to create each product. Make your response comprehensive but practical, with clear language and realistic items. """ try: chat_completion = client.chat.completions.create( model=GROQ_MODEL, messages=[ {"role": "system", "content": "You are an expert at creating OPT frameworks to help with project planning and goal setting."}, {"role": "user", "content": prompt} ], temperature=0.7, max_tokens=1500 ) framework = chat_completion.choices[0].message.content return framework except Exception as e: return f"Error generating OPT framework: {str(e)}" def generate_automation_analysis(opt_content): """Generate automation analysis for the OPT framework tasks""" if not opt_content or "Tasks" not in opt_content: return "No tasks found to analyze for automation." prompt = f""" Analyze the following OPT framework and identify tasks that can be automated: {opt_content} For each task that can be automated: 1. Identify the task 2. Explain why it can be automated 3. Provide a step-by-step beginner's guide to automating this task 4. Suggest tools or software that could help with the automation Format your response as a comprehensive automation analysis with clear sections and explanations. """ try: chat_completion = client.chat.completions.create( model=GROQ_MODEL, messages=[ {"role": "system", "content": "You are an expert at identifying tasks that can be automated and providing guidance on automation techniques."}, {"role": "user", "content": prompt} ], temperature=0.7, max_tokens=2000 ) analysis = chat_completion.choices[0].message.content return analysis except Exception as e: return f"Error generating automation analysis: {str(e)}" def handle_topic_submission(topic): """Handle topic submission from text input""" opt_framework = generate_opt_framework(topic) return opt_framework, gr.update(visible=True), gr.update(visible=True) def handle_example_topic(example_topic): """Handle clicking on example topic buttons""" opt_framework = generate_opt_framework(example_topic) return example_topic, opt_framework, gr.update(visible=True), gr.update(visible=True) def handle_regenerate(topic): """Handle regeneration request""" if not topic: return "Please enter a topic first." opt_framework = generate_opt_framework(topic) return opt_framework def analyze_with_progress(opt_content, progress=gr.Progress()): """Handle request for automation analysis with progress indication""" # Initial loading state progress(0, desc="Preparing analysis...") yield "Analyzing tasks for automation potential. Please wait...", gr.update(visible=True) # Simulate progress steps to provide visual feedback progress(0.3, desc="Identifying tasks...") time.sleep(0.5) # Just to show progress visually progress(0.6, desc="Evaluating automation potential...") time.sleep(0.5) progress(0.8, desc="Generating step-by-step guides...") time.sleep(0.5) # Generate the actual analysis analysis = generate_automation_analysis(opt_content) # Complete the progress and return results progress(1.0, desc="Complete!") yield analysis, gr.update(visible=True) def create_pdf_file(content, title): """Create a PDF document from the content and save to temp file""" # Create a temporary file temp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.pdf') temp_filename = temp_file.name temp_file.close() doc = SimpleDocTemplate(temp_filename, pagesize=pagesizes.letter) styles = getSampleStyleSheet() story = [] # Add custom title style title_style = ParagraphStyle( 'TitleStyle', parent=styles['Heading1'], fontSize=16, alignment=1, spaceAfter=0.5*inch ) # Add title story.append(Paragraph(f"OPT Framework and Automation Analysis: {title}", title_style)) story.append(Spacer(1, 0.25*inch)) # Process content paragraphs = content.split('\n') for para in paragraphs: if para.startswith('# '): story.append(Paragraph(para[2:], styles['Heading1'])) elif para.startswith('## '): story.append(Paragraph(para[3:], styles['Heading2'])) elif para.startswith('### '): story.append(Paragraph(para[4:], styles['Heading3'])) elif para.strip(): story.append(Paragraph(para, styles['Normal'])) else: story.append(Spacer(1, 0.1*inch)) doc.build(story) return temp_filename def create_docx_file(content, title): """Create a DOCX document from the content and save to temp file""" # Create a temporary file temp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.docx') temp_filename = temp_file.name temp_file.close() doc = docx.Document() # Add title title_para = doc.add_paragraph() title_run = title_para.add_run(f"OPT Framework and Automation Analysis: {title}") title_run.font.size = Pt(18) title_run.font.bold = True title_para.alignment = WD_ALIGN_PARAGRAPH.CENTER # Process content paragraphs = content.split('\n') for para in paragraphs: if para.startswith('# '): p = doc.add_paragraph() run = p.add_run(para[2:]) run.font.size = Pt(16) run.font.bold = True elif para.startswith('## '): p = doc.add_paragraph() run = p.add_run(para[3:]) run.font.size = Pt(14) run.font.bold = True elif para.startswith('### '): p = doc.add_paragraph() run = p.add_run(para[4:]) run.font.size = Pt(12) run.font.bold = True elif para.strip(): doc.add_paragraph(para) doc.save(temp_filename) return temp_filename def download_pdf(opt_content, analysis_content, topic): """Create PDF for download""" combined_content = f"{opt_content}\n\n# Automation Analysis\n\n{analysis_content}" pdf_path = create_pdf_file(combined_content, topic) return pdf_path def download_docx(opt_content, analysis_content, topic): """Create DOCX for download""" combined_content = f"{opt_content}\n\n# Automation Analysis\n\n{analysis_content}" docx_path = create_docx_file(combined_content, topic) return docx_path # Create the Gradio interface with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue"), css=custom_css) as app: # App header gr.Markdown("# OPT Framework Generator", elem_classes=["app-header"]) # What is OPT Framework (unhidden) gr.Markdown(""" ## What is the OPT Framework? The OPT Framework is a structured approach to planning that breaks down goals into three key components: - **Objectives**: High-level goals that define what success looks like - **Products**: Tangible deliverables that help achieve the objectives - **Tasks**: Specific, actionable steps required to create each product This framework brings clarity, focus, and momentum to any project, making execution more purposeful and efficient. """) # How to use section (collapsible) with gr.Accordion("How to Use This App", open=False): gr.Markdown(""" 1. Enter your topic or project in the text box, or click one of the example buttons 2. Click "Generate OPT Framework" to create your custom framework 3. Click "Generate Another Version" if you want alternative options 4. Analyze tasks for automation potential 5. Download your complete analysis as PDF or DOCX for future reference This tool helps you organize any project or goal into a clear, actionable plan with insights on which tasks can be automated. (PS: Please wait for a few seconds before downloading the report) """) # Input section with text box and examples side by side with gr.Row(): with gr.Column(scale=7): # 70% width for text input topic_input = gr.Textbox( label="Enter your project/goal", placeholder="Enter anything you can think of... a project, goal, business idea, personal challenge, etc.", lines=3 ) submit_btn = gr.Button("Generate OPT Framework", variant="primary", elem_classes=["generate-btn"]) with gr.Column(scale=3): # 30% width for examples gr.Markdown("### Quick Examples:") example_btns = [ gr.Button("Mobile App Development"), gr.Button("Content Marketing Strategy"), gr.Button("Home Renovation Project"), gr.Button("Personal Fitness Goal"), gr.Button("Writing a Novel") ] # Output section with custom styling opt_output = gr.Markdown(elem_classes=["output-box"], label="Generated OPT Framework") with gr.Row(visible=False) as action_row: regenerate_btn = gr.Button("Generate Another Version") analyze_btn = gr.Button("Analyze Tasks for Automation") # Loading indicator and analysis output analysis_output = gr.Markdown(elem_classes=["output-box"], label="Automation Analysis", visible=False) with gr.Row(visible=False) as download_container: download_btn = gr.Button("Download Report (Please wait for a few seconds before downloading)") with gr.Row(visible=False) as download_format_row: time.sleep(1) pdf_btn = gr.Button("PDF") docx_btn = gr.Button("DOCX") # Set up event handlers submit_btn.click( handle_topic_submission, inputs=[topic_input], outputs=[opt_output, action_row, analyze_btn] ) for btn in example_btns: btn.click( handle_example_topic, inputs=[btn], outputs=[topic_input, opt_output, action_row, analyze_btn] ) regenerate_btn.click( handle_regenerate, inputs=[topic_input], outputs=[opt_output] ) # Modified to use streaming output for better loading feedback analyze_btn.click( analyze_with_progress, inputs=[opt_output], outputs=[analysis_output, download_container], show_progress=True ) download_btn.click( lambda: gr.update(visible=True), outputs=[download_format_row] ) pdf_btn.click( download_pdf, inputs=[opt_output, analysis_output, topic_input], outputs=[gr.File(label="Download PDF")] ) docx_btn.click( download_docx, inputs=[opt_output, analysis_output, topic_input], outputs=[gr.File(label="Download DOCX")] ) if __name__ == "__main__": app.launch()