bluenevus commited on
Commit
90ea430
·
1 Parent(s): 2eb04be

Update app.py via AI Editor

Browse files
Files changed (1) hide show
  1. app.py +36 -62
app.py CHANGED
@@ -33,6 +33,26 @@ MAX_OUTPUT_TOKENS = 65536
33
 
34
  SESSION_STORE = {}
35
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  def get_session_id_from_cookie(cookie_str):
37
  if not cookie_str:
38
  return None
@@ -256,13 +276,9 @@ def process_document(sess_data, action, selected_filename=None, chat_input=None,
256
  if not doc_content:
257
  logging.warning("No uploaded document found for shredding.")
258
  return "No document uploaded.", None, None, None, None
259
- prompt = (
260
- "Analyze the following RFP/PWS/SOW/RFI and generate a requirements spreadsheet. Return ONLY the markdown spreadsheet and NOTHING else"
261
- "Identify requirements by action words like 'shall', 'will', 'perform', etc. Also analye the document and put a column for recommended win theme for each requirement identified. Organize by PWS section and requirement. "
262
- "Do not write as if responding to the proposal Return the ONLY markdown spreadsheet and NOTHING else, no intro, no outro, no comments.\n"
263
- )
264
  if chat_input:
265
- prompt += f"User additional instructions: {chat_input}\n"
266
  prompt += f"\nFile Name: {selected_filename}\n\n"
267
  prompt += doc_content
268
  result = gemini_generate_content(prompt, file_id=doc_fileid, chat_input=chat_input)
@@ -284,18 +300,10 @@ def process_document(sess_data, action, selected_filename=None, chat_input=None,
284
  rfp_text = sess_data["uploaded_documents"][selected_filename]
285
  proposal_text = sess_data["proposals"][selected_proposal_filename]
286
  logging.info(f"Compliance check: comparing proposal [{selected_proposal_filename}] to RFP [{selected_filename}]")
287
- prompt = (
288
- "You are a proposal compliance expert. Use the following RFP/SOW/PWS/RFI and the generated proposal response. "
289
- "Compare the proposal to the RFP requirements and win themes. "
290
- "For each PWS section/requirement, determine if the proposal fully, partially, or does not address the requirement and win theme. "
291
- "For each, give a finding and a recommendation to recover for compliance or to strengthen the response. "
292
- "Return ONLY a markdown table (NO comments, NO intro, NO outro, NO summary) with the following columns: "
293
- "| PWS Section Number | Section Name | Requirement Description | Finding | Recommendation to Recover for Compliance |. "
294
- "Be concise and focus on actionable compliance gaps. Only the table, nothing else.\n\n"
295
- f"---\nRFP/SOW/PWS/RFI ({selected_filename}):\n{rfp_text}\n"
296
- "---\nGenerated Proposal Document:\n"
297
- f"{proposal_text}\n"
298
- )
299
  result = gemini_generate_content(prompt, file_id=None, chat_input=None)
300
  if result and not result.startswith("Error"):
301
  xlsx_bytes = save_markdown_as_xlsx(result, selected_filename)
@@ -315,17 +323,10 @@ def process_document(sess_data, action, selected_filename=None, chat_input=None,
315
  rfp_text = sess_data["uploaded_documents"][selected_filename]
316
  proposal_text = sess_data["proposals"][selected_proposal_filename]
317
  logging.info(f"Evaluation Board: extracting criteria from RFP [{selected_filename}], evaluating proposal [{selected_proposal_filename}]")
318
- prompt = (
319
- "You are a federal acquisition evaluation board. Your job is to extract Section L and Section M (evaluation criteria) from the following RFP/SOW/PWS/RFI if they exist. "
320
- "If Section L or Section M are not present, then read all requirements and develop a set of evaluation criteria that would be appropriate for this type of acquisition. "
321
- "List each evaluation criterion exactly as it appears in the document or as you have developed. "
322
- "For each extracted or developed evaluation criterion, evaluate the provided proposal and rate it as exactly one of: unacceptable, acceptable, good, or outstanding (no other ratings allowed). Add a column to explain the reason for the rating. Also include a column for recommendations to remediate the document so that it gets a better rating "
323
- "Return ONLY a markdown spreadsheet/table (NO intro, NO outro, NO comments, NO summary) with exactly these columns: | Evaluation Criteria | Evaluation | Reason | Recommendation |"
324
- "Each row should have the criterion exactly as extracted or developed, and the evaluation for how well the proposal meets or exceeds it. Only the table, nothing else.\n\n"
325
- f"---\nRFP/SOW/PWS/RFI ({selected_filename}):\n{rfp_text}\n"
326
- "---\nProposal Document:\n"
327
- f"{proposal_text}\n"
328
- )
329
  result = gemini_generate_content(prompt, file_id=None, chat_input=None)
330
  if result and not result.startswith("Error"):
331
  xlsx_bytes = save_markdown_as_xlsx(result, selected_filename)
@@ -351,14 +352,9 @@ def process_document(sess_data, action, selected_filename=None, chat_input=None,
351
  logging.info(f"RFP file {rfp_filename} uploaded to Gemini for proposal.")
352
  except Exception as e:
353
  logging.error(f"Failed to upload RFP file {rfp_filename} for proposal: {e}")
354
- prompt = (
355
- "Respond to the following RFP/SOW/PWS/RFI by creating a highly detailed proposal response that follows each section and subsection header. "
356
- "The response to each section and subsection will be compliant and compelling, focusing on describing the approach, and how the labor category uses a specific industry standard process in a workflow described in steps, and how technology is used. "
357
- "You must show innovation in the approach. Refer to research that validates the approach and cite sources with measurable outcome. "
358
- "Be sure to respond in paragraph format only, never use numbering, or bullets, only paragraph describing in detail.Return only the proposal response in markdown and nothing else, no comments, no intro, no outro, just the proposal\n"
359
- )
360
  if chat_input:
361
- prompt += f"User additional instructions: {chat_input}\n"
362
  prompt += f"\n---\nRFP/SOW/PWS/RFI ({rfp_filename}):\n{doc_content}\n"
363
  result = gemini_generate_content(prompt, file_id=rfp_fileid, chat_input=chat_input)
364
  sess_data["generated_response"] = result
@@ -381,20 +377,11 @@ def process_document(sess_data, action, selected_filename=None, chat_input=None,
381
 
382
  findings_content = sess_data["uploaded_documents"][selected_filename]
383
  proposal_text = sess_data["proposals"][selected_proposal_filename]
384
- prompt = (
385
- "You are a proposal compliance recovery expert. Use the findings and recommendations table and the original proposal response provided below. "
386
- "Address ONLY those sections of the proposal that have a finding and a recommendation for improvement. "
387
- "Do NOT change sections that are marked as fully compliant or already fully address the requirements. "
388
- "For each section that needs fixing, revise it in the proposal to address the recommendation for compliance or to strengthen the response. "
389
- "Return the full proposal with only the necessary sections revised, and leave all other sections untouched. "
390
- "Do not add any introduction, summary, or comments. Return only the revised proposal in markdown, nothing else.\n"
391
- )
392
  if chat_input:
393
- prompt += f"User additional instructions: {chat_input}\n"
394
-
395
  prompt += f"\n---\nFindings and Recommendations Table ({selected_filename}):\n{findings_content}\n"
396
  prompt += f"\n---\nOriginal Proposal Document ({selected_proposal_filename}):\n{proposal_text}\n"
397
-
398
  result = gemini_generate_content(prompt, file_id=None, chat_input=chat_input)
399
  if result and not result.startswith("Error"):
400
  base_name = os.path.splitext(selected_proposal_filename)[0]
@@ -414,21 +401,9 @@ def process_document(sess_data, action, selected_filename=None, chat_input=None,
414
  return "No proposal document selected for LOE estimation.", None, None, None, None
415
  proposal_text = sess_data["proposals"][selected_proposal_filename]
416
  proposal_base_name = os.path.splitext(selected_proposal_filename)[0]
417
- prompt = (
418
- "You are a federal proposal cost and level of effort estimator. "
419
- "Analyze the following proposal response which is structured to map to a government RFP, PWS, or SOW. "
420
- "For each PWS task or requirement referenced in the proposal, estimate the labor categories and a conservative, overestimated number of hours for each labor category required to accomplish that task. "
421
- "Include a management reserve to ensure the estimate is not underestimated. "
422
- "Return ONLY a markdown table (NO comments, NO intro, NO outro, NO summary) with the following columns: "
423
- "| PWS Task Number | Brief Task Description | Labor Category | Estimated Hours (including management reserve) | "
424
- "For each task, if more than one labor category is needed, list each category on its own row under the same task. "
425
- "Be sure to break down by detailed task, not just high level sections. "
426
- "Be detailed and thorough in your estimation and make sure to overestimate hours to ensure sufficient coverage. "
427
- "If the proposal references any assumed task number or section, use it in the table. "
428
- "Return ONLY the markdown table, no other text, no intro, no outro.\n\n"
429
- )
430
  if chat_input:
431
- prompt += f"User additional instructions: {chat_input}\n"
432
  prompt += f"\n---\nProposal Document ({selected_proposal_filename}):\n{proposal_text}\n"
433
  result = gemini_generate_content(prompt, file_id=None, chat_input=chat_input)
434
  if result and not result.startswith("Error"):
@@ -737,7 +712,6 @@ def master_callback(
737
  uploaded_rfp_decoded_bytes = None
738
 
739
  if triggered_id == 'cancel-action-btn':
740
- # Release Gemini lock if held, to allow cancellation of Gemini operation
741
  lock = sess_data.get("gemini_lock")
742
  if lock and lock.locked():
743
  try:
 
33
 
34
  SESSION_STORE = {}
35
 
36
+ PROMPT_FILES = {
37
+ 'shred': 'prompt_shred',
38
+ 'loe': 'prompt_LOE',
39
+ 'compliance': 'prompt_compliance',
40
+ 'proposal': 'prompt_proposal',
41
+ 'recover': 'prompt_recover',
42
+ 'virtual_board': 'prompt_virtual_board'
43
+ }
44
+
45
+ def read_prompt_file(prompt_type):
46
+ fname = PROMPT_FILES.get(prompt_type)
47
+ if not fname:
48
+ return f"[Error: No prompt file mapping for {prompt_type}]"
49
+ try:
50
+ with open(fname, 'r', encoding='utf-8') as f:
51
+ return f.read().strip()
52
+ except Exception as e:
53
+ logging.error(f"Could not read prompt file {fname}: {e}")
54
+ return f"[Error: Could not read prompt file for {prompt_type}]"
55
+
56
  def get_session_id_from_cookie(cookie_str):
57
  if not cookie_str:
58
  return None
 
276
  if not doc_content:
277
  logging.warning("No uploaded document found for shredding.")
278
  return "No document uploaded.", None, None, None, None
279
+ prompt = read_prompt_file('shred')
 
 
 
 
280
  if chat_input:
281
+ prompt += f"\nUser additional instructions: {chat_input}\n"
282
  prompt += f"\nFile Name: {selected_filename}\n\n"
283
  prompt += doc_content
284
  result = gemini_generate_content(prompt, file_id=doc_fileid, chat_input=chat_input)
 
300
  rfp_text = sess_data["uploaded_documents"][selected_filename]
301
  proposal_text = sess_data["proposals"][selected_proposal_filename]
302
  logging.info(f"Compliance check: comparing proposal [{selected_proposal_filename}] to RFP [{selected_filename}]")
303
+ prompt = read_prompt_file('compliance')
304
+ prompt += f"\n---\nRFP/SOW/PWS/RFI ({selected_filename}):\n{rfp_text}\n"
305
+ prompt += "---\nGenerated Proposal Document:\n"
306
+ prompt += f"{proposal_text}\n"
 
 
 
 
 
 
 
 
307
  result = gemini_generate_content(prompt, file_id=None, chat_input=None)
308
  if result and not result.startswith("Error"):
309
  xlsx_bytes = save_markdown_as_xlsx(result, selected_filename)
 
323
  rfp_text = sess_data["uploaded_documents"][selected_filename]
324
  proposal_text = sess_data["proposals"][selected_proposal_filename]
325
  logging.info(f"Evaluation Board: extracting criteria from RFP [{selected_filename}], evaluating proposal [{selected_proposal_filename}]")
326
+ prompt = read_prompt_file('virtual_board')
327
+ prompt += f"\n---\nRFP/SOW/PWS/RFI ({selected_filename}):\n{rfp_text}\n"
328
+ prompt += "---\nProposal Document:\n"
329
+ prompt += f"{proposal_text}\n"
 
 
 
 
 
 
 
330
  result = gemini_generate_content(prompt, file_id=None, chat_input=None)
331
  if result and not result.startswith("Error"):
332
  xlsx_bytes = save_markdown_as_xlsx(result, selected_filename)
 
352
  logging.info(f"RFP file {rfp_filename} uploaded to Gemini for proposal.")
353
  except Exception as e:
354
  logging.error(f"Failed to upload RFP file {rfp_filename} for proposal: {e}")
355
+ prompt = read_prompt_file('proposal')
 
 
 
 
 
356
  if chat_input:
357
+ prompt += f"\nUser additional instructions: {chat_input}\n"
358
  prompt += f"\n---\nRFP/SOW/PWS/RFI ({rfp_filename}):\n{doc_content}\n"
359
  result = gemini_generate_content(prompt, file_id=rfp_fileid, chat_input=chat_input)
360
  sess_data["generated_response"] = result
 
377
 
378
  findings_content = sess_data["uploaded_documents"][selected_filename]
379
  proposal_text = sess_data["proposals"][selected_proposal_filename]
380
+ prompt = read_prompt_file('recover')
 
 
 
 
 
 
 
381
  if chat_input:
382
+ prompt += f"\nUser additional instructions: {chat_input}\n"
 
383
  prompt += f"\n---\nFindings and Recommendations Table ({selected_filename}):\n{findings_content}\n"
384
  prompt += f"\n---\nOriginal Proposal Document ({selected_proposal_filename}):\n{proposal_text}\n"
 
385
  result = gemini_generate_content(prompt, file_id=None, chat_input=chat_input)
386
  if result and not result.startswith("Error"):
387
  base_name = os.path.splitext(selected_proposal_filename)[0]
 
401
  return "No proposal document selected for LOE estimation.", None, None, None, None
402
  proposal_text = sess_data["proposals"][selected_proposal_filename]
403
  proposal_base_name = os.path.splitext(selected_proposal_filename)[0]
404
+ prompt = read_prompt_file('loe')
 
 
 
 
 
 
 
 
 
 
 
 
405
  if chat_input:
406
+ prompt += f"\nUser additional instructions: {chat_input}\n"
407
  prompt += f"\n---\nProposal Document ({selected_proposal_filename}):\n{proposal_text}\n"
408
  result = gemini_generate_content(prompt, file_id=None, chat_input=chat_input)
409
  if result and not result.startswith("Error"):
 
712
  uploaded_rfp_decoded_bytes = None
713
 
714
  if triggered_id == 'cancel-action-btn':
 
715
  lock = sess_data.get("gemini_lock")
716
  if lock and lock.locked():
717
  try: