Spaces:
Paused
Paused
Update app.py via AI Editor
Browse files
app.py
CHANGED
@@ -8,8 +8,7 @@ import pandas as pd
|
|
8 |
import logging
|
9 |
from docx import Document
|
10 |
import mimetypes
|
11 |
-
from threading import
|
12 |
-
import threading
|
13 |
import time
|
14 |
|
15 |
import google.generativeai as genai
|
@@ -38,8 +37,6 @@ shredded_document = None
|
|
38 |
generated_response = None
|
39 |
|
40 |
gemini_lock = Lock()
|
41 |
-
stream_buffer = {"preview": ""}
|
42 |
-
stream_event = Event()
|
43 |
|
44 |
def decode_document(decoded_bytes):
|
45 |
try:
|
@@ -89,7 +86,7 @@ def upload_to_gemini_file(decoded_bytes, filename):
|
|
89 |
logging.error(f"Exception during file upload to Gemini: {e}")
|
90 |
return None
|
91 |
|
92 |
-
def
|
93 |
try:
|
94 |
files = []
|
95 |
if file_id:
|
@@ -111,19 +108,10 @@ def gemini_generate_content_stream(prompt, file_id=None, chat_input=None, cancel
|
|
111 |
)
|
112 |
)
|
113 |
result = response.text if hasattr(response, "text") else str(response)
|
114 |
-
|
115 |
-
for i in range(0, len(result), chunk_size):
|
116 |
-
if cancel_event is not None and cancel_event.is_set():
|
117 |
-
logging.info("Gemini stream cancelled by user.")
|
118 |
-
yield "[Cancelled by user]\n"
|
119 |
-
break
|
120 |
-
yield result[:i+chunk_size]
|
121 |
-
time.sleep(0.08)
|
122 |
-
if cancel_event is not None and cancel_event.is_set():
|
123 |
-
yield "[Cancelled by user]\n"
|
124 |
except Exception as e:
|
125 |
logging.error("Error during Gemini generate_content: %s", e)
|
126 |
-
|
127 |
|
128 |
def save_shredded_as_docx(shredded_text, rfp_filename):
|
129 |
doc = Document()
|
@@ -155,8 +143,8 @@ def save_compliance_as_docx(compliance_text, rfp_filename):
|
|
155 |
memf.seek(0)
|
156 |
return memf.read()
|
157 |
|
158 |
-
def process_document(action, selected_filename=None, chat_input=None, rfp_decoded_bytes=None,
|
159 |
-
global shredded_document, generated_response
|
160 |
|
161 |
logging.info(f"Process document called with action: {action}")
|
162 |
|
@@ -186,44 +174,17 @@ def process_document(action, selected_filename=None, chat_input=None, rfp_decode
|
|
186 |
if chat_input:
|
187 |
prompt += f"User additional instructions: {chat_input}\n"
|
188 |
prompt += f"\nFile Name: {selected_filename}\n\n"
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
break
|
201 |
-
result = stream_buffer["preview"]
|
202 |
-
shredded_document = result
|
203 |
-
if not cancel_event or not cancel_event.is_set():
|
204 |
-
docx_bytes = save_shredded_as_docx(result, selected_filename)
|
205 |
-
generated_docx_name = f"{os.path.splitext(selected_filename)[0]}_shredded.docx"
|
206 |
-
shredded_documents[generated_docx_name] = docx_bytes
|
207 |
-
result_holder["text"] = result
|
208 |
-
result_holder["docx_name"] = generated_docx_name
|
209 |
-
else:
|
210 |
-
result_holder["text"] = "[Cancelled by user]\n"
|
211 |
-
result_holder["docx_name"] = None
|
212 |
-
logging.info("Document shredded successfully.")
|
213 |
-
except Exception as e:
|
214 |
-
shredded_document = f"Error during shredding: {e}"
|
215 |
-
logging.error("Error in thread_shred: %s", e)
|
216 |
-
result_holder["text"] = shredded_document
|
217 |
-
|
218 |
-
shredded_document = "Shredding in progress..."
|
219 |
-
stream_buffer["preview"] = ""
|
220 |
-
t = Thread(target=thread_shred)
|
221 |
-
t.start()
|
222 |
-
t.join()
|
223 |
-
if result_holder["docx_name"] and result_holder["text"]:
|
224 |
-
if result_holder["docx_name"] not in uploaded_documents:
|
225 |
-
uploaded_documents[result_holder["docx_name"]] = result_holder["text"]
|
226 |
-
return result_holder["text"], None, result_holder["docx_name"], result_holder["text"]
|
227 |
|
228 |
elif action == 'proposal':
|
229 |
if not doc_content:
|
@@ -249,42 +210,16 @@ def process_document(action, selected_filename=None, chat_input=None, rfp_decode
|
|
249 |
if chat_input:
|
250 |
prompt += f"User additional instructions: {chat_input}\n"
|
251 |
prompt += f"\n---\nRFP/SOW/PWS/RFI ({rfp_filename}):\n{doc_content}\n"
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
stream_buffer["preview"] = partial
|
263 |
-
if cancel_event is not None and cancel_event.is_set():
|
264 |
-
break
|
265 |
-
response = stream_buffer["preview"]
|
266 |
-
generated_response = response
|
267 |
-
if not cancel_event or not cancel_event.is_set():
|
268 |
-
docx_bytes = save_proposal_as_docx(response, rfp_filename)
|
269 |
-
generated_docx_name = f"{os.path.splitext(rfp_filename)[0]}_proposal.docx"
|
270 |
-
uploaded_proposals[generated_docx_name] = response
|
271 |
-
uploaded_proposals_fileid[generated_docx_name] = None
|
272 |
-
result_holder["text"] = response
|
273 |
-
result_holder["docx_name"] = generated_docx_name
|
274 |
-
else:
|
275 |
-
result_holder["text"] = "[Cancelled by user]\n"
|
276 |
-
result_holder["docx_name"] = None
|
277 |
-
logging.info("Received proposal results from Gemini.")
|
278 |
-
except Exception as e:
|
279 |
-
generated_response = f"Error during Gemini completion: {e}"
|
280 |
-
logging.error("Error during Gemini proposal request: %s", e)
|
281 |
-
result_holder["text"] = generated_response
|
282 |
-
|
283 |
-
stream_buffer["preview"] = ""
|
284 |
-
t = Thread(target=thread_proposal)
|
285 |
-
t.start()
|
286 |
-
t.join()
|
287 |
-
return result_holder["text"], None, result_holder["docx_name"], result_holder["text"]
|
288 |
|
289 |
elif action == 'compliance':
|
290 |
if not selected_generated_filename or selected_generated_filename not in uploaded_proposals:
|
@@ -308,37 +243,15 @@ def process_document(action, selected_filename=None, chat_input=None, rfp_decode
|
|
308 |
"---\nGenerated Proposal Document:\n"
|
309 |
f"{proposal_text}\n"
|
310 |
)
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
if cancel_event is not None and cancel_event.is_set():
|
321 |
-
break
|
322 |
-
result = stream_buffer["preview"]
|
323 |
-
result_holder["text"] = result
|
324 |
-
if not cancel_event or not cancel_event.is_set():
|
325 |
-
docx_bytes = save_compliance_as_docx(result, selected_filename)
|
326 |
-
compliance_docx_name = f"{os.path.splitext(selected_filename)[0]}_compliance_check.docx"
|
327 |
-
uploaded_documents[compliance_docx_name] = result
|
328 |
-
shredded_documents[compliance_docx_name] = docx_bytes
|
329 |
-
result_holder["docx_name"] = compliance_docx_name
|
330 |
-
else:
|
331 |
-
result_holder["docx_name"] = None
|
332 |
-
logging.info("Compliance check completed.")
|
333 |
-
except Exception as e:
|
334 |
-
logging.error("Error during compliance check: %s", e)
|
335 |
-
result_holder["text"] = f"Error during compliance check: {e}"
|
336 |
-
|
337 |
-
stream_buffer["preview"] = ""
|
338 |
-
t = Thread(target=thread_compliance)
|
339 |
-
t.start()
|
340 |
-
t.join()
|
341 |
-
return result_holder["text"], None, result_holder["docx_name"], result_holder["text"]
|
342 |
|
343 |
elif action == 'recover':
|
344 |
return "Recovery not implemented yet.", None, None, None
|
@@ -427,10 +340,6 @@ def get_uploaded_proposal_list(docdict):
|
|
427 |
return dbc.ListGroup(doc_list, flush=True)
|
428 |
|
429 |
app.layout = dbc.Container([
|
430 |
-
dcc.Store(id='shred-store', data={'text': None, 'docx_name': None}),
|
431 |
-
dcc.Store(id='proposal-store', data={'text': None, 'docx_name': None}),
|
432 |
-
dcc.Store(id='stream-status', data={'streaming': False}),
|
433 |
-
dcc.Interval(id='stream-interval', interval=5000, n_intervals=0, disabled=True),
|
434 |
dbc.Row([
|
435 |
dbc.Col([
|
436 |
dbc.Card([
|
@@ -531,8 +440,6 @@ app.layout = dbc.Container([
|
|
531 |
], fluid=True)
|
532 |
|
533 |
@app.callback(
|
534 |
-
Output('shred-store', 'data'),
|
535 |
-
Output('proposal-store', 'data'),
|
536 |
Output('output-data-upload', 'children'),
|
537 |
Output('uploaded-doc-list', 'children'),
|
538 |
Output('select-document-dropdown', 'options'),
|
@@ -541,8 +448,6 @@ app.layout = dbc.Container([
|
|
541 |
Output('uploaded-proposal-list', 'children'),
|
542 |
Output('select-proposal-dropdown', 'options'),
|
543 |
Output('select-proposal-dropdown', 'value'),
|
544 |
-
Output('stream-status', 'data'),
|
545 |
-
Output('stream-interval', 'disabled'),
|
546 |
[
|
547 |
Input('shred-action-btn', 'n_clicks'),
|
548 |
Input('proposal-action-btn', 'n_clicks'),
|
@@ -561,9 +466,7 @@ app.layout = dbc.Container([
|
|
561 |
State('chat-input', 'value'),
|
562 |
State('select-document-dropdown', 'value'),
|
563 |
State('select-proposal-dropdown', 'value'),
|
564 |
-
Input('cancel-action-btn', 'n_clicks')
|
565 |
-
Input('stream-interval', 'n_intervals'),
|
566 |
-
State('stream-status', 'data') # <-- Moved this to the last State, matching the last argument
|
567 |
],
|
568 |
prevent_initial_call=True
|
569 |
)
|
@@ -574,8 +477,7 @@ def master_callback(
|
|
574 |
shredded_delete_clicks, shredded_doc_children,
|
575 |
select_proposal_dropdown_value,
|
576 |
chat_input, selected_filename, selected_proposal_dropdown, selected_proposal_dropdown_state,
|
577 |
-
cancel_clicks
|
578 |
-
stream_n_intervals, stream_status
|
579 |
):
|
580 |
ctx = callback_context
|
581 |
triggered_id = ctx.triggered[0]['prop_id'].split('.')[0] if ctx.triggered else None
|
@@ -588,46 +490,15 @@ def master_callback(
|
|
588 |
|
589 |
upload_triggered = False
|
590 |
|
591 |
-
shred_store = {'text': None, 'docx_name': None}
|
592 |
-
proposal_store = {'text': None, 'docx_name': None}
|
593 |
-
streaming = False
|
594 |
-
|
595 |
rfp_delete_clicks = safe_get_n_clicks(ctx, 5)
|
596 |
proposal_delete_clicks = safe_get_n_clicks(ctx, 9)
|
597 |
shredded_delete_clicks = safe_get_n_clicks(ctx, 11)
|
598 |
|
599 |
uploaded_rfp_decoded_bytes = None
|
600 |
|
601 |
-
global gemini_lock
|
602 |
-
|
603 |
-
if triggered_id == 'stream-interval':
|
604 |
-
if not stream_status or not stream_status.get('streaming'):
|
605 |
-
return dash.no_update, dash.no_update, dash.no_update, dash.no_update, dash.no_update, dash.no_update, dash.no_update, dash.no_update, dash.no_update, dash.no_update, stream_status, True
|
606 |
-
preview = stream_buffer.get("preview", "")
|
607 |
-
still_streaming = gemini_lock.locked()
|
608 |
-
if not still_streaming:
|
609 |
-
stream_status['streaming'] = False
|
610 |
-
output_data_upload = dcc.Markdown(preview, style={"whiteSpace": "pre-wrap", "wordWrap": "break-word"})
|
611 |
-
doc_options = [{'label': fn, 'value': fn} for fn in uploaded_documents.keys()]
|
612 |
-
doc_value = selected_doc if selected_doc in uploaded_documents else (next(iter(uploaded_documents), None) if uploaded_documents else None)
|
613 |
-
shredded_doc_list_items = get_shredded_doc_list(shredded_documents)
|
614 |
-
uploaded_doc_list = get_uploaded_doc_list(uploaded_documents)
|
615 |
-
uploaded_proposal_list = get_uploaded_proposal_list(uploaded_proposals)
|
616 |
-
proposal_options = [{'label': fn, 'value': fn} for fn in uploaded_proposals.keys()]
|
617 |
-
proposal_value = select_proposal_dropdown_value if select_proposal_dropdown_value in uploaded_proposals else (next(iter(uploaded_proposals), None) if uploaded_proposals else None)
|
618 |
-
return (
|
619 |
-
shred_store, proposal_store, output_data_upload,
|
620 |
-
uploaded_doc_list, doc_options, doc_value,
|
621 |
-
shredded_doc_list_items,
|
622 |
-
uploaded_proposal_list, proposal_options, proposal_value,
|
623 |
-
stream_status,
|
624 |
-
True
|
625 |
-
)
|
626 |
-
return dash.no_update, dash.no_update, dcc.Markdown(preview, style={"whiteSpace": "pre-wrap", "wordWrap": "break-word"}), dash.no_update, dash.no_update, dash.no_update, dash.no_update, dash.no_update, dash.no_update, dash.no_update, stream_status, False
|
627 |
|
628 |
if triggered_id == 'cancel-action-btn':
|
629 |
-
stream_event.set()
|
630 |
-
streaming = False
|
631 |
output_data_upload = html.Div("[Cancelled by user]\n", style={"wordWrap": "break-word"})
|
632 |
doc_options = [{'label': fn, 'value': fn} for fn in uploaded_documents.keys()]
|
633 |
doc_value = selected_doc if selected_doc in uploaded_documents else (next(iter(uploaded_documents), None) if uploaded_documents else None)
|
@@ -637,12 +508,10 @@ def master_callback(
|
|
637 |
proposal_options = [{'label': fn, 'value': fn} for fn in uploaded_proposals.keys()]
|
638 |
proposal_value = select_proposal_dropdown_value if select_proposal_dropdown_value in uploaded_proposals else (next(iter(uploaded_proposals), None) if uploaded_proposals else None)
|
639 |
return (
|
640 |
-
|
641 |
uploaded_doc_list, doc_options, doc_value,
|
642 |
shredded_doc_list_items,
|
643 |
-
uploaded_proposal_list, proposal_options, proposal_value
|
644 |
-
{'streaming': False},
|
645 |
-
True
|
646 |
)
|
647 |
|
648 |
if triggered_id == 'upload-document' and rfp_content is not None and rfp_filename:
|
@@ -742,33 +611,29 @@ def master_callback(
|
|
742 |
if not got_lock:
|
743 |
output_data_upload = html.Div("Another Gemini operation is in progress. Please wait or cancel.", style={"wordWrap": "break-word"})
|
744 |
return (
|
745 |
-
|
746 |
uploaded_doc_list, doc_options, doc_value,
|
747 |
shredded_doc_list_items,
|
748 |
-
uploaded_proposal_list, proposal_options, proposal_value
|
749 |
-
{'streaming': False},
|
750 |
-
True
|
751 |
)
|
752 |
-
|
753 |
-
|
754 |
-
|
755 |
-
|
756 |
-
|
757 |
-
|
758 |
-
|
759 |
-
|
760 |
-
|
761 |
-
|
762 |
-
|
763 |
-
|
764 |
-
|
765 |
return (
|
766 |
-
|
767 |
uploaded_doc_list, doc_options, doc_value,
|
768 |
shredded_doc_list_items,
|
769 |
-
uploaded_proposal_list, proposal_options, proposal_value
|
770 |
-
{'streaming': True},
|
771 |
-
False
|
772 |
)
|
773 |
|
774 |
if upload_triggered:
|
@@ -776,23 +641,19 @@ def master_callback(
|
|
776 |
proposal_value = proposal_value if proposal_value in uploaded_proposals else (next(iter(uploaded_proposals), None) if uploaded_proposals else None)
|
777 |
output_data_upload = html.Div("Upload/Delete completed.", style={"wordWrap": "break-word"})
|
778 |
return (
|
779 |
-
|
780 |
uploaded_doc_list, doc_options, doc_value,
|
781 |
shredded_doc_list_items,
|
782 |
-
uploaded_proposal_list, proposal_options, proposal_value
|
783 |
-
{'streaming': False},
|
784 |
-
True
|
785 |
)
|
786 |
|
787 |
doc_value = doc_value if doc_value in uploaded_documents else (next(iter(uploaded_documents), None) if uploaded_documents else None)
|
788 |
proposal_value = proposal_value if proposal_value in uploaded_proposals else (next(iter(uploaded_proposals), None) if uploaded_proposals else None)
|
789 |
return (
|
790 |
-
|
791 |
uploaded_doc_list, doc_options, doc_value,
|
792 |
shredded_doc_list_items,
|
793 |
-
uploaded_proposal_list, proposal_options, proposal_value
|
794 |
-
{'streaming': False},
|
795 |
-
True
|
796 |
)
|
797 |
|
798 |
if __name__ == '__main__':
|
|
|
8 |
import logging
|
9 |
from docx import Document
|
10 |
import mimetypes
|
11 |
+
from threading import Lock
|
|
|
12 |
import time
|
13 |
|
14 |
import google.generativeai as genai
|
|
|
37 |
generated_response = None
|
38 |
|
39 |
gemini_lock = Lock()
|
|
|
|
|
40 |
|
41 |
def decode_document(decoded_bytes):
|
42 |
try:
|
|
|
86 |
logging.error(f"Exception during file upload to Gemini: {e}")
|
87 |
return None
|
88 |
|
89 |
+
def gemini_generate_content(prompt, file_id=None, chat_input=None):
|
90 |
try:
|
91 |
files = []
|
92 |
if file_id:
|
|
|
108 |
)
|
109 |
)
|
110 |
result = response.text if hasattr(response, "text") else str(response)
|
111 |
+
return result
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
112 |
except Exception as e:
|
113 |
logging.error("Error during Gemini generate_content: %s", e)
|
114 |
+
return f"Error during Gemini completion: {e}"
|
115 |
|
116 |
def save_shredded_as_docx(shredded_text, rfp_filename):
|
117 |
doc = Document()
|
|
|
143 |
memf.seek(0)
|
144 |
return memf.read()
|
145 |
|
146 |
+
def process_document(action, selected_filename=None, chat_input=None, rfp_decoded_bytes=None, selected_generated_filename=None):
|
147 |
+
global shredded_document, generated_response
|
148 |
|
149 |
logging.info(f"Process document called with action: {action}")
|
150 |
|
|
|
174 |
if chat_input:
|
175 |
prompt += f"User additional instructions: {chat_input}\n"
|
176 |
prompt += f"\nFile Name: {selected_filename}\n\n"
|
177 |
+
result = gemini_generate_content(prompt, file_id=doc_fileid, chat_input=chat_input)
|
178 |
+
shredded_document = result
|
179 |
+
if result and not result.startswith("Error"):
|
180 |
+
docx_bytes = save_shredded_as_docx(result, selected_filename)
|
181 |
+
generated_docx_name = f"{os.path.splitext(selected_filename)[0]}_shredded.docx"
|
182 |
+
shredded_documents[generated_docx_name] = docx_bytes
|
183 |
+
if generated_docx_name not in uploaded_documents:
|
184 |
+
uploaded_documents[generated_docx_name] = result
|
185 |
+
return result, None, generated_docx_name, result
|
186 |
+
else:
|
187 |
+
return result, None, None, result
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
188 |
|
189 |
elif action == 'proposal':
|
190 |
if not doc_content:
|
|
|
210 |
if chat_input:
|
211 |
prompt += f"User additional instructions: {chat_input}\n"
|
212 |
prompt += f"\n---\nRFP/SOW/PWS/RFI ({rfp_filename}):\n{doc_content}\n"
|
213 |
+
result = gemini_generate_content(prompt, file_id=rfp_fileid, chat_input=chat_input)
|
214 |
+
generated_response = result
|
215 |
+
if result and not result.startswith("Error"):
|
216 |
+
docx_bytes = save_proposal_as_docx(result, rfp_filename)
|
217 |
+
generated_docx_name = f"{os.path.splitext(rfp_filename)[0]}_proposal.docx"
|
218 |
+
uploaded_proposals[generated_docx_name] = result
|
219 |
+
uploaded_proposals_fileid[generated_docx_name] = None
|
220 |
+
return result, None, generated_docx_name, result
|
221 |
+
else:
|
222 |
+
return result, None, None, result
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
223 |
|
224 |
elif action == 'compliance':
|
225 |
if not selected_generated_filename or selected_generated_filename not in uploaded_proposals:
|
|
|
243 |
"---\nGenerated Proposal Document:\n"
|
244 |
f"{proposal_text}\n"
|
245 |
)
|
246 |
+
result = gemini_generate_content(prompt, file_id=None, chat_input=None)
|
247 |
+
if result and not result.startswith("Error"):
|
248 |
+
docx_bytes = save_compliance_as_docx(result, selected_filename)
|
249 |
+
compliance_docx_name = f"{os.path.splitext(selected_filename)[0]}_compliance_check.docx"
|
250 |
+
uploaded_documents[compliance_docx_name] = result
|
251 |
+
shredded_documents[compliance_docx_name] = docx_bytes
|
252 |
+
return result, None, compliance_docx_name, result
|
253 |
+
else:
|
254 |
+
return result, None, None, result
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
255 |
|
256 |
elif action == 'recover':
|
257 |
return "Recovery not implemented yet.", None, None, None
|
|
|
340 |
return dbc.ListGroup(doc_list, flush=True)
|
341 |
|
342 |
app.layout = dbc.Container([
|
|
|
|
|
|
|
|
|
343 |
dbc.Row([
|
344 |
dbc.Col([
|
345 |
dbc.Card([
|
|
|
440 |
], fluid=True)
|
441 |
|
442 |
@app.callback(
|
|
|
|
|
443 |
Output('output-data-upload', 'children'),
|
444 |
Output('uploaded-doc-list', 'children'),
|
445 |
Output('select-document-dropdown', 'options'),
|
|
|
448 |
Output('uploaded-proposal-list', 'children'),
|
449 |
Output('select-proposal-dropdown', 'options'),
|
450 |
Output('select-proposal-dropdown', 'value'),
|
|
|
|
|
451 |
[
|
452 |
Input('shred-action-btn', 'n_clicks'),
|
453 |
Input('proposal-action-btn', 'n_clicks'),
|
|
|
466 |
State('chat-input', 'value'),
|
467 |
State('select-document-dropdown', 'value'),
|
468 |
State('select-proposal-dropdown', 'value'),
|
469 |
+
Input('cancel-action-btn', 'n_clicks')
|
|
|
|
|
470 |
],
|
471 |
prevent_initial_call=True
|
472 |
)
|
|
|
477 |
shredded_delete_clicks, shredded_doc_children,
|
478 |
select_proposal_dropdown_value,
|
479 |
chat_input, selected_filename, selected_proposal_dropdown, selected_proposal_dropdown_state,
|
480 |
+
cancel_clicks
|
|
|
481 |
):
|
482 |
ctx = callback_context
|
483 |
triggered_id = ctx.triggered[0]['prop_id'].split('.')[0] if ctx.triggered else None
|
|
|
490 |
|
491 |
upload_triggered = False
|
492 |
|
|
|
|
|
|
|
|
|
493 |
rfp_delete_clicks = safe_get_n_clicks(ctx, 5)
|
494 |
proposal_delete_clicks = safe_get_n_clicks(ctx, 9)
|
495 |
shredded_delete_clicks = safe_get_n_clicks(ctx, 11)
|
496 |
|
497 |
uploaded_rfp_decoded_bytes = None
|
498 |
|
499 |
+
global gemini_lock
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
500 |
|
501 |
if triggered_id == 'cancel-action-btn':
|
|
|
|
|
502 |
output_data_upload = html.Div("[Cancelled by user]\n", style={"wordWrap": "break-word"})
|
503 |
doc_options = [{'label': fn, 'value': fn} for fn in uploaded_documents.keys()]
|
504 |
doc_value = selected_doc if selected_doc in uploaded_documents else (next(iter(uploaded_documents), None) if uploaded_documents else None)
|
|
|
508 |
proposal_options = [{'label': fn, 'value': fn} for fn in uploaded_proposals.keys()]
|
509 |
proposal_value = select_proposal_dropdown_value if select_proposal_dropdown_value in uploaded_proposals else (next(iter(uploaded_proposals), None) if uploaded_proposals else None)
|
510 |
return (
|
511 |
+
output_data_upload,
|
512 |
uploaded_doc_list, doc_options, doc_value,
|
513 |
shredded_doc_list_items,
|
514 |
+
uploaded_proposal_list, proposal_options, proposal_value
|
|
|
|
|
515 |
)
|
516 |
|
517 |
if triggered_id == 'upload-document' and rfp_content is not None and rfp_filename:
|
|
|
611 |
if not got_lock:
|
612 |
output_data_upload = html.Div("Another Gemini operation is in progress. Please wait or cancel.", style={"wordWrap": "break-word"})
|
613 |
return (
|
614 |
+
output_data_upload,
|
615 |
uploaded_doc_list, doc_options, doc_value,
|
616 |
shredded_doc_list_items,
|
617 |
+
uploaded_proposal_list, proposal_options, proposal_value
|
|
|
|
|
618 |
)
|
619 |
+
try:
|
620 |
+
action_name = "shred" if triggered_id=="shred-action-btn" else ("proposal" if triggered_id=="proposal-action-btn" else "compliance")
|
621 |
+
result, _, _, _ = process_document(action_name, doc_value, chat_input, uploaded_rfp_decoded_bytes, select_proposal_dropdown_value)
|
622 |
+
output_data_upload = dcc.Markdown(result, style={"whiteSpace": "pre-wrap", "wordWrap": "break-word"})
|
623 |
+
finally:
|
624 |
+
gemini_lock.release()
|
625 |
+
doc_options = [{'label': fn, 'value': fn} for fn in uploaded_documents.keys()]
|
626 |
+
doc_value = doc_value if doc_value in uploaded_documents else (next(iter(uploaded_documents), None) if uploaded_documents else None)
|
627 |
+
proposal_options = [{'label': fn, 'value': fn} for fn in uploaded_proposals.keys()]
|
628 |
+
proposal_value = proposal_value if proposal_value in uploaded_proposals else (next(iter(uploaded_proposals), None) if uploaded_proposals else None)
|
629 |
+
shredded_doc_list_items = get_shredded_doc_list(shredded_documents)
|
630 |
+
uploaded_doc_list = get_uploaded_doc_list(uploaded_documents)
|
631 |
+
uploaded_proposal_list = get_uploaded_proposal_list(uploaded_proposals)
|
632 |
return (
|
633 |
+
output_data_upload,
|
634 |
uploaded_doc_list, doc_options, doc_value,
|
635 |
shredded_doc_list_items,
|
636 |
+
uploaded_proposal_list, proposal_options, proposal_value
|
|
|
|
|
637 |
)
|
638 |
|
639 |
if upload_triggered:
|
|
|
641 |
proposal_value = proposal_value if proposal_value in uploaded_proposals else (next(iter(uploaded_proposals), None) if uploaded_proposals else None)
|
642 |
output_data_upload = html.Div("Upload/Delete completed.", style={"wordWrap": "break-word"})
|
643 |
return (
|
644 |
+
output_data_upload,
|
645 |
uploaded_doc_list, doc_options, doc_value,
|
646 |
shredded_doc_list_items,
|
647 |
+
uploaded_proposal_list, proposal_options, proposal_value
|
|
|
|
|
648 |
)
|
649 |
|
650 |
doc_value = doc_value if doc_value in uploaded_documents else (next(iter(uploaded_documents), None) if uploaded_documents else None)
|
651 |
proposal_value = proposal_value if proposal_value in uploaded_proposals else (next(iter(uploaded_proposals), None) if uploaded_proposals else None)
|
652 |
return (
|
653 |
+
output_data_upload,
|
654 |
uploaded_doc_list, doc_options, doc_value,
|
655 |
shredded_doc_list_items,
|
656 |
+
uploaded_proposal_list, proposal_options, proposal_value
|
|
|
|
|
657 |
)
|
658 |
|
659 |
if __name__ == '__main__':
|