ans123 commited on
Commit
17fffbd
·
verified ·
1 Parent(s): 747aa89

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +396 -172
app.py CHANGED
@@ -8,13 +8,12 @@ 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()
@@ -39,68 +38,216 @@ 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
 
@@ -108,7 +255,8 @@ 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(
@@ -127,7 +275,7 @@ Create a complete, professionally formatted project proposal that could be prese
127
  "content": prompt
128
  }
129
  ],
130
- temperature=0.5, # Lower temperature for more consistent results
131
  max_tokens=4500
132
  )
133
 
@@ -140,18 +288,23 @@ Create a complete, professionally formatted project proposal that could be prese
140
 
141
  def extract_title(proposal):
142
  """Extract the title from the proposal"""
143
- # Try to match the exact format first
144
  title_match = re.search(r"\*\*Project Proposal: (.*?)\*\*", proposal)
145
  if title_match:
146
  return title_match.group(1)
147
 
 
 
 
 
 
148
  # Fallback pattern for more flexibility
149
- title_match = re.search(r"\*\*\s*(?:Project Proposal|Proposal|Title):\s*(.*?)\s*\*\*", proposal, re.IGNORECASE)
150
  if title_match:
151
  return title_match.group(1)
152
 
153
  # If no title found, use a generic one
154
- return "Project Proposal"
155
 
156
  def create_pdf(proposal, output_path="proposal.pdf"):
157
  """Create a PDF document from the proposal"""
@@ -241,78 +394,106 @@ def create_slides(proposal):
241
 
242
  # Add title slide
243
  title_slide = prs.slides.add_slide(title_slide_layout)
244
- title_slide.shapes.title.text = f"Project Proposal: {title}"
245
  subtitle = title_slide.placeholders[1]
246
- subtitle.text = "Professional Project Proposal"
247
 
248
- # List of sections to look for
249
- sections = [
250
- "Executive Summary",
251
- "Project Background",
252
- "Goals and Objectives",
253
- "Methodology and Approach",
254
- "Timeline",
255
- "Budget Considerations",
256
- "Expected Outcomes",
257
- "Team and Resources",
258
- "Risk Assessment",
259
- "Conclusion"
260
- ]
261
 
262
- # Extract sections using regex
263
- section_matches = re.finditer(r'\*\*\d+\.\s+(.*?)\*\*\n\n(.*?)(?=\*\*\d+\.|\Z)',
264
- proposal, re.DOTALL)
265
 
266
- for match in section_matches:
267
- section_title = match.group(1)
268
- section_content = match.group(2).strip()
 
 
 
 
 
 
 
 
 
 
 
269
 
270
- # Add section title slide
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
271
  section_slide = prs.slides.add_slide(section_title_layout)
272
  section_slide.shapes.title.text = section_title
273
 
274
- # Split content into paragraphs
275
- paragraphs = section_content.split('\n\n')
276
-
277
- # Process each paragraph
278
  current_slide = None
279
  text_frame = None
280
- paragraphs_on_slide = 0
281
 
282
- for para in paragraphs:
283
- para = para.strip()
284
- if not para:
285
- continue
286
-
287
  # Start a new slide if needed
288
- if current_slide is None or paragraphs_on_slide >= 3:
289
  current_slide = prs.slides.add_slide(content_layout)
290
  current_slide.shapes.title.text = section_title
291
  text_frame = current_slide.placeholders[1].text_frame
292
- paragraphs_on_slide = 0
293
 
294
- # Add the paragraph
295
- p = text_frame.add_paragraph()
296
-
297
- # Check if it's a bullet point list
298
- if re.match(r'^[\*\-]', para):
299
- # Process bullet points
300
- bullet_items = re.split(r'\n[\*\-]\s+', para)
301
- for item in bullet_items:
302
- item = item.strip()
303
- if item:
304
- # Remove leading bullet if present
305
- item = re.sub(r'^[\*\-]\s+', '', item)
306
- bullet_p = text_frame.add_paragraph()
307
- bullet_p.text = item
308
- bullet_p.level = 1
309
- else:
310
- p.text = para
311
 
312
- paragraphs_on_slide += 1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
313
 
