Spaces:
Paused
Paused
Update app.py via AI Editor
Browse files
app.py
CHANGED
@@ -452,92 +452,141 @@ def update_right_col(selected_type, shred_doc, pink_doc, pink_review_doc, red_do
|
|
452 |
@app.callback(
|
453 |
Output('file-list', 'children'),
|
454 |
Output('store-shred', 'data'),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
455 |
Input('upload-document', 'contents'),
|
456 |
State('upload-document', 'filename'),
|
457 |
State('file-list', 'children'),
|
458 |
-
State('store-shred', 'data')
|
459 |
-
)
|
460 |
-
def update_output(list_of_contents, list_of_names, existing_files, current_shred):
|
461 |
-
global uploaded_files
|
462 |
-
if list_of_contents is not None:
|
463 |
-
new_files = []
|
464 |
-
for i, (content, name) in enumerate(zip(list_of_contents, list_of_names)):
|
465 |
-
file_content = process_document(content, name)
|
466 |
-
uploaded_files[name] = file_content
|
467 |
-
new_files.append(
|
468 |
-
dbc.Row([
|
469 |
-
dbc.Col(
|
470 |
-
html.Button('×', id={'type': 'remove-file', 'index': name}, style={'marginRight': '5px', 'fontSize': '10px'}),
|
471 |
-
width=1
|
472 |
-
),
|
473 |
-
dbc.Col(
|
474 |
-
html.Span(name, style={'wordBreak': 'break-all'}),
|
475 |
-
width=11
|
476 |
-
)
|
477 |
-
], id={'type': 'file-row', 'index': name}, align="center", className="mb-1")
|
478 |
-
)
|
479 |
-
if existing_files is None:
|
480 |
-
existing_files = []
|
481 |
-
elif not isinstance(existing_files, list):
|
482 |
-
existing_files = [existing_files]
|
483 |
-
logging.info("Documents uploaded and file list updated.")
|
484 |
-
return existing_files + new_files, current_shred
|
485 |
-
return existing_files, current_shred
|
486 |
-
|
487 |
-
@app.callback(
|
488 |
-
Output('file-list', 'children'),
|
489 |
-
Output('store-shred', 'data'),
|
490 |
Input({'type': 'remove-file', 'index': ALL}, 'n_clicks'),
|
491 |
State('file-list', 'children'),
|
492 |
State('store-shred', 'data'),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
493 |
prevent_initial_call=True
|
494 |
)
|
495 |
-
def
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
518 |
filtered_files.append(file)
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
|
|
|
|
|
|
541 |
|
542 |
def gemini_generate(prompt, max_tokens=4096, temperature=0.25):
|
543 |
result_holder = {}
|
@@ -605,6 +654,8 @@ Now, generate the {document_type}:
|
|
605 |
Output('store-gold-review', 'data'),
|
606 |
Output('store-loe', 'data'),
|
607 |
Output('store-virtual-board', 'data'),
|
|
|
|
|
608 |
Input({'type': 'btn-generate-doc', 'index': ALL}, 'n_clicks'),
|
609 |
State({'type': 'btn-generate-doc', 'index': ALL}, 'id'),
|
610 |
State({'type': 'radio-doc-source-shred', 'index': ALL}, 'value'),
|
@@ -634,9 +685,25 @@ Now, generate the {document_type}:
|
|
634 |
State('store-gold-review', 'data'),
|
635 |
State('store-loe', 'data'),
|
636 |
State('store-virtual-board', 'data'),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
637 |
prevent_initial_call=True
|
638 |
)
|
639 |
-
def
|
640 |
n_clicks_list, btn_ids,
|
641 |
radio_shred, upload_shred_contents, upload_shred_filenames,
|
642 |
radio_pink, upload_pink_contents, upload_pink_filenames,
|
@@ -644,322 +711,258 @@ def generate_any_doc(
|
|
644 |
radio_red, upload_red_contents, upload_red_filenames,
|
645 |
radio_red_review, upload_red_review_contents, upload_red_review_filenames,
|
646 |
radio_gold, upload_gold_contents, upload_gold_filenames,
|
647 |
-
store_shred, store_pink, store_pink_review, store_red, store_red_review, store_gold, store_gold_review, store_loe, store_virtual_board
|
|
|
|
|
648 |
):
|
649 |
ctx = callback_context
|
650 |
-
|
651 |
-
|
652 |
-
|
653 |
-
|
654 |
-
if
|
655 |
-
|
656 |
-
|
657 |
-
|
658 |
-
|
659 |
-
|
660 |
-
|
661 |
-
|
662 |
-
|
663 |
-
|
664 |
-
|
665 |
-
|
666 |
-
|
667 |
-
|
668 |
-
|
669 |
-
|
670 |
-
|
671 |
-
|
672 |
-
|
|
|
|
|
|
|
|
|
|
|
673 |
else:
|
674 |
-
return
|
675 |
-
else:
|
676 |
-
return loaded_var
|
677 |
|
678 |
-
|
679 |
-
|
680 |
-
|
681 |
-
|
682 |
-
|
683 |
-
|
684 |
-
|
685 |
-
|
686 |
-
|
687 |
-
|
688 |
-
|
689 |
-
except Exception as e:
|
690 |
-
logging.error(f"Error generating document: {str(e)}")
|
691 |
-
return html.Div(f"Error generating document: {str(e)}"), "Error", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc
|
692 |
|
693 |
-
|
694 |
-
|
695 |
-
|
696 |
-
|
697 |
-
|
698 |
-
|
699 |
-
|
700 |
-
|
701 |
-
|
702 |
-
|
703 |
-
|
704 |
-
logging.error(f"Error generating Pink: {str(e)}")
|
705 |
-
return html.Div(f"Error generating Pink: {str(e)}"), "Error", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc
|
706 |
-
|
707 |
-
if doc_type == "Pink Review":
|
708 |
-
pink = get_doc_from_radio(radio_pink, upload_pink_contents, upload_pink_filenames, pink_doc)
|
709 |
-
shred = get_doc_from_radio(radio_shred, upload_shred_contents, upload_shred_filenames, shred_doc)
|
710 |
-
if not pink or not shred:
|
711 |
-
return html.Div("Please provide both Pink and Shred documents (either loaded or uploaded) to generate Pink Review."), "", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc
|
712 |
-
try:
|
713 |
-
generated = generate_document(doc_type, [pink, shred])
|
714 |
-
pink_review_doc = generated
|
715 |
-
preview = markdown_table_preview(generated)
|
716 |
-
logging.info("Pink Review document generated.")
|
717 |
-
return preview, "Pink Review generated", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc
|
718 |
-
except Exception as e:
|
719 |
-
logging.error(f"Error generating Pink Review: {str(e)}")
|
720 |
-
return html.Div(f"Error generating Pink Review: {str(e)}"), "Error", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc
|
721 |
|
722 |
-
|
723 |
-
|
724 |
-
|
725 |
-
|
726 |
-
|
727 |
-
|
728 |
-
|
729 |
-
|
730 |
-
|
731 |
-
|
732 |
-
|
733 |
-
|
734 |
-
return html.Div(f"Error generating Red: {str(e)}"), "Error", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc
|
735 |
-
|
736 |
-
if doc_type == "Red Review":
|
737 |
-
red = get_doc_from_radio(radio_red, upload_red_contents, upload_red_filenames, red_doc)
|
738 |
-
shred = get_doc_from_radio(radio_shred, upload_shred_contents, upload_shred_filenames, shred_doc)
|
739 |
-
if not red or not shred:
|
740 |
-
return html.Div("Please provide both Red and Shred documents (either loaded or uploaded) to generate Red Review."), "", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc
|
741 |
-
try:
|
742 |
-
generated = generate_document(doc_type, [red, shred])
|
743 |
-
red_review_doc = generated
|
744 |
-
preview = markdown_table_preview(generated)
|
745 |
-
logging.info("Red Review document generated.")
|
746 |
-
return preview, "Red Review generated", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc
|
747 |
-
except Exception as e:
|
748 |
-
logging.error(f"Error generating Red Review: {str(e)}")
|
749 |
-
return html.Div(f"Error generating Red Review: {str(e)}"), "Error", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc
|
750 |
|
751 |
-
|
752 |
-
|
753 |
-
|
754 |
-
|
755 |
-
|
756 |
-
|
757 |
-
|
758 |
-
|
759 |
-
|
760 |
-
|
761 |
-
|
762 |
-
logging.error(f"Error generating Gold: {str(e)}")
|
763 |
-
return html.Div(f"Error generating Gold: {str(e)}"), "Error", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc
|
764 |
-
|
765 |
-
if doc_type == "Gold Review":
|
766 |
-
gold = get_doc_from_radio(radio_gold, upload_gold_contents, upload_gold_filenames, gold_doc)
|
767 |
-
shred = get_doc_from_radio(radio_shred, upload_shred_contents, upload_shred_filenames, shred_doc)
|
768 |
-
if not gold or not shred:
|
769 |
-
return html.Div("Please provide both Gold and Shred documents (either loaded or uploaded) to generate Gold Review."), "", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc
|
770 |
-
try:
|
771 |
-
generated = generate_document(doc_type, [gold, shred])
|
772 |
-
gold_review_doc = generated
|
773 |
-
preview = markdown_table_preview(generated)
|
774 |
-
logging.info("Gold Review document generated.")
|
775 |
-
return preview, "Gold Review generated", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc
|
776 |
-
except Exception as e:
|
777 |
-
logging.error(f"Error generating Gold Review: {str(e)}")
|
778 |
-
return html.Div(f"Error generating Gold Review: {str(e)}"), "Error", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc
|
779 |
|
780 |
-
|
781 |
-
|
782 |
-
|
783 |
-
|
784 |
-
|
785 |
-
|
786 |
-
|
787 |
-
|
788 |
-
|
789 |
-
|
790 |
-
|
791 |
-
|
792 |
-
return html.Div(f"Error generating LOE: {str(e)}"), "Error", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc
|
793 |
|
794 |
-
|
795 |
-
|
796 |
-
|
797 |
-
|
798 |
-
|
799 |
-
|
800 |
-
|
801 |
-
|
802 |
-
|
803 |
-
|
804 |
-
|
805 |
-
generated = generate_document(doc_type, [lm_text])
|
806 |
-
virtual_board_doc = generated
|
807 |
-
preview = markdown_table_preview(generated)
|
808 |
-
logging.info("Virtual Board document generated.")
|
809 |
-
return preview, "Virtual Board generated", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc
|
810 |
-
except Exception as e:
|
811 |
-
logging.error(f"Error generating Virtual Board: {str(e)}")
|
812 |
-
return html.Div(f"Error generating Virtual Board: {str(e)}"), "Error", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc
|
813 |
|
814 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
815 |
|
816 |
-
|
817 |
-
|
818 |
-
|
819 |
-
|
820 |
-
|
821 |
-
|
822 |
-
|
823 |
-
|
824 |
-
|
825 |
-
|
826 |
-
|
827 |
-
Output('store-virtual-board', 'data'),
|
828 |
-
Input('btn-send-chat', 'n_clicks'),
|
829 |
-
Input('btn-clear-chat', 'n_clicks'),
|
830 |
-
State('chat-input', 'value'),
|
831 |
-
State('selected-doc-type', 'data'),
|
832 |
-
State('document-preview', 'children'),
|
833 |
-
State('store-shred', 'data'),
|
834 |
-
State('store-pink', 'data'),
|
835 |
-
State('store-pink-review', 'data'),
|
836 |
-
State('store-red', 'data'),
|
837 |
-
State('store-red-review', 'data'),
|
838 |
-
State('store-gold', 'data'),
|
839 |
-
State('store-gold-review', 'data'),
|
840 |
-
State('store-loe', 'data'),
|
841 |
-
State('store-virtual-board', 'data'),
|
842 |
-
prevent_initial_call=True
|
843 |
-
)
|
844 |
-
def update_document_via_chat(btn_send, btn_clear, chat_input, selected_doc_type, doc_preview,
|
845 |
-
store_shred, store_pink, store_pink_review, store_red, store_red_review, store_gold, store_gold_review, store_loe, store_virtual_board):
|
846 |
-
ctx = callback_context
|
847 |
-
if not ctx.triggered:
|
848 |
-
raise dash.exceptions.PreventUpdate
|
849 |
-
trigger_id = ctx.triggered[0]['prop_id'].split('.')[0]
|
850 |
-
if trigger_id == 'btn-clear-chat':
|
851 |
-
return "", dash.no_update, store_shred, store_pink, store_pink_review, store_red, store_red_review, store_gold, store_gold_review, store_loe, store_virtual_board
|
852 |
-
|
853 |
-
doc_map = {
|
854 |
-
"Shred": store_shred,
|
855 |
-
"Pink": store_pink,
|
856 |
-
"Pink Review": store_pink_review,
|
857 |
-
"Red": store_red,
|
858 |
-
"Red Review": store_red_review,
|
859 |
-
"Gold": store_gold,
|
860 |
-
"Gold Review": store_gold_review,
|
861 |
-
"LOE": store_loe,
|
862 |
-
"Virtual Board": store_virtual_board
|
863 |
-
}
|
864 |
-
current_document = doc_map.get(selected_doc_type)
|
865 |
-
|
866 |
-
if not chat_input or current_document is None:
|
867 |
-
raise dash.exceptions.PreventUpdate
|
868 |
|
869 |
-
|
870 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
871 |
Current spreadsheet (markdown table format):
|
872 |
{current_document}
|
873 |
Instructions:
|
874 |
1. Provide the updated spreadsheet as a markdown table only.
|
875 |
2. Do not include any narrative, only the markdown table.
|
876 |
-
Now, provide the updated {
|
877 |
"""
|
878 |
-
|
879 |
-
|
880 |
Current document:
|
881 |
{current_document}
|
882 |
Instructions:
|
883 |
1. Provide the updated document content.
|
884 |
2. Maintain proper formatting and structure.
|
885 |
3. Incorporate the requested changes seamlessly.
|
886 |
-
4. If the {
|
887 |
-
Now, provide the updated {
|
888 |
"""
|
889 |
-
|
890 |
-
try:
|
891 |
-
new_document = gemini_generate(prompt, max_tokens=4096, temperature=0.5)
|
892 |
-
if selected_doc_type in spreadsheet_types:
|
893 |
-
preview = markdown_table_preview(new_document)
|
894 |
-
else:
|
895 |
-
preview = markdown_narrative_preview(new_document)
|
896 |
-
# Only update the relevant store
|
897 |
-
stores = [store_shred, store_pink, store_pink_review, store_red, store_red_review, store_gold, store_gold_review, store_loe, store_virtual_board]
|
898 |
-
doc_types = ["Shred", "Pink", "Pink Review", "Red", "Red Review", "Gold", "Gold Review", "LOE", "Virtual Board"]
|
899 |
-
new_stores = []
|
900 |
-
for dt, s in zip(doc_types, stores):
|
901 |
-
if dt == selected_doc_type:
|
902 |
-
new_stores.append(new_document)
|
903 |
-
else:
|
904 |
-
new_stores.append(s)
|
905 |
-
return f"Document updated based on: {chat_input}", preview, *new_stores
|
906 |
-
except Exception as e:
|
907 |
-
logging.error(f"Error updating document via chat: {str(e)}")
|
908 |
-
return f"Error updating document: {str(e)}", html.Div(f"Error updating document: {str(e)}"), store_shred, store_pink, store_pink_review, store_red, store_red_review, store_gold, store_gold_review, store_loe, store_virtual_board
|
909 |
-
|
910 |
-
@app.callback(
|
911 |
-
Output("download-document", "data"),
|
912 |
-
Input("btn-download", "n_clicks"),
|
913 |
-
State('selected-doc-type', 'data'),
|
914 |
-
State('store-shred', 'data'),
|
915 |
-
State('store-pink', 'data'),
|
916 |
-
State('store-pink-review', 'data'),
|
917 |
-
State('store-red', 'data'),
|
918 |
-
State('store-red-review', 'data'),
|
919 |
-
State('store-gold', 'data'),
|
920 |
-
State('store-gold-review', 'data'),
|
921 |
-
State('store-loe', 'data'),
|
922 |
-
State('store-virtual-board', 'data'),
|
923 |
-
prevent_initial_call=True
|
924 |
-
)
|
925 |
-
def download_document(n_clicks, selected_doc_type, store_shred, store_pink, store_pink_review, store_red, store_red_review, store_gold, store_gold_review, store_loe, store_virtual_board):
|
926 |
-
doc_map = {
|
927 |
-
"Shred": store_shred,
|
928 |
-
"Pink": store_pink,
|
929 |
-
"Pink Review": store_pink_review,
|
930 |
-
"Red": store_red,
|
931 |
-
"Red Review": store_red_review,
|
932 |
-
"Gold": store_gold,
|
933 |
-
"Gold Review": store_gold_review,
|
934 |
-
"LOE": store_loe,
|
935 |
-
"Virtual Board": store_virtual_board
|
936 |
-
}
|
937 |
-
current_document = doc_map.get(selected_doc_type)
|
938 |
-
if current_document is None:
|
939 |
-
raise dash.exceptions.PreventUpdate
|
940 |
-
|
941 |
-
if selected_doc_type in spreadsheet_types:
|
942 |
try:
|
943 |
-
|
944 |
-
|
945 |
-
|
946 |
-
|
947 |
-
|
948 |
-
|
949 |
-
|
950 |
-
|
951 |
-
|
952 |
-
|
953 |
-
|
954 |
-
|
955 |
-
|
956 |
-
|
957 |
-
logging.info(f"{selected_doc_type} document downloaded as Word.")
|
958 |
-
output.seek(0)
|
959 |
-
return dcc.send_bytes(output.read(), f"{selected_doc_type}.docx")
|
960 |
except Exception as e:
|
961 |
-
|
962 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
963 |
|
964 |
@app.callback(
|
965 |
Output("chat-input", "rows"),
|
|
|
452 |
@app.callback(
|
453 |
Output('file-list', 'children'),
|
454 |
Output('store-shred', 'data'),
|
455 |
+
Output({'type': f'uploaded-doc-name-shred', 'index': ALL}, 'children'),
|
456 |
+
Output({'type': f'uploaded-doc-name-pink', 'index': ALL}, 'children'),
|
457 |
+
Output({'type': f'uploaded-doc-name-pink_review', 'index': ALL}, 'children'),
|
458 |
+
Output({'type': f'uploaded-doc-name-red', 'index': ALL}, 'children'),
|
459 |
+
Output({'type': f'uploaded-doc-name-red_review', 'index': ALL}, 'children'),
|
460 |
+
Output({'type': f'uploaded-doc-name-gold', 'index': ALL}, 'children'),
|
461 |
+
Output({'type': f'upload-doc-type-shred', 'index': ALL}, 'contents'),
|
462 |
+
Output({'type': f'upload-doc-type-pink', 'index': ALL}, 'contents'),
|
463 |
+
Output({'type': f'upload-doc-type-pink_review', 'index': ALL}, 'contents'),
|
464 |
+
Output({'type': f'upload-doc-type-red', 'index': ALL}, 'contents'),
|
465 |
+
Output({'type': f'upload-doc-type-red_review', 'index': ALL}, 'contents'),
|
466 |
+
Output({'type': f'upload-doc-type-gold', 'index': ALL}, 'contents'),
|
467 |
+
Output({'type': f'radio-doc-source-shred', 'index': ALL}, 'value'),
|
468 |
+
Output({'type': f'radio-doc-source-pink', 'index': ALL}, 'value'),
|
469 |
+
Output({'type': f'radio-doc-source-pink_review', 'index': ALL}, 'value'),
|
470 |
+
Output({'type': f'radio-doc-source-red', 'index': ALL}, 'value'),
|
471 |
+
Output({'type': f'radio-doc-source-red_review', 'index': ALL}, 'value'),
|
472 |
+
Output({'type': f'radio-doc-source-gold', 'index': ALL}, 'value'),
|
473 |
Input('upload-document', 'contents'),
|
474 |
State('upload-document', 'filename'),
|
475 |
State('file-list', 'children'),
|
476 |
+
State('store-shred', 'data'),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
477 |
Input({'type': 'remove-file', 'index': ALL}, 'n_clicks'),
|
478 |
State('file-list', 'children'),
|
479 |
State('store-shred', 'data'),
|
480 |
+
Input({'type': f'upload-doc-type-shred', 'index': ALL}, 'contents'),
|
481 |
+
State({'type': f'upload-doc-type-shred', 'index': ALL}, 'filename'),
|
482 |
+
State({'type': f'upload-doc-type-shred', 'index': ALL}, 'id'),
|
483 |
+
Input({'type': f'upload-doc-type-pink', 'index': ALL}, 'contents'),
|
484 |
+
State({'type': f'upload-doc-type-pink', 'index': ALL}, 'filename'),
|
485 |
+
State({'type': f'upload-doc-type-pink', 'index': ALL}, 'id'),
|
486 |
+
Input({'type': f'upload-doc-type-pink_review', 'index': ALL}, 'contents'),
|
487 |
+
State({'type': f'upload-doc-type-pink_review', 'index': ALL}, 'filename'),
|
488 |
+
State({'type': f'upload-doc-type-pink_review', 'index': ALL}, 'id'),
|
489 |
+
Input({'type': f'upload-doc-type-red', 'index': ALL}, 'contents'),
|
490 |
+
State({'type': f'upload-doc-type-red', 'index': ALL}, 'filename'),
|
491 |
+
State({'type': f'upload-doc-type-red', 'index': ALL}, 'id'),
|
492 |
+
Input({'type': f'upload-doc-type-red_review', 'index': ALL}, 'contents'),
|
493 |
+
State({'type': f'upload-doc-type-red_review', 'index': ALL}, 'filename'),
|
494 |
+
State({'type': f'upload-doc-type-red_review', 'index': ALL}, 'id'),
|
495 |
+
Input({'type': f'upload-doc-type-gold', 'index': ALL}, 'contents'),
|
496 |
+
State({'type': f'upload-doc-type-gold', 'index': ALL}, 'filename'),
|
497 |
+
State({'type': f'upload-doc-type-gold', 'index': ALL}, 'id'),
|
498 |
prevent_initial_call=True
|
499 |
)
|
500 |
+
def combined_upload_remove_update(
|
501 |
+
upload_contents, upload_filenames, existing_files, current_shred,
|
502 |
+
remove_n_clicks, remove_existing_files, remove_current_shred,
|
503 |
+
upload_shred_contents, upload_shred_filenames, upload_shred_ids,
|
504 |
+
upload_pink_contents, upload_pink_filenames, upload_pink_ids,
|
505 |
+
upload_pink_review_contents, upload_pink_review_filenames, upload_pink_review_ids,
|
506 |
+
upload_red_contents, upload_red_filenames, upload_red_ids,
|
507 |
+
upload_red_review_contents, upload_red_review_filenames, upload_red_review_ids,
|
508 |
+
upload_gold_contents, upload_gold_filenames, upload_gold_ids
|
509 |
+
):
|
510 |
+
global uploaded_files, uploaded_doc_contents
|
511 |
+
ctx = callback_context
|
512 |
+
outputs = [dash.no_update]*21
|
513 |
+
|
514 |
+
# Handle Shred upload
|
515 |
+
if ctx.triggered and ctx.triggered[0]['prop_id'].startswith('upload-document'):
|
516 |
+
new_files = []
|
517 |
+
if upload_contents is not None:
|
518 |
+
for i, (content, name) in enumerate(zip(upload_contents, upload_filenames)):
|
519 |
+
file_content = process_document(content, name)
|
520 |
+
uploaded_files[name] = file_content
|
521 |
+
new_files.append(
|
522 |
+
dbc.Row([
|
523 |
+
dbc.Col(
|
524 |
+
html.Button('×', id={'type': 'remove-file', 'index': name}, style={'marginRight': '5px', 'fontSize': '10px'}),
|
525 |
+
width=1
|
526 |
+
),
|
527 |
+
dbc.Col(
|
528 |
+
html.Span(name, style={'wordBreak': 'break-all'}),
|
529 |
+
width=11
|
530 |
+
)
|
531 |
+
], id={'type': 'file-row', 'index': name}, align="center", className="mb-1")
|
532 |
+
)
|
533 |
+
if existing_files is None:
|
534 |
+
existing_files = []
|
535 |
+
elif not isinstance(existing_files, list):
|
536 |
+
existing_files = [existing_files]
|
537 |
+
logging.info("Documents uploaded and file list updated.")
|
538 |
+
outputs[0] = existing_files + new_files
|
539 |
+
outputs[1] = current_shred
|
540 |
+
return outputs
|
541 |
+
|
542 |
+
# Handle file removal
|
543 |
+
if ctx.triggered and ctx.triggered[0]['prop_id'].startswith("{\"type\":\"remove-file\""):
|
544 |
+
try:
|
545 |
+
import json
|
546 |
+
triggered_id = ctx.triggered[0]['prop_id'].split('.')[0]
|
547 |
+
triggered_dict = json.loads(triggered_id)
|
548 |
+
removed_file = triggered_dict['index']
|
549 |
+
except Exception as e:
|
550 |
+
logging.error(f"Could not parse removed file from callback context: {e}")
|
551 |
+
outputs[0] = remove_existing_files
|
552 |
+
outputs[1] = remove_current_shred
|
553 |
+
return outputs
|
554 |
+
uploaded_files.pop(removed_file, None)
|
555 |
+
logging.info(f"Removed file: {removed_file}")
|
556 |
+
filtered_files = []
|
557 |
+
if remove_existing_files:
|
558 |
+
for file in remove_existing_files:
|
559 |
+
try:
|
560 |
+
file_id = file['props']['id']
|
561 |
+
if file_id['index'] != removed_file:
|
562 |
+
filtered_files.append(file)
|
563 |
+
except Exception as e:
|
564 |
filtered_files.append(file)
|
565 |
+
outputs[0] = filtered_files
|
566 |
+
outputs[1] = remove_current_shred
|
567 |
+
return outputs
|
568 |
+
|
569 |
+
# Handle all doc-type uploads
|
570 |
+
doc_upload_types = [
|
571 |
+
("shred", upload_shred_contents, upload_shred_filenames, upload_shred_ids, 2, 8, 14),
|
572 |
+
("pink", upload_pink_contents, upload_pink_filenames, upload_pink_ids, 3, 9, 15),
|
573 |
+
("pink_review", upload_pink_review_contents, upload_pink_review_filenames, upload_pink_review_ids, 4, 10, 16),
|
574 |
+
("red", upload_red_contents, upload_red_filenames, upload_red_ids, 5, 11, 17),
|
575 |
+
("red_review", upload_red_review_contents, upload_red_review_filenames, upload_red_review_ids, 6, 12, 18),
|
576 |
+
("gold", upload_gold_contents, upload_gold_filenames, upload_gold_ids, 7, 13, 19)
|
577 |
+
]
|
578 |
+
for src, contents, filenames, ids, name_idx, content_idx, radio_idx in doc_upload_types:
|
579 |
+
if contents and any(c is not None for c in contents):
|
580 |
+
for i, content in enumerate(contents):
|
581 |
+
if content is not None:
|
582 |
+
uploaded_doc_contents[(src, ids[i]['index'])] = (content, filenames[i])
|
583 |
+
logging.info(f"{ids[i]['index']} {src} file uploaded: {filenames[i]}")
|
584 |
+
outputs[name_idx] = [filenames[i] if j==i else "" for j in range(len(contents))]
|
585 |
+
outputs[content_idx] = [content if j==i else None for j in range(len(contents))]
|
586 |
+
outputs[radio_idx] = ["uploaded" if j==i else "loaded" for j in range(len(contents))]
|
587 |
+
return outputs
|
588 |
+
|
589 |
+
return outputs
|
590 |
|
591 |
def gemini_generate(prompt, max_tokens=4096, temperature=0.25):
|
592 |
result_holder = {}
|
|
|
654 |
Output('store-gold-review', 'data'),
|
655 |
Output('store-loe', 'data'),
|
656 |
Output('store-virtual-board', 'data'),
|
657 |
+
Output('chat-output', 'children'),
|
658 |
+
Output("download-document", "data"),
|
659 |
Input({'type': 'btn-generate-doc', 'index': ALL}, 'n_clicks'),
|
660 |
State({'type': 'btn-generate-doc', 'index': ALL}, 'id'),
|
661 |
State({'type': 'radio-doc-source-shred', 'index': ALL}, 'value'),
|
|
|
685 |
State('store-gold-review', 'data'),
|
686 |
State('store-loe', 'data'),
|
687 |
State('store-virtual-board', 'data'),
|
688 |
+
Input('btn-send-chat', 'n_clicks'),
|
689 |
+
Input('btn-clear-chat', 'n_clicks'),
|
690 |
+
State('chat-input', 'value'),
|
691 |
+
State('selected-doc-type', 'data'),
|
692 |
+
State('document-preview', 'children'),
|
693 |
+
Input("btn-download", "n_clicks"),
|
694 |
+
State('selected-doc-type', 'data'),
|
695 |
+
State('store-shred', 'data'),
|
696 |
+
State('store-pink', 'data'),
|
697 |
+
State('store-pink-review', 'data'),
|
698 |
+
State('store-red', 'data'),
|
699 |
+
State('store-red-review', 'data'),
|
700 |
+
State('store-gold', 'data'),
|
701 |
+
State('store-gold-review', 'data'),
|
702 |
+
State('store-loe', 'data'),
|
703 |
+
State('store-virtual-board', 'data'),
|
704 |
prevent_initial_call=True
|
705 |
)
|
706 |
+
def combined_doc_chat_download(
|
707 |
n_clicks_list, btn_ids,
|
708 |
radio_shred, upload_shred_contents, upload_shred_filenames,
|
709 |
radio_pink, upload_pink_contents, upload_pink_filenames,
|
|
|
711 |
radio_red, upload_red_contents, upload_red_filenames,
|
712 |
radio_red_review, upload_red_review_contents, upload_red_review_filenames,
|
713 |
radio_gold, upload_gold_contents, upload_gold_filenames,
|
714 |
+
store_shred, store_pink, store_pink_review, store_red, store_red_review, store_gold, store_gold_review, store_loe, store_virtual_board,
|
715 |
+
btn_send, btn_clear, chat_input, chat_doc_type, doc_preview,
|
716 |
+
btn_download, dl_doc_type, dl_store_shred, dl_store_pink, dl_store_pink_review, dl_store_red, dl_store_red_review, dl_store_gold, dl_store_gold_review, dl_store_loe, dl_store_virtual_board
|
717 |
):
|
718 |
ctx = callback_context
|
719 |
+
# Default outputs
|
720 |
+
outputs = [dash.no_update]*12 + [None]
|
721 |
+
|
722 |
+
# Document generation triggers
|
723 |
+
if ctx.triggered and ctx.triggered[0]['prop_id'].startswith("{\"type\":\"btn-generate-doc\""):
|
724 |
+
# Use the same logic as before for document generation
|
725 |
+
idx = [i for i, x in enumerate(n_clicks_list) if x]
|
726 |
+
if not idx:
|
727 |
+
return outputs
|
728 |
+
idx = idx[-1]
|
729 |
+
doc_type = btn_ids[idx]['index']
|
730 |
+
|
731 |
+
shred_doc = store_shred
|
732 |
+
pink_doc = store_pink
|
733 |
+
pink_review_doc = store_pink_review
|
734 |
+
red_doc = store_red
|
735 |
+
red_review_doc = store_red_review
|
736 |
+
gold_doc = store_gold
|
737 |
+
gold_review_doc = store_gold_review
|
738 |
+
loe_doc = store_loe
|
739 |
+
virtual_board_doc = store_virtual_board
|
740 |
+
|
741 |
+
def get_doc_from_radio(radio, upload_contents, upload_filenames, loaded_var):
|
742 |
+
if radio and radio[0] == 'uploaded':
|
743 |
+
if upload_contents and upload_contents[0] and upload_filenames and upload_filenames[0]:
|
744 |
+
return process_document(upload_contents[0], upload_filenames[0])
|
745 |
+
else:
|
746 |
+
return None
|
747 |
else:
|
748 |
+
return loaded_var
|
|
|
|
|
749 |
|
750 |
+
if doc_type == "Shred":
|
751 |
+
if not uploaded_files:
|
752 |
+
return [html.Div("Please upload a document before shredding."), "", None, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc, "", None]
|
753 |
+
file_contents = list(uploaded_files.values())
|
754 |
+
try:
|
755 |
+
generated = generate_document(doc_type, file_contents)
|
756 |
+
shred_doc = generated
|
757 |
+
preview = markdown_table_preview(generated)
|
758 |
+
return [preview, "Shred generated", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc, "", None]
|
759 |
+
except Exception as e:
|
760 |
+
return [html.Div(f"Error generating document: {str(e)}"), "Error", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc, "", None]
|
|
|
|
|
|
|
761 |
|
762 |
+
if doc_type == "Pink":
|
763 |
+
shred = get_doc_from_radio(radio_shred, upload_shred_contents, upload_shred_filenames, shred_doc)
|
764 |
+
if not shred:
|
765 |
+
return [html.Div("Please provide a Shred requirements document (either loaded or uploaded) to generate Pink."), "", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc, "", None]
|
766 |
+
try:
|
767 |
+
generated = generate_document(doc_type, [shred])
|
768 |
+
pink_doc = generated
|
769 |
+
preview = markdown_narrative_preview(generated)
|
770 |
+
return [preview, "Pink generated", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc, "", None]
|
771 |
+
except Exception as e:
|
772 |
+
return [html.Div(f"Error generating Pink: {str(e)}"), "Error", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc, "", None]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
773 |
|
774 |
+
if doc_type == "Pink Review":
|
775 |
+
pink = get_doc_from_radio(radio_pink, upload_pink_contents, upload_pink_filenames, pink_doc)
|
776 |
+
shred = get_doc_from_radio(radio_shred, upload_shred_contents, upload_shred_filenames, shred_doc)
|
777 |
+
if not pink or not shred:
|
778 |
+
return [html.Div("Please provide both Pink and Shred documents (either loaded or uploaded) to generate Pink Review."), "", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc, "", None]
|
779 |
+
try:
|
780 |
+
generated = generate_document(doc_type, [pink, shred])
|
781 |
+
pink_review_doc = generated
|
782 |
+
preview = markdown_table_preview(generated)
|
783 |
+
return [preview, "Pink Review generated", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc, "", None]
|
784 |
+
except Exception as e:
|
785 |
+
return [html.Div(f"Error generating Pink Review: {str(e)}"), "Error", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc, "", None]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
786 |
|
787 |
+
if doc_type == "Red":
|
788 |
+
pink_review = get_doc_from_radio(radio_pink_review, upload_pink_review_contents, upload_pink_review_filenames, pink_review_doc)
|
789 |
+
if not pink_review:
|
790 |
+
return [html.Div("Please provide a Pink Review document (either loaded or uploaded) to generate Red."), "", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc, "", None]
|
791 |
+
try:
|
792 |
+
generated = generate_document(doc_type, [pink_review])
|
793 |
+
red_doc = generated
|
794 |
+
preview = markdown_narrative_preview(generated)
|
795 |
+
return [preview, "Red generated", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc, "", None]
|
796 |
+
except Exception as e:
|
797 |
+
return [html.Div(f"Error generating Red: {str(e)}"), "Error", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc, "", None]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
798 |
|
799 |
+
if doc_type == "Red Review":
|
800 |
+
red = get_doc_from_radio(radio_red, upload_red_contents, upload_red_filenames, red_doc)
|
801 |
+
shred = get_doc_from_radio(radio_shred, upload_shred_contents, upload_shred_filenames, shred_doc)
|
802 |
+
if not red or not shred:
|
803 |
+
return [html.Div("Please provide both Red and Shred documents (either loaded or uploaded) to generate Red Review."), "", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc, "", None]
|
804 |
+
try:
|
805 |
+
generated = generate_document(doc_type, [red, shred])
|
806 |
+
red_review_doc = generated
|
807 |
+
preview = markdown_table_preview(generated)
|
808 |
+
return [preview, "Red Review generated", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc, "", None]
|
809 |
+
except Exception as e:
|
810 |
+
return [html.Div(f"Error generating Red Review: {str(e)}"), "Error", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc, "", None]
|
|
|
811 |
|
812 |
+
if doc_type == "Gold":
|
813 |
+
red_review = get_doc_from_radio(radio_red_review, upload_red_review_contents, upload_red_review_filenames, red_review_doc)
|
814 |
+
if not red_review:
|
815 |
+
return [html.Div("Please provide a Red Review document (either loaded or uploaded) to generate Gold."), "", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc, "", None]
|
816 |
+
try:
|
817 |
+
generated = generate_document(doc_type, [red_review])
|
818 |
+
gold_doc = generated
|
819 |
+
preview = markdown_narrative_preview(generated)
|
820 |
+
return [preview, "Gold generated", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc, "", None]
|
821 |
+
except Exception as e:
|
822 |
+
return [html.Div(f"Error generating Gold: {str(e)}"), "Error", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc, "", None]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
823 |
|
824 |
+
if doc_type == "Gold Review":
|
825 |
+
gold = get_doc_from_radio(radio_gold, upload_gold_contents, upload_gold_filenames, gold_doc)
|
826 |
+
shred = get_doc_from_radio(radio_shred, upload_shred_contents, upload_shred_filenames, shred_doc)
|
827 |
+
if not gold or not shred:
|
828 |
+
return [html.Div("Please provide both Gold and Shred documents (either loaded or uploaded) to generate Gold Review."), "", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc, "", None]
|
829 |
+
try:
|
830 |
+
generated = generate_document(doc_type, [gold, shred])
|
831 |
+
gold_review_doc = generated
|
832 |
+
preview = markdown_table_preview(generated)
|
833 |
+
return [preview, "Gold Review generated", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc, "", None]
|
834 |
+
except Exception as e:
|
835 |
+
return [html.Div(f"Error generating Gold Review: {str(e)}"), "Error", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc, "", None]
|
836 |
|
837 |
+
if doc_type == "LOE":
|
838 |
+
gold = get_doc_from_radio(radio_gold, upload_gold_contents, upload_gold_filenames, gold_doc)
|
839 |
+
if not gold:
|
840 |
+
return [html.Div("Please provide a Gold document (either loaded or uploaded) to generate LOE."), "", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc, "", None]
|
841 |
+
try:
|
842 |
+
generated = generate_document(doc_type, [gold])
|
843 |
+
loe_doc = generated
|
844 |
+
preview = markdown_table_preview(generated)
|
845 |
+
return [preview, "LOE generated", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc, "", None]
|
846 |
+
except Exception as e:
|
847 |
+
return [html.Div(f"Error generating LOE: {str(e)}"), "Error", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc, "", None]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
848 |
|
849 |
+
if doc_type == "Virtual Board":
|
850 |
+
shred = get_doc_from_radio(radio_shred, upload_shred_contents, upload_shred_filenames, shred_doc)
|
851 |
+
if not shred:
|
852 |
+
return [html.Div("Please provide a Shred requirements document (either loaded or uploaded) to generate Virtual Board."), "", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc, "", None]
|
853 |
+
try:
|
854 |
+
lm_text = ""
|
855 |
+
lm_match = re.search(r'(Section\s+L[\s\S]+?)(Section\s+M|$)', shred, re.IGNORECASE)
|
856 |
+
if lm_match:
|
857 |
+
lm_text = lm_match.group(1)
|
858 |
+
else:
|
859 |
+
lm_text = shred
|
860 |
+
generated = generate_document(doc_type, [lm_text])
|
861 |
+
virtual_board_doc = generated
|
862 |
+
preview = markdown_table_preview(generated)
|
863 |
+
return [preview, "Virtual Board generated", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc, "", None]
|
864 |
+
except Exception as e:
|
865 |
+
return [html.Div(f"Error generating Virtual Board: {str(e)}"), "Error", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc, "", None]
|
866 |
+
|
867 |
+
return [html.Div("Unsupported document type or missing required sources."), "", shred_doc, pink_doc, pink_review_doc, red_doc, red_review_doc, gold_doc, gold_review_doc, loe_doc, virtual_board_doc, "", None]
|
868 |
+
|
869 |
+
# Chat triggers
|
870 |
+
if ctx.triggered and (ctx.triggered[0]['prop_id'] == 'btn-send-chat.n_clicks' or ctx.triggered[0]['prop_id'] == 'btn-clear-chat.n_clicks'):
|
871 |
+
if ctx.triggered[0]['prop_id'] == 'btn-clear-chat.n_clicks':
|
872 |
+
return [dash.no_update]*11 + ["", None]
|
873 |
+
|
874 |
+
doc_map = {
|
875 |
+
"Shred": store_shred,
|
876 |
+
"Pink": store_pink,
|
877 |
+
"Pink Review": store_pink_review,
|
878 |
+
"Red": store_red,
|
879 |
+
"Red Review": store_red_review,
|
880 |
+
"Gold": store_gold,
|
881 |
+
"Gold Review": store_gold_review,
|
882 |
+
"LOE": store_loe,
|
883 |
+
"Virtual Board": store_virtual_board
|
884 |
+
}
|
885 |
+
current_document = doc_map.get(chat_doc_type)
|
886 |
+
|
887 |
+
if not chat_input or current_document is None:
|
888 |
+
return [dash.no_update]*11 + ["", None]
|
889 |
+
|
890 |
+
if chat_doc_type in spreadsheet_types:
|
891 |
+
prompt = f"""Update the following {chat_doc_type} spreadsheet based on this instruction: {chat_input}
|
892 |
Current spreadsheet (markdown table format):
|
893 |
{current_document}
|
894 |
Instructions:
|
895 |
1. Provide the updated spreadsheet as a markdown table only.
|
896 |
2. Do not include any narrative, only the markdown table.
|
897 |
+
Now, provide the updated {chat_doc_type} spreadsheet:
|
898 |
"""
|
899 |
+
else:
|
900 |
+
prompt = f"""Update the following {chat_doc_type} document based on this instruction: {chat_input}
|
901 |
Current document:
|
902 |
{current_document}
|
903 |
Instructions:
|
904 |
1. Provide the updated document content.
|
905 |
2. Maintain proper formatting and structure.
|
906 |
3. Incorporate the requested changes seamlessly.
|
907 |
+
4. If the {chat_doc_type} is Pink, Red, or Gold then your goal is to write a FULL proposal response, not just a strategy and be compliant and compelling by addressing all the requirements from the document provided. Focus on describing the approach and highly detailed how it will be done, the steps, workflow, people, processes and technology to accomplish the task. Be sure to refer to research that validates the approach and cite sources with measurable outcomes and improve on innovations of the approach. Do not just say things like we will, or MicroHealth will, use active voice and verbs that are definitive in nature, not maybe, could be, should be, can be and things like that. This is a proposal response so logical flow is important so the reader can follow.
|
908 |
+
Now, provide the updated {chat_doc_type}:
|
909 |
"""
|
910 |
+
logging.info(f"Updating document via chat for {chat_doc_type} instruction: {chat_input}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
911 |
try:
|
912 |
+
new_document = gemini_generate(prompt, max_tokens=4096, temperature=0.5)
|
913 |
+
if chat_doc_type in spreadsheet_types:
|
914 |
+
preview = markdown_table_preview(new_document)
|
915 |
+
else:
|
916 |
+
preview = markdown_narrative_preview(new_document)
|
917 |
+
stores = [store_shred, store_pink, store_pink_review, store_red, store_red_review, store_gold, store_gold_review, store_loe, store_virtual_board]
|
918 |
+
doc_types = ["Shred", "Pink", "Pink Review", "Red", "Red Review", "Gold", "Gold Review", "LOE", "Virtual Board"]
|
919 |
+
new_stores = []
|
920 |
+
for dt, s in zip(doc_types, stores):
|
921 |
+
if dt == chat_doc_type:
|
922 |
+
new_stores.append(new_document)
|
923 |
+
else:
|
924 |
+
new_stores.append(s)
|
925 |
+
return [preview, dash.no_update] + new_stores + ["Document updated based on: {}".format(chat_input), None]
|
|
|
|
|
|
|
926 |
except Exception as e:
|
927 |
+
return [html.Div(f"Error updating document: {str(e)}"), dash.no_update, store_shred, store_pink, store_pink_review, store_red, store_red_review, store_gold, store_gold_review, store_loe, store_virtual_board, f"Error updating document: {str(e)}", None]
|
928 |
+
|
929 |
+
# Download trigger
|
930 |
+
if ctx.triggered and ctx.triggered[0]['prop_id'] == "btn-download.n_clicks":
|
931 |
+
doc_map = {
|
932 |
+
"Shred": dl_store_shred,
|
933 |
+
"Pink": dl_store_pink,
|
934 |
+
"Pink Review": dl_store_pink_review,
|
935 |
+
"Red": dl_store_red,
|
936 |
+
"Red Review": dl_store_red_review,
|
937 |
+
"Gold": dl_store_gold,
|
938 |
+
"Gold Review": dl_store_gold_review,
|
939 |
+
"LOE": dl_store_loe,
|
940 |
+
"Virtual Board": dl_store_virtual_board
|
941 |
+
}
|
942 |
+
current_document = doc_map.get(dl_doc_type)
|
943 |
+
if current_document is None:
|
944 |
+
return outputs
|
945 |
+
if dl_doc_type in spreadsheet_types:
|
946 |
+
try:
|
947 |
+
xlsx_bytes = markdown_tables_to_xlsx(current_document)
|
948 |
+
logging.info(f"{dl_doc_type} document downloaded as Excel.")
|
949 |
+
return [dash.no_update]*11 + ["", dcc.send_bytes(xlsx_bytes.read(), f"{dl_doc_type}.xlsx")]
|
950 |
+
except Exception as e:
|
951 |
+
return [dash.no_update]*11 + ["", dcc.send_string(f"Error downloading {dl_doc_type}: {str(e)}", f"{dl_doc_type}_error.txt")]
|
952 |
+
else:
|
953 |
+
try:
|
954 |
+
plain = strip_markdown(current_document)
|
955 |
+
doc = Document()
|
956 |
+
for para in plain.split('\n'):
|
957 |
+
doc.add_paragraph(para)
|
958 |
+
output = BytesIO()
|
959 |
+
doc.save(output)
|
960 |
+
logging.info(f"{dl_doc_type} document downloaded as Word.")
|
961 |
+
output.seek(0)
|
962 |
+
return [dash.no_update]*11 + ["", dcc.send_bytes(output.read(), f"{dl_doc_type}.docx")]
|
963 |
+
except Exception as e:
|
964 |
+
return [dash.no_update]*11 + ["", dcc.send_string(f"Error downloading document: {str(e)}", f"{dl_doc_type}_error.txt")]
|
965 |
+
return outputs
|
966 |
|
967 |
@app.callback(
|
968 |
Output("chat-input", "rows"),
|