Spaces:
Paused
Paused
Update app.py via AI Editor
Browse files
app.py
CHANGED
|
@@ -132,13 +132,13 @@ def save_proposal_as_docx(proposal_text, base_filename):
|
|
| 132 |
memf.seek(0)
|
| 133 |
return memf.read()
|
| 134 |
|
| 135 |
-
def process_document(action, selected_filename=None, chat_input=None
|
| 136 |
global shredded_document, generated_response
|
| 137 |
logging.info(f"Process document called with action: {action}")
|
| 138 |
|
| 139 |
doc_content = None
|
| 140 |
doc_fileid = None
|
| 141 |
-
if action in ["shred", "generate"]:
|
| 142 |
if selected_filename and selected_filename in uploaded_documents:
|
| 143 |
doc_content = uploaded_documents[selected_filename]
|
| 144 |
doc_fileid = uploaded_documents_fileid.get(selected_filename)
|
|
@@ -149,8 +149,6 @@ def process_document(action, selected_filename=None, chat_input=None, selected_p
|
|
| 149 |
else:
|
| 150 |
doc_content = None
|
| 151 |
doc_fileid = None
|
| 152 |
-
elif action == "proposal":
|
| 153 |
-
pass
|
| 154 |
|
| 155 |
if action == 'shred':
|
| 156 |
if not doc_content:
|
|
@@ -225,45 +223,21 @@ def process_document(action, selected_filename=None, chat_input=None, selected_p
|
|
| 225 |
return result_holder["text"], result_holder["docx_bytes"], result_holder["docx_name"]
|
| 226 |
|
| 227 |
elif action == 'proposal':
|
| 228 |
-
|
| 229 |
-
generated_doc_content = None
|
| 230 |
-
rfp_filename = selected_filename
|
| 231 |
-
generated_docname = selected_generated
|
| 232 |
-
rfp_fileid = uploaded_documents_fileid.get(selected_filename)
|
| 233 |
-
gen_fileid = None
|
| 234 |
-
if not (selected_filename and selected_filename in uploaded_documents):
|
| 235 |
logging.warning("No RFP/SOW/PWS/RFI document selected for proposal action.")
|
| 236 |
return "No RFP/SOW/PWS/RFI document selected.", None, None
|
| 237 |
-
|
| 238 |
-
|
| 239 |
-
return "No generated document selected.", None, None
|
| 240 |
-
rfp_content = uploaded_documents[selected_filename]
|
| 241 |
-
gen_bytes = generated_documents[selected_generated]
|
| 242 |
-
try:
|
| 243 |
-
try:
|
| 244 |
-
docx_stream = io.BytesIO(gen_bytes)
|
| 245 |
-
doc = Document(docx_stream)
|
| 246 |
-
generated_doc_content = "\n".join([para.text for para in doc.paragraphs])
|
| 247 |
-
except Exception as e:
|
| 248 |
-
try:
|
| 249 |
-
generated_doc_content = gen_bytes.decode('utf-8')
|
| 250 |
-
except Exception:
|
| 251 |
-
generated_doc_content = "<Unable to decode generated document.>"
|
| 252 |
-
except Exception as e:
|
| 253 |
-
generated_doc_content = "<Unable to read generated document.>"
|
| 254 |
-
logging.error(f"Failed to read generated document: {e}")
|
| 255 |
-
|
| 256 |
prompt = (
|
| 257 |
-
"Respond to the following RFP/SOW/PWS/RFI
|
| 258 |
"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. "
|
| 259 |
"You must show innovation in the approach. Refer to research that validates the approach and cite sources with measurable outcome. "
|
| 260 |
"Be sure to respond in paragraph format only, never use numbering, or bullets, only paragraph describing in detail.\n"
|
| 261 |
)
|
| 262 |
if chat_input:
|
| 263 |
prompt += f"User additional instructions: {chat_input}\n"
|
| 264 |
-
prompt += f"\n---\nRFP/SOW/PWS/RFI ({rfp_filename}):\n"
|
| 265 |
-
prompt
|
| 266 |
-
logging.info(f"Sending proposal prompt to Gemini. RFP: {rfp_filename}, Generated Doc: {generated_docname}")
|
| 267 |
result_holder = {"text": None, "docx_bytes": None, "docx_name": None}
|
| 268 |
def thread_proposal():
|
| 269 |
try:
|
|
@@ -271,7 +245,7 @@ def process_document(action, selected_filename=None, chat_input=None, selected_p
|
|
| 271 |
response = gemini_generate_content(prompt, file_id=rfp_fileid, chat_input=chat_input)
|
| 272 |
logging.info("Received proposal results from Gemini.")
|
| 273 |
docx_bytes = save_proposal_as_docx(response, rfp_filename)
|
| 274 |
-
generated_docx_name = f"{os.path.splitext(rfp_filename)[0]}
|
| 275 |
result_holder["text"] = response
|
| 276 |
result_holder["docx_bytes"] = docx_bytes
|
| 277 |
result_holder["docx_name"] = generated_docx_name
|
|
@@ -649,14 +623,11 @@ def master_callback(
|
|
| 649 |
|
| 650 |
elif triggered_id == 'proposal-action-btn':
|
| 651 |
rfp_doc = selected_filename
|
| 652 |
-
|
| 653 |
-
logging.info(f"Starting proposal streaming with RFP: {rfp_doc}, Generated Doc: {gen_doc}")
|
| 654 |
result, generated_docx_bytes, generated_docx_name = process_document(
|
| 655 |
'proposal',
|
| 656 |
rfp_doc,
|
| 657 |
-
chat_input
|
| 658 |
-
None,
|
| 659 |
-
gen_doc
|
| 660 |
)
|
| 661 |
if generated_docx_bytes and generated_docx_name:
|
| 662 |
generated_documents[generated_docx_name] = generated_docx_bytes
|
|
|
|
| 132 |
memf.seek(0)
|
| 133 |
return memf.read()
|
| 134 |
|
| 135 |
+
def process_document(action, selected_filename=None, chat_input=None):
|
| 136 |
global shredded_document, generated_response
|
| 137 |
logging.info(f"Process document called with action: {action}")
|
| 138 |
|
| 139 |
doc_content = None
|
| 140 |
doc_fileid = None
|
| 141 |
+
if action in ["shred", "generate", "proposal"]:
|
| 142 |
if selected_filename and selected_filename in uploaded_documents:
|
| 143 |
doc_content = uploaded_documents[selected_filename]
|
| 144 |
doc_fileid = uploaded_documents_fileid.get(selected_filename)
|
|
|
|
| 149 |
else:
|
| 150 |
doc_content = None
|
| 151 |
doc_fileid = None
|
|
|
|
|
|
|
| 152 |
|
| 153 |
if action == 'shred':
|
| 154 |
if not doc_content:
|
|
|
|
| 223 |
return result_holder["text"], result_holder["docx_bytes"], result_holder["docx_name"]
|
| 224 |
|
| 225 |
elif action == 'proposal':
|
| 226 |
+
if not doc_content:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 227 |
logging.warning("No RFP/SOW/PWS/RFI document selected for proposal action.")
|
| 228 |
return "No RFP/SOW/PWS/RFI document selected.", None, None
|
| 229 |
+
rfp_filename = selected_filename
|
| 230 |
+
rfp_fileid = uploaded_documents_fileid.get(selected_filename)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 231 |
prompt = (
|
| 232 |
+
"Respond to the following RFP/SOW/PWS/RFI by creating a highly detailed proposal response that follows each section and subsection header. "
|
| 233 |
"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. "
|
| 234 |
"You must show innovation in the approach. Refer to research that validates the approach and cite sources with measurable outcome. "
|
| 235 |
"Be sure to respond in paragraph format only, never use numbering, or bullets, only paragraph describing in detail.\n"
|
| 236 |
)
|
| 237 |
if chat_input:
|
| 238 |
prompt += f"User additional instructions: {chat_input}\n"
|
| 239 |
+
prompt += f"\n---\nRFP/SOW/PWS/RFI ({rfp_filename}):\n{doc_content}\n"
|
| 240 |
+
logging.info(f"Sending proposal prompt to Gemini. RFP: {rfp_filename}")
|
|
|
|
| 241 |
result_holder = {"text": None, "docx_bytes": None, "docx_name": None}
|
| 242 |
def thread_proposal():
|
| 243 |
try:
|
|
|
|
| 245 |
response = gemini_generate_content(prompt, file_id=rfp_fileid, chat_input=chat_input)
|
| 246 |
logging.info("Received proposal results from Gemini.")
|
| 247 |
docx_bytes = save_proposal_as_docx(response, rfp_filename)
|
| 248 |
+
generated_docx_name = f"{os.path.splitext(rfp_filename)[0]}_proposal.docx"
|
| 249 |
result_holder["text"] = response
|
| 250 |
result_holder["docx_bytes"] = docx_bytes
|
| 251 |
result_holder["docx_name"] = generated_docx_name
|
|
|
|
| 623 |
|
| 624 |
elif triggered_id == 'proposal-action-btn':
|
| 625 |
rfp_doc = selected_filename
|
| 626 |
+
logging.info(f"Starting proposal with RFP: {rfp_doc}")
|
|
|
|
| 627 |
result, generated_docx_bytes, generated_docx_name = process_document(
|
| 628 |
'proposal',
|
| 629 |
rfp_doc,
|
| 630 |
+
chat_input
|
|
|
|
|
|
|
| 631 |
)
|
| 632 |
if generated_docx_bytes and generated_docx_name:
|
| 633 |
generated_documents[generated_docx_name] = generated_docx_bytes
|