314
  # Save the presentation
315
- output_path = "proposal_slides.pptx"
316
  prs.save(output_path)
317
  return output_path
318
 
@@ -326,90 +507,133 @@ def create_slides(proposal):
326
  subtitle = slide.placeholders[1]
327
  subtitle.text = f"An error occurred: {str(e)}\nPlease try again with a different project description."
328
 
329
- output_path = "proposal_slides.pptx"
330
  prs.save(output_path)
331
  except:
332
  # If even the error presentation fails, return a default path
333
  pass
334
  return output_path
335
 
336
- def process_input(description, project_type):
337
- """Process the input and generate both proposal, PDF and slides"""
338
  try:
339
- # Check if input is too short
340
- if len(description.strip()) < 10:
341
- return "Please provide a more detailed project description (at least 10 characters).", None, None
 
342
 
343
- # Map project type to specific type value
344
- type_value = None
345
- if project_type == "SaaS Performance Platform":
346
- type_value = "saas_performance"
347
 
348
- # Generate the proposal
349
- proposal = generate_proposal(description, type_value)
 
350
 
351
- # Create a basic PDF without any custom styles - fallback approach
352
- try:
353
- from reportlab.lib.pagesizes import letter
354
- from reportlab.pdfgen import canvas
355
-
356
- # Basic PDF generation using canvas directly
357
- c = canvas.Canvas("proposal.pdf", pagesize=letter)
358
- width, height = letter
359
-
360
- # Title
361
- c.setFont("Helvetica-Bold", 16)
362
- c.drawCentredString(width/2, height-50, "Project Proposal")
363
-
364
- # Simple text rendering
365
- c.setFont("Helvetica", 10)
366
- y = height - 80
367
- line_height = 14
368
-
369
- lines = proposal.split('\n')
370
- for line in lines:
371
- # Check for page break
372
- if y < 50:
373
- c.showPage()
374
- y = height - 50
375
 
376
- # Check if it's a header (starts with **)
377
- if line.startswith('**'):
378
- c.setFont("Helvetica-Bold", 12)
379
- # Remove ** markers
380
- line = line.replace('**', '')
381
- else:
382
- c.setFont("Helvetica", 10)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
383
 
384
- # Draw the line
385
- if line.strip():
386
- c.drawString(50, y, line)
 
 
387
  y -= line_height
388
-
389
- c.save()
390
- pdf_path = "proposal.pdf"
391
- except Exception as pdf_error:
392
- print(f"Error creating PDF: {pdf_error}")
393
- pdf_path = None
 
 
 
 
 
 
394
 
395
- # Create the slides
396
- try:
397
- ppt_path = create_slides(proposal)
398
- except Exception as ppt_error:
399
- print(f"Error creating slides: {ppt_error}")
400
- ppt_path = None
401
 
402
- return proposal, pdf_path, ppt_path
 
403
  except Exception as e:
404
- error_message = f"An error occurred: {str(e)}\nPlease try again with a different project description."
405
- print(f"Error in process_input: {e}")
406
- return error_message, None, None
 
 
 
 
 
 
 
 
 
 
407
 
408
  # Create Gradio interface
409
  def create_interface():
410
- with gr.Blocks(title="Professional Project Proposal Generator") as app:
411
- gr.Markdown("# Professional Project Proposal Generator")
412
- gr.Markdown("Generate comprehensive, professionally formatted project proposals with PDF and PowerPoint exports.")
413
 
414
  with gr.Row():
415
  with gr.Column(scale=1):
@@ -422,10 +646,10 @@ def create_interface():
422
  project_type = gr.Dropdown(
423
  label="Project Type",
424
  choices=["General Project", "SaaS Performance Platform"],
425
- value="General Project"
426
  )
427
 
428
- generate_button = gr.Button("Generate Proposal", variant="primary")
429
 
430
  # Examples
