Spaces:
Sleeping
Sleeping
File size: 15,849 Bytes
8cf2a7f 4558e9e 8cf2a7f 67b74d5 4558e9e 67b74d5 4558e9e 67b74d5 4558e9e 67b74d5 4558e9e 67b74d5 4558e9e 67b74d5 8cf2a7f 4558e9e 67b74d5 4558e9e 67b74d5 4558e9e 67b74d5 8cf2a7f 4558e9e 8cf2a7f 4558e9e 8cf2a7f 67b74d5 4558e9e 8cf2a7f 67b74d5 4558e9e 67b74d5 8cf2a7f 67b74d5 8cf2a7f 67b74d5 8cf2a7f 67b74d5 8cf2a7f 67b74d5 8cf2a7f 67b74d5 8cf2a7f 67b74d5 8cf2a7f 67b74d5 8cf2a7f 67b74d5 8cf2a7f 67b74d5 8cf2a7f 67b74d5 4558e9e 8cf2a7f 67b74d5 8cf2a7f 4558e9e 8cf2a7f 67b74d5 4558e9e 67b74d5 8cf2a7f 67b74d5 8cf2a7f 4558e9e 8cf2a7f 67b74d5 8cf2a7f 4558e9e 8cf2a7f 4558e9e 8cf2a7f 67b74d5 8cf2a7f 4558e9e 8cf2a7f 4558e9e 8cf2a7f 67b74d5 4558e9e 8cf2a7f 4558e9e 67b74d5 4558e9e 67b74d5 4558e9e 67b74d5 8cf2a7f 67b74d5 8cf2a7f 4558e9e 8cf2a7f 4558e9e 8cf2a7f |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 |
import os
import sys
import time
import gradio as gr
from openai import OpenAI
from pptx import Presentation
from pptx.util import Pt, Inches
from pptx.enum.text import PP_ALIGN
from pptx.dml.color import RGBColor
from reportlab.lib.pagesizes import letter
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib import colors
from reportlab.lib.units import inch
from reportlab.lib.enums import TA_CENTER, TA_JUSTIFY
from dotenv import load_dotenv
import re
# Load environment variables
load_dotenv()
# Get API key from environment variable
OPENROUTER_API_KEY = os.getenv("OPENROUTER_API_KEY")
if not OPENROUTER_API_KEY:
raise ValueError("OPENROUTER_API_KEY environment variable is not set")
# OpenRouter API configuration
MODEL_NAME = "meta-llama/llama-3.3-8b-instruct:free" # You can also use more powerful models like "anthropic/claude-3-opus-20240229"
SITE_URL = "https://proposal-generator.io" # Replace with your actual site URL
SITE_NAME = "Professional Proposal Generator" # Replace with your actual site name
# Initialize OpenAI client for OpenRouter
client = OpenAI(
base_url="https://openrouter.ai/api/v1",
api_key=OPENROUTER_API_KEY,
)
def generate_proposal(description, project_type=None):
"""Generate a proposal from a description using OpenRouter API"""
# Create a better prompt with example formatting and detailed instructions
system_prompt = """You are a professional business proposal writer with expertise in creating detailed, well-structured project proposals.
Your proposals are comprehensive, highly detailed, and follow a clear structure with proper formatting. Each section should include substantial content with specific details, bullet points where appropriate, and professional language.
Make sure to:
1. Include proper formatting with section headings in bold
2. Add bullet points for lists and key points
3. Include realistic timelines, budgets, and team structures
4. Provide concrete, specific details rather than generic statements
5. Maintain a professional tone throughout
6. Create content that looks like it was written by human experts in the field
The proposal must be highly detailed, professionally formatted, and ready for presentation to stakeholders.
"""
example_format = """**Project Proposal: [Title based on description]**
**1. Executive Summary**
A comprehensive 3-5 paragraph summary that clearly articulates the project's purpose, key features, benefits, timeline, budget range, and expected outcomes. Include specific metrics and goals.
**2. Project Background**
Detailed explanation of the current situation, market analysis, problems being addressed, and the opportunity. Include specific industry trends, challenges, and the gap this project fills.
**3. Goals and Objectives**
Clearly separated primary goals (broader aims) and specific objectives (measurable targets). Use bullet points for clarity, with each objective being SMART (Specific, Measurable, Achievable, Relevant, Time-bound).
**4. Methodology and Approach**
Detailed explanation of the implementation approach, including specific phases, methodologies, technologies, and frameworks to be used. Outline the specific steps that will be taken.
**5. Timeline**
Specific weekly breakdown of the project with clear milestones, deliverables, and dependencies. Include duration estimates and key decision points.
**6. Budget Considerations**
Detailed budget breakdown with percentages, actual figures, and justifications for each expense category. Include contingency planning and ROI estimates where applicable.
**7. Expected Outcomes**
Comprehensive list of both tangible and intangible outcomes, specific metrics for success, and long-term benefits. Include KPIs that will be used to measure success.
**8. Team and Resources**
Specific team composition with roles, responsibilities, and experience levels. Include external resources, tools, and infrastructure requirements.
**9. Risk Assessment**
Detailed identification of potential risks, probability and impact ratings, and specific mitigation strategies for each risk. Include contingency plans.
**10. Conclusion**
Powerful closing that reinforces the value proposition, summarizes key benefits, and includes a clear call to action."""
# Create a project type specific prompt if provided
project_specific_prompt = ""
if project_type == "saas_performance":
project_specific_prompt = """For this SaaS Performance Evaluation Platform, be sure to include:
- Multi-tenant architecture with role-based access control details
- User authentication and authorization specifics
- Dashboard and analytics features with visualization options
- Evaluation framework customization capabilities
- Data input methods and integration with external systems
- Performance tracking and reporting mechanisms
- Specific technology stack recommendations with justifications
- Security measures for protecting sensitive performance data
- Scalability and performance considerations"""
prompt = f"""Create a detailed project proposal based on the following description. Format it exactly like the example format provided, with bold section headings and proper structure.
{example_format}
Project Description: {description}
{project_specific_prompt}
Create a complete, professionally formatted project proposal that could be presented directly to stakeholders. Make each section highly detailed and specific."""
try:
completion = client.chat.completions.create(
extra_headers={
"HTTP-Referer": SITE_URL,
"X-Title": SITE_NAME,
},
model=MODEL_NAME,
messages=[
{
"role": "system",
"content": system_prompt
},
{
"role": "user",
"content": prompt
}
],
temperature=0.5, # Lower temperature for more consistent results
max_tokens=4500
)
proposal = completion.choices[0].message.content
return proposal
except Exception as e:
print(f"Error generating proposal: {e}")
return f"Error generating proposal: {e}"
def extract_title(proposal):
"""Extract the title from the proposal"""
title_match = re.search(r"\*\*Project Proposal: (.*?)\*\*", proposal)
if title_match:
return title_match.group(1)
return "Project Proposal"
def create_pdf(proposal, output_path="proposal.pdf"):
"""Create a PDF document from the proposal"""
doc = SimpleDocTemplate(output_path, pagesize=letter,
rightMargin=72, leftMargin=72,
topMargin=72, bottomMargin=72)
styles = getSampleStyleSheet()
# Create custom styles
styles.add(ParagraphStyle(name='Title',
parent=styles['Heading1'],
fontSize=16,
alignment=TA_CENTER,
spaceAfter=20))
styles.add(ParagraphStyle(name='SectionHeading',
parent=styles['Heading2'],
fontSize=14,
spaceAfter=12,
spaceBefore=20))
styles.add(ParagraphStyle(name='Normal',
parent=styles['Normal'],
fontSize=10,
alignment=TA_JUSTIFY,
spaceAfter=10))
# Extract title
title = extract_title(proposal)
# Process the proposal content
story = []
# Add title
story.append(Paragraph(f"<b>Project Proposal: {title}</b>", styles['Title']))
story.append(Spacer(1, 0.25*inch))
# Process sections
sections = re.split(r'\*\*\d+\.\s+(.*?)\*\*', proposal)
headers = re.findall(r'\*\*\d+\.\s+(.*?)\*\*', proposal)
# The first element in sections is the title area, skip it
for i, content in enumerate(sections[1:], 0):
if i < len(headers):
# Add section header
story.append(Paragraph(f"<b>{i+1}. {headers[i]}</b>", styles['SectionHeading']))
# Process content paragraphs
paragraphs = content.strip().split('\n\n')
for para in paragraphs:
para = para.strip()
if not para:
continue
# Check if it's a bullet point list
if re.match(r'^[\*\-]', para):
# Process bullet points
bullet_items = re.split(r'\n[\*\-]\s+', para)
for item in bullet_items:
item = item.strip()
if item:
# Remove leading bullet if present
item = re.sub(r'^[\*\-]\s+', '', item)
story.append(Paragraph(f"• {item}", styles['Normal']))
else:
# Regular paragraph
story.append(Paragraph(para, styles['Normal']))
# Build the PDF
doc.build(story)
return output_path
def create_slides(proposal):
"""Create PowerPoint slides from the proposal"""
prs = Presentation()
# Extract title
title = extract_title(proposal)
# Set up slide layouts
title_slide_layout = prs.slide_layouts[0]
section_title_layout = prs.slide_layouts[2]
content_layout = prs.slide_layouts[1]
# Add title slide
title_slide = prs.slides.add_slide(title_slide_layout)
title_slide.shapes.title.text = f"Project Proposal: {title}"
subtitle = title_slide.placeholders[1]
subtitle.text = "Professional Project Proposal"
# List of sections to look for
sections = [
"Executive Summary",
"Project Background",
"Goals and Objectives",
"Methodology and Approach",
"Timeline",
"Budget Considerations",
"Expected Outcomes",
"Team and Resources",
"Risk Assessment",
"Conclusion"
]
# Extract sections using regex
section_matches = re.finditer(r'\*\*\d+\.\s+(.*?)\*\*\n\n(.*?)(?=\*\*\d+\.|\Z)',
proposal, re.DOTALL)
for match in section_matches:
section_title = match.group(1)
section_content = match.group(2).strip()
# Add section title slide
section_slide = prs.slides.add_slide(section_title_layout)
section_slide.shapes.title.text = section_title
# Split content into paragraphs
paragraphs = section_content.split('\n\n')
# Process each paragraph
current_slide = None
text_frame = None
paragraphs_on_slide = 0
for para in paragraphs:
para = para.strip()
if not para:
continue
# Start a new slide if needed
if current_slide is None or paragraphs_on_slide >= 3:
current_slide = prs.slides.add_slide(content_layout)
current_slide.shapes.title.text = section_title
text_frame = current_slide.placeholders[1].text_frame
paragraphs_on_slide = 0
# Add the paragraph
p = text_frame.add_paragraph()
# Check if it's a bullet point list
if re.match(r'^[\*\-]', para):
# Process bullet points
bullet_items = re.split(r'\n[\*\-]\s+', para)
for item in bullet_items:
item = item.strip()
if item:
# Remove leading bullet if present
item = re.sub(r'^[\*\-]\s+', '', item)
bullet_p = text_frame.add_paragraph()
bullet_p.text = item
bullet_p.level = 1
else:
p.text = para
paragraphs_on_slide += 1
# Save the presentation
output_path = "proposal_slides.pptx"
prs.save(output_path)
return output_path
def process_input(description, project_type):
"""Process the input and generate both proposal, PDF and slides"""
# Check if input is too short
if len(description.strip()) < 10:
return "Please provide a more detailed project description (at least 10 characters).", None, None
# Generate the proposal
proposal = generate_proposal(description, project_type)
# Create the PDF
pdf_path = create_pdf(proposal)
# Create the slides
ppt_path = create_slides(proposal)
return proposal, pdf_path, ppt_path
# Create Gradio interface
def create_interface():
with gr.Blocks(title="Professional Project Proposal Generator") as app:
gr.Markdown("# Professional Project Proposal Generator")
gr.Markdown("Generate comprehensive, professionally formatted project proposals with PDF and PowerPoint exports.")
with gr.Row():
with gr.Column(scale=1):
description_input = gr.Textbox(
label="Project Description",
placeholder="Describe your project in detail...",
lines=10
)
project_type = gr.Dropdown(
label="Project Type",
choices=["General Project", "SaaS Performance Platform"],
value="General Project"
)
generate_button = gr.Button("Generate Proposal", variant="primary")
# Examples
examples = gr.Examples(
examples=[
["Develop a cloud-based SaaS platform for performance evaluation in educational institutions and corporate environments. The platform will enable users to track, evaluate, and report on individual performance metrics with customizable evaluation models.", "SaaS Performance Platform"],
["Create a mobile application for sustainable waste management and recycling in urban communities. The app will connect residents with local recycling centers and provide educational resources on waste reduction.", "General Project"],
["Design and implement a smart agriculture system using IoT sensors for small-scale farms. The system will monitor soil conditions, weather patterns, and crop health to optimize irrigation and fertilization.", "General Project"]
],
inputs=[description_input, project_type]
)
with gr.Column(scale=2):
output_tabs = gr.Tabs()
with output_tabs:
with gr.TabItem("Proposal Text"):
proposal_output = gr.Textbox(label="Generated Proposal", lines=25)
with gr.TabItem("Documents"):
with gr.Row():
pdf_output = gr.File(label="PDF Document")
slides_output = gr.File(label="PowerPoint Slides")
generate_button.click(
process_input,
inputs=[description_input, project_type],
outputs=[proposal_output, pdf_output, slides_output]
)
return app
# Main script code
if __name__ == "__main__":
print("Starting Gradio interface...")
app = create_interface()
app.launch(share=True) |