Spaces:
Paused
Paused
Update app.py via AI Editor
Browse files
app.py
CHANGED
@@ -256,11 +256,48 @@ def process_document(action, selected_filename=None, chat_input=None, rfp_decode
|
|
256 |
elif action == 'recover':
|
257 |
# For recover: need compliance check or shred (selected_filename), and proposal (selected_proposal_filename)
|
258 |
if not selected_proposal_filename or selected_proposal_filename not in proposals:
|
|
|
259 |
return "No proposal document selected for recovery.", None, None, None, None
|
260 |
if not selected_filename or selected_filename not in uploaded_documents:
|
|
|
261 |
return "No compliance check or shredded requirements document selected for recovery.", None, None, None, None
|
|
|
262 |
findings_content = uploaded_documents[selected_filename]
|
263 |
proposal_text = proposals[selected_proposal_filename]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
264 |
logging.info(f"Recovery: fixing proposal [{selected_proposal_filename}] based on findings [{selected_filename}]")
|
265 |
prompt = (
|
266 |
"You are a proposal compliance recovery expert. Use the following findings and recommendations table, and the original proposal response. "
|
@@ -269,21 +306,33 @@ def process_document(action, selected_filename=None, chat_input=None, rfp_decode
|
|
269 |
"For each section that needs fixing, revise it in the proposal to address the recommendation for compliance or to strengthen the response. "
|
270 |
"Return the full proposal with only the necessary sections revised, and leave all other sections untouched. "
|
271 |
"Do not add any introduction, summary, or comments. Return only the revised proposal in markdown, nothing else.\n\n"
|
|
|
|
|
|
|
|
|
272 |
"Findings and Recommendations Table or Requirements Table:\n"
|
273 |
f"{findings_content}\n"
|
274 |
"---\nOriginal Proposal:\n"
|
275 |
f"{proposal_text}\n"
|
276 |
)
|
277 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
278 |
if result and not result.startswith("Error"):
|
279 |
-
# Name for the recovered proposal: <original proposal base>_recovered.docx
|
280 |
base_name = os.path.splitext(selected_proposal_filename)[0]
|
281 |
recovered_docx_name = f"{base_name}_recovered.docx"
|
282 |
docx_bytes = save_proposal_as_docx(result, base_name)
|
283 |
proposals[recovered_docx_name] = result
|
284 |
proposals_fileid[recovered_docx_name] = None
|
|
|
285 |
return result, None, None, recovered_docx_name, docx_bytes
|
286 |
else:
|
|
|
287 |
return result, None, None, None, None
|
288 |
|
289 |
elif action == 'loe':
|
@@ -645,7 +694,6 @@ def master_callback(
|
|
645 |
output_data_upload = dcc.Markdown(result, style={"whiteSpace": "pre-wrap", "wordWrap": "break-word"})
|
646 |
elif triggered_id == "recover-action-btn":
|
647 |
action_name = "recover"
|
648 |
-
# For recover, use selected compliance/shred doc (doc_value) and selected proposal (proposal_value)
|
649 |
result, _, _, generated_filename, generated_docx_bytes = process_document(
|
650 |
action_name, doc_value, chat_input, None, proposal_value
|
651 |
)
|
|
|
256 |
elif action == 'recover':
|
257 |
# For recover: need compliance check or shred (selected_filename), and proposal (selected_proposal_filename)
|
258 |
if not selected_proposal_filename or selected_proposal_filename not in proposals:
|
259 |
+
logging.error("No proposal document selected for recovery.")
|
260 |
return "No proposal document selected for recovery.", None, None, None, None
|
261 |
if not selected_filename or selected_filename not in uploaded_documents:
|
262 |
+
logging.error("No compliance check or shredded requirements document selected for recovery.")
|
263 |
return "No compliance check or shredded requirements document selected for recovery.", None, None, None, None
|
264 |
+
|
265 |
findings_content = uploaded_documents[selected_filename]
|
266 |
proposal_text = proposals[selected_proposal_filename]
|
267 |
+
findings_fileid = uploaded_documents_fileid.get(selected_filename)
|
268 |
+
proposal_fileid = proposals_fileid.get(selected_proposal_filename)
|
269 |
+
|
270 |
+
# Upload findings doc if not already uploaded
|
271 |
+
if not findings_fileid:
|
272 |
+
if selected_filename in shredded_documents:
|
273 |
+
findings_bytes = shredded_documents[selected_filename]
|
274 |
+
elif selected_filename in uploaded_documents_bytes:
|
275 |
+
findings_bytes = uploaded_documents_bytes[selected_filename]
|
276 |
+
else:
|
277 |
+
findings_bytes = None
|
278 |
+
if findings_bytes:
|
279 |
+
try:
|
280 |
+
findings_fileid = upload_to_gemini_file(findings_bytes, selected_filename)
|
281 |
+
if findings_fileid:
|
282 |
+
uploaded_documents_fileid[selected_filename] = findings_fileid
|
283 |
+
logging.info(f"Findings/Compliance doc {selected_filename} uploaded to Gemini for recover.")
|
284 |
+
except Exception as e:
|
285 |
+
logging.error(f"Failed to upload findings doc {selected_filename} for recover: {e}")
|
286 |
+
|
287 |
+
# Upload proposal doc if not already uploaded
|
288 |
+
if not proposal_fileid:
|
289 |
+
proposal_bytes = None
|
290 |
+
if selected_proposal_filename in proposals:
|
291 |
+
proposal_bytes = save_proposal_as_docx(proposals[selected_proposal_filename], selected_proposal_filename)
|
292 |
+
if proposal_bytes:
|
293 |
+
try:
|
294 |
+
proposal_fileid = upload_to_gemini_file(proposal_bytes, selected_proposal_filename)
|
295 |
+
if proposal_fileid:
|
296 |
+
proposals_fileid[selected_proposal_filename] = proposal_fileid
|
297 |
+
logging.info(f"Proposal doc {selected_proposal_filename} uploaded to Gemini for recover.")
|
298 |
+
except Exception as e:
|
299 |
+
logging.error(f"Failed to upload proposal doc {selected_proposal_filename} for recover: {e}")
|
300 |
+
|
301 |
logging.info(f"Recovery: fixing proposal [{selected_proposal_filename}] based on findings [{selected_filename}]")
|
302 |
prompt = (
|
303 |
"You are a proposal compliance recovery expert. Use the following findings and recommendations table, and the original proposal response. "
|
|
|
306 |
"For each section that needs fixing, revise it in the proposal to address the recommendation for compliance or to strengthen the response. "
|
307 |
"Return the full proposal with only the necessary sections revised, and leave all other sections untouched. "
|
308 |
"Do not add any introduction, summary, or comments. Return only the revised proposal in markdown, nothing else.\n\n"
|
309 |
+
)
|
310 |
+
if chat_input:
|
311 |
+
prompt += f"User additional instructions: {chat_input}\n"
|
312 |
+
prompt += (
|
313 |
"Findings and Recommendations Table or Requirements Table:\n"
|
314 |
f"{findings_content}\n"
|
315 |
"---\nOriginal Proposal:\n"
|
316 |
f"{proposal_text}\n"
|
317 |
)
|
318 |
+
# If both are present, use both as file context for Gemini
|
319 |
+
used_fileid = None
|
320 |
+
if findings_fileid:
|
321 |
+
used_fileid = findings_fileid
|
322 |
+
elif proposal_fileid:
|
323 |
+
used_fileid = proposal_fileid
|
324 |
+
|
325 |
+
result = gemini_generate_content(prompt, file_id=used_fileid, chat_input=chat_input)
|
326 |
if result and not result.startswith("Error"):
|
|
|
327 |
base_name = os.path.splitext(selected_proposal_filename)[0]
|
328 |
recovered_docx_name = f"{base_name}_recovered.docx"
|
329 |
docx_bytes = save_proposal_as_docx(result, base_name)
|
330 |
proposals[recovered_docx_name] = result
|
331 |
proposals_fileid[recovered_docx_name] = None
|
332 |
+
logging.info(f"Recovered proposal generated and saved as {recovered_docx_name}.")
|
333 |
return result, None, None, recovered_docx_name, docx_bytes
|
334 |
else:
|
335 |
+
logging.error(f"Error in Gemini recover: {result}")
|
336 |
return result, None, None, None, None
|
337 |
|
338 |
elif action == 'loe':
|
|
|
694 |
output_data_upload = dcc.Markdown(result, style={"whiteSpace": "pre-wrap", "wordWrap": "break-word"})
|
695 |
elif triggered_id == "recover-action-btn":
|
696 |
action_name = "recover"
|
|
|
697 |
result, _, _, generated_filename, generated_docx_bytes = process_document(
|
698 |
action_name, doc_value, chat_input, None, proposal_value
|
699 |
)
|