431
  examples = gr.Examples(
@@ -440,8 +664,8 @@ def create_interface():
440
  with gr.Column(scale=2):
441
  output_tabs = gr.Tabs()
442
  with output_tabs:
443
- with gr.TabItem("Proposal Text"):
444
- proposal_output = gr.Textbox(label="Generated Proposal", lines=25)
445
  with gr.TabItem("Documents"):
446
  with gr.Row():
447
  pdf_output = gr.File(label="PDF Document")
 
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.pdfgen import canvas
 
 
12
  from reportlab.lib.units import inch
13
+ from reportlab.lib import colors
14
  from dotenv import load_dotenv
15
  import re
16
+ import textwrap
17
 
18
  # Load environment variables
19
  load_dotenv()
 
38
  """Generate a proposal from a description using OpenRouter API"""
39
 
40
  # Create a better prompt with example formatting and detailed instructions
41
+ system_prompt = """You are a professional technical documentation writer with expertise in creating detailed, well-structured requirements and proposal documents.
42
 
43
+ Your documents are comprehensive, highly detailed, and follow a clear structure with proper formatting. Each section should include substantial content with specific details, bullet points, and professional technical language.
44
 
45
  Make sure to:
46
  1. Include proper formatting with section headings in bold
47
+ 2. Use bullet points (● symbol) for listing features and requirements
48
+ 3. Organize content into logical sections and subsections
49
+ 4. Provide concrete, specific technical details rather than generic statements
50
+ 5. Maintain a professional, technical tone throughout
51
+ 6. DO NOT include timelines, budgets, or pricing information
52
+ 7. Format the document to look like a formal technical requirements document
53
+ 8. Focus on functional requirements, technical specifications, and feature details
54
 
55
+ The document must be highly detailed, professionally formatted, and ready for presentation to technical stakeholders.
56
  """
57
 
58
+ # For SaaS Performance Platform, use a specific template based on the provided document
59
+ if project_type == "saas_performance":
60
+ example_format = """**[Title based on description]**
61
+
62
+ **Introduction:**
63
+ A comprehensive explanation of the project goals, purpose, and overview in 2-3 paragraphs. Describe the key benefits and intended outcomes without mentioning timelines or budgets.
64
+
65
+ **Functional Requirements:**
66
+
67
+ **User Authentication and Role Management:**
68
+ ● [Feature point 1]
69
+ ● [Feature point 2]
70
+ ● [Feature point 3]
71
+
72
+ **Dashboard and Analytics:**
73
+ ● [Feature point 1]
74
+ ● [Feature point 2]
75
+ ● [Feature point 3]
76
+
77
+ **Evaluation Framework Builder:**
78
+ ● [Feature point 1]
79
+ ● [Feature point 2]
80
+ ● [Feature point 3]
81
+
82
+ **Data Input and Rating Engine:**
83
+ ● [Feature point 1]
84
+ ● [Feature point 2]
85
+ ● [Feature point 3]
86
+
87
+ **Progress Tracking Module:**
88
+ ● [Feature point 1]
89
+ ● [Feature point 2]
90
+ ● [Feature point 3]
91
+
92
+ **Reporting and Exporting:**
93
+ ● [Feature point 1]
94
+ ● [Feature point 2]
95
+ ● [Feature point 3]
96
+
97
+ **Notifications:**
98
+ ● [Feature point 1]
99
+
100
+ **Permission and Access Management:**
101
+ ● [Feature point 1]
102
+ ● [Feature point 2]
103
+
104
+ **Audit Log and Activity Tracking:**
105
+ ● [Feature point 1]
106
+ ● [Feature point 2]
107
+
108
+ **Modules:**
109
+ ● [Module 1]
110
+ ● [Module 2]
111
+ ● [Module 3]
112
+ ● [Module 4]
113
+ ● [Module 5]
114
+ ● [Module 6]
115
+ ● [Module 7]
116
+ ● [Module 8]
117
+
118
+ **User Roles and Permissions:**
119
+
120
+ **[Role Type 1]:**
121
+ ● [Permission 1]
122
+ ● [Permission 2]
123
+
124
+ **[Role Type 2]:**
125
+ ● [Permission 1]
126
+ ● [Permission 2]
127
+ ● [Permission 3]
128
+
129
+ **[Role Type 3]:**
130
+ ● [Permission 1]
131
+ ● [Permission 2]
132
+
133
+ **[Role Type 4]:**
134
+ ● [Permission 1]
135
+ ● [Permission 2]
136
+ ● [Permission 3]
137
+
138
+ **Technology Stack:**
139
+ ● [Technology Category 1]: [Specific technologies]
140
+ ● [Technology Category 2]: [Specific technologies]
141
+ ● [Technology Category 3]: [Specific technologies]
142
+ ● [Technology Category 4]: [Specific technologies]
143
+ ● [Technology Category 5]: [Specific technologies]
144
+ ● [Technology Category 6]: [Specific technologies]
145
+ ● [Technology Category 7]: [Specific technologies]
146
+ ● [Technology Category 8]: [Specific technologies]
147
+ ● [Technology Category 9]: [Specific technologies]
148
+ ● [Technology Category 10]: [Specific technologies]
149
 
150
+ **Conclusion:**
151
+ A final summary of the proposed system and its benefits in 1-2 paragraphs. Emphasize how the solution will meet the needs described without mentioning timelines or costs."""
152
+ else:
153
+ # General format for other project types
154
+ example_format = """**[Title based on description]**
155
 
156
+ **Introduction:**
157
+ A comprehensive explanation of the project goals, purpose, and overview in 2-3 paragraphs. Describe the key benefits and intended outcomes without mentioning timelines or budgets.
158
 
159
+ **Functional Requirements:**
 
160
 
161
+ **[Key Feature Area 1]:**
162
+ [Feature point 1]
163
+ ● [Feature point 2]
164
+ ● [Feature point 3]
165
 
166
+ **[Key Feature Area 2]:**
167
+ [Feature point 1]
168
+ ● [Feature point 2]
169
+ ● [Feature point 3]
170
 
171
+ **[Key Feature Area 3]:**
172
+ [Feature point 1]
173
+ ● [Feature point 2]
174
+ ● [Feature point 3]
175
 
176
+ **[Key Feature Area 4]:**
177
+ [Feature point 1]
178
+ ● [Feature point 2]
179
+ ● [Feature point 3]
180
 
181
+ **System Architecture:**
182
+ [Architecture Component 1]
183
+ ● [Architecture Component 2]
184
+ ● [Architecture Component 3]
185
 
186
+ **Technical Specifications:**
187
+ [Technical Requirement 1]
188
+ ● [Technical Requirement 2]
189
+ ● [Technical Requirement 3]
190
 
191
+ **Security Requirements:**
192
+ [Security Feature 1]
193
+ ● [Security Feature 2]
194
+ ● [Security Feature 3]
195
 
196
+ **Integration Requirements:**
197
+ ● [Integration Point 1]
198
+ ● [Integration Point 2]
199
+ ● [Integration Point 3]
200
+
201
+ **User Types and Permissions:**
202
+
203
+ **[User Type 1]:**
204
+ ● [Permission 1]
205
+ ● [Permission 2]
206
+
207
+ **[User Type 2]:**
208
+ ● [Permission 1]
209
+ ● [Permission 2]
210
+
211
+ **[User Type 3]:**
212
+ ● [Permission 1]
213
+ ● [Permission 2]
214
+
215
+ **Technology Stack:**
216
+ ● [Technology Area 1]: [Specific technologies]
217
+ ● [Technology Area 2]: [Specific technologies]
218
+ ● [Technology Area 3]: [Specific technologies]
219
+ ● [Technology Area 4]: [Specific technologies]
220
+
221
+ **Conclusion:**
222
+ A final summary of the proposed system and its benefits in 1-2 paragraphs. Emphasize how the solution will meet the needs described without mentioning timelines or costs."""
223
+
224
+ # Create a project type specific instruction
225
  project_specific_prompt = ""
226
  if project_type == "saas_performance":
227
+ project_specific_prompt = """
228
+ Format the document to precisely match the example provided. For this SaaS Performance Evaluation Platform:
229
+
230
+ 1. DO NOT include any sections about budget, timeline, team structure, or pricing
231
+ 2. Structure the document exactly like the provided example with these specific sections:
232
+ - Introduction
233
+ - Functional Requirements (with all subsections as shown)
234
+ - User Roles and Permissions (with all user types)
235
+ - Technology Stack
236
+ - Conclusion
237
+ 3. Use bullet points with the ● symbol for all feature lists
238
+ 4. Include specific technical details about:
239
+ - Multi-tenant architecture with role-based access control
240
+ - User authentication and authorization
241
+ - Dashboard and analytics features with visualization options
242
+ - Evaluation framework capabilities
243
+ - Data input methods and rating systems
244
+ - Reporting and exporting functions
245
+ - Specific technology recommendations
246
+ 5. Maintain a formal, technical tone throughout the document
247
+ 6. Format all section headings in bold with a colon, like: "**Section Name:**"
248
+ """
249
 
250
+ prompt = f"""Create a detailed technical requirements document based on the following description. Format it exactly like the example format provided, with bold section headings and proper structure.
251
 
252
  {example_format}
253
 
 
255
 
256
  {project_specific_prompt}
257
 
258
+ Create a complete, professionally formatted technical requirements document that resembles a formal functional specification. DO NOT include any sections about budget, timeline, team structure, or pricing. Focus entirely on functional and technical requirements.
259
+ """
260
 
261
  try:
262
  completion = client.chat.completions.create(
 
275
  "content": prompt
276
  }
277
  ],
278
+ temperature=0.4, # Lower temperature for more consistent, formal results
279
  max_tokens=4500
280
  )
281
 
 
288
 
289
  def extract_title(proposal):
290
  """Extract the title from the proposal"""
291
+ # Try to match the exact format first - standard format
292
  title_match = re.search(r"\*\*Project Proposal: (.*?)\*\*", proposal)
293
  if title_match:
294
  return title_match.group(1)
295
 
296
+ # Try to match the requirements document format - just the title
297
+ title_match = re.search(r"\*\*(.*?)\*\*", proposal)
298
+ if title_match:
299
+ return title_match.group(1)
300
+
301
  # Fallback pattern for more flexibility
302
+ title_match = re.search(r"\*\*\s*(?:Project Proposal|Proposal|Title|Requirements Document):\s*(.*?)\s*\*\*", proposal, re.IGNORECASE)
303
  if title_match:
304
  return title_match.group(1)
305
 
306
  # If no title found, use a generic one
307
+ return "Requirements Document"
308
 
309
  def create_pdf(proposal, output_path="proposal.pdf"):
310
  """Create a PDF document from the proposal"""
 
394
 
395
  # Add title slide
396
  title_slide = prs.slides.add_slide(title_slide_layout)
397
+ title_slide.shapes.title.text = title
398
  subtitle = title_slide.placeholders[1]
