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