399
+ subtitle.text = "Requirements Document"
400
 
401
+ # Parse the document into sections
402
+ sections = []
403
+ current_section = None
404
+ current_content = []
 
 
 
 
 
 
 
 
 
405
 
406
+ # Split into paragraphs
407
+ paragraphs = proposal.split('\n\n')
 
408
 
409
+ for para in paragraphs:
410
+ para = para.strip()
411
+ if not para:
412
+ continue
413
+
414
+ # Check if it's a main section header
415
+ if para.startswith('**') and para.endswith('**'):
416
+ # Save previous section if exists
417
+ if current_section and current_content:
418
+ sections.append((current_section, current_content))
419
+
420
+ # Start new section
421
+ current_section = para.replace('**', '')
422
+ current_content = []
423
 
424
+ # Check if it's a subsection header
425
+ elif para.startswith('**') and '**:' in para:
426
+ parts = para.split('**:', 1)
427
+ if len(parts) == 2:
428
+ # Add as subsection with special formatting
429
+ header = parts[0].replace('**', '') + ':'
430
+ content = parts[1].strip()
431
+ current_content.append(("subsection", header, content if content else []))
432
+
433
+ # Regular content or bullet points
434
+ else:
435
+ current_content.append(("content", para))
436
+
437
+ # Add the last section
438
+ if current_section and current_content:
439
+ sections.append((current_section, current_content))
440
+
441
+ # Create slides for each section
442
+ for section_title, contents in sections:
443
+ # Skip the first section if it's the title
444
+ if section_title.lower() == title.lower():
445
+ continue
446
+
447
+ # Section title slide
448
  section_slide = prs.slides.add_slide(section_title_layout)
449
  section_slide.shapes.title.text = section_title
450
 
451
+ # Content slides
 
 
 
452
  current_slide = None
453
  text_frame = None
454
+ items_on_slide = 0
455
 
456
+ for content_type, *content_data in contents:
 
 
 
 
457
  # Start a new slide if needed
458
+ if current_slide is None or items_on_slide >= 6:
459
  current_slide = prs.slides.add_slide(content_layout)
460
  current_slide.shapes.title.text = section_title
461
  text_frame = current_slide.placeholders[1].text_frame
462
+ items_on_slide = 0
463
 
464
+ if content_type == "subsection":
465
+ # Add subsection header
466
+ subsection_header, subsection_content = content_data
467
+ p = text_frame.add_paragraph()
468
+ p.text = subsection_header
469
+ p.font.bold = True
470
+ items_on_slide += 1
471
+
472
+ # Add subsection content if any
473
+ if subsection_content and isinstance(subsection_content, str):
474
+ p = text_frame.add_paragraph()
475
+ p.text = subsection_content
476
+ items_on_slide += 1
 
 
 
 
477
 
478
+ elif content_type == "content":
479
+ para_text = content_data[0]
480
+
481
+ # Check if it's a bullet list
482
+ if para_text.startswith('●'):
483
+ lines = para_text.split('\n')
484
+ for line in lines:
485
+ if line.strip():
486
+ p = text_frame.add_paragraph()
487
+ p.text = line.strip().replace('●', '').strip()
488
+ p.level = 1
489
+ items_on_slide += 1
490
+ else:
491
+ p = text_frame.add_paragraph()
492
+ p.text = para_text
493
+ items_on_slide += 1
494
 
495
  # Save the presentation
496
+ output_path = "requirements_slides.pptx"
497
  prs.save(output_path)
498
  return output_path
499
 
 
507
  subtitle = slide.placeholders[1]
508
  subtitle.text = f"An error occurred: {str(e)}\nPlease try again with a different project description."
509
 
510
+ output_path = "requirements_slides.pptx"
511
  prs.save(output_path)
512
  except:
513
  # If even the error presentation fails, return a default path
514
  pass
515
  return output_path
516
 
517
+ def create_pdf(proposal, output_path="requirements_document.pdf"):
518
+ """Create a PDF document from the proposal"""
519
  try:
520
+ from reportlab.lib.pagesizes import letter
521
+ from reportlab.pdfgen import canvas
522
+ from reportlab.lib.units import inch
523
+ from reportlab.lib import colors
524
 
525
+ # Basic PDF generation using canvas directly
526
+ c = canvas.Canvas(output_path, pagesize=letter)
527
+ width, height = letter
 
528
 
529
+ # Add a header with company info (similar to the example)
530
+ c.setFont("Helvetica", 10)
531
+ c.drawString(1*inch, height-0.5*inch, "Generated Requirements Document")
532
 
533
+ # Title
534
+ title = extract_title(proposal)
535
+ c.setFont("Helvetica-Bold", 14)
536
+ c.drawCentredString(width/2, height-1.2*inch, title)
537
+
538
+ # Simple text rendering
539
+ c.setFont("Helvetica", 10)
540
+ y = height - 1.5*inch
541
+ line_height = 14
542
+
543
+ # Process by paragraphs to handle sections better
544
+ paragraphs = proposal.split('\n\n')
545
+
546
+ for paragraph in paragraphs:
547
+ paragraph = paragraph.strip()
548
+ if not paragraph:
549
+ continue
 
 
 
 
 
 
 
550
 
551
+ # Check for page break
552
+ if y < 1*inch:
553
+ c.showPage()
554
+ # Add header to new page
555
+ c.setFont("Helvetica", 10)
556
+ c.drawString(1*inch, height-0.5*inch, "Generated Requirements Document")
557
+ y = height - 1*inch
558
+
559
+ # Check if it's a section header (starts with **)
560
+ if paragraph.startswith('**') and paragraph.endswith('**'):
561
+ c.setFont("Helvetica-Bold", 12)
562
+ # Remove ** markers
563
+ paragraph = paragraph.replace('**', '')
564
+ c.drawString(1*inch, y, paragraph)
565
+ y -= line_height * 1.5
566
+ # Check if it's a subsection header (starts with ** but has more text)
567
+ elif paragraph.startswith('**') and '**:' in paragraph:
568
+ parts = paragraph.split('**:', 1)
569
+ if len(parts) == 2:
570
+ header = parts[0].replace('**', '') + ':'
571
+ c.setFont("Helvetica-Bold", 11)
572
+ c.drawString(1*inch, y, header)
573
+ y -= line_height * 1.2
574
+
575
+ # If there's content after the header
576
+ content = parts[1].strip()
577
+ if content:
578
+ c.setFont("Helvetica", 10)
579
+ # Need to wrap this text
580
+ text_object = c.beginText(1.2*inch, y)
581
+ for line in textwrap.wrap(content, width=70):
582
+ text_object.textLine(line)
583
+ y -= line_height
584
+ c.drawText(text_object)
585
+ y -= line_height * 0.5
586
+ # Check if it's a bullet point
587
+ elif paragraph.startswith('●'):
588
+ c.setFont("Helvetica", 10)
589
+ # Draw the bullet
590
+ c.drawString(1.2*inch, y, '●')
591
 
592
+ # Draw the text after the bullet with indentation
593
+ text = paragraph[1:].strip()
594
+ text_object = c.beginText(1.5*inch, y)
595
+ for line in textwrap.wrap(text, width=60):
596
+ text_object.textLine(line)
597
  y -= line_height
598
+ c.drawText(text_object)
599
+ y -= line_height * 0.3
600
+ else:
601
+ # Regular paragraph
602
+ c.setFont("Helvetica", 10)
603
+ # Need to wrap this text
604
+ text_object = c.beginText(1*inch, y)
605
+ for line in textwrap.wrap(paragraph, width=70):
606
+ text_object.textLine(line)
607
+ y -= line_height
608
+ c.drawText(text_object)
609
+ y -= line_height * 0.5
610
 
611
+ # Add a footer with page number
612
+ c.setFont("Helvetica", 8)
613
+ c.drawCentredString(width/2, 0.5*inch, "Page 1")
 
 
 
614
 
615
+ c.save()
616
+ return output_path
617
  except Exception as e:
618
+ print(f"Error creating PDF: {e}")
619
+ # Create an even simpler emergency PDF
620
+ try:
621
+ c = canvas.Canvas(output_path, pagesize=letter)
622
+ width, height = letter
623
+ c.setFont("Helvetica-Bold", 14)
624
+ c.drawString(1*inch, height-1*inch, "Requirements Document")
625
+ c.setFont("Helvetica", 10)
626
+ c.drawString(1*inch, height-1.5*inch, "Error formatting document. Please see text version.")
627
+ c.save()
628
+ except Exception as inner_e:
629
+ print(f"Error creating emergency PDF: {inner_e}")
630
+ return output_path
631
 
632
  # Create Gradio interface
633
  def create_interface():
634
+ with gr.Blocks(title="Requirements Document Generator") as app:
635
+ gr.Markdown("# Technical Requirements Document Generator")
636
+ gr.Markdown("Generate comprehensive, professionally formatted technical requirements documents with PDF and PowerPoint exports.")
637
 
638
  with gr.Row():
639
  with gr.Column(scale=1):
 
646
  project_type = gr.Dropdown(
647
  label="Project Type",
648
  choices=["General Project", "SaaS Performance Platform"],
649
+ value="SaaS Performance Platform"
650
  )
651
 
652
+ generate_button = gr.Button("Generate Requirements Document", variant="primary")
653
 
654
  # Examples
655
  examples = gr.Examples(
 
664
  with gr.Column(scale=2):
665
  output_tabs = gr.Tabs()
666
  with output_tabs:
667
+ with gr.TabItem("Document Text"):
668
+ proposal_output = gr.Textbox(label="Generated Document", lines=25)
669
  with gr.TabItem("Documents"):
670
  with gr.Row():
671
  pdf_output = gr.File(label="PDF Document")