Spaces:
Paused
Paused
Update app.py
Browse files
app.py
CHANGED
@@ -26,8 +26,6 @@ current_document = None
|
|
26 |
document_type = None
|
27 |
shredded_document = None
|
28 |
pink_review_document = None
|
29 |
-
red_review_document = None
|
30 |
-
generated_documents = {}
|
31 |
|
32 |
# Document types and their descriptions
|
33 |
document_types = {
|
@@ -36,7 +34,7 @@ document_types = {
|
|
36 |
"Pink Review": "Evaluate compliance of the Pink Team document against the requirements and output a spreadsheet of non compliant findings by pws number, the goal of that pws section, what made it non compliant and your recommendations for recovery",
|
37 |
"Red": "Produce a Red Team document based on the Pink Review by pws sections. Your goal is to be compliant and compelling by recovering all the findings in Pink Review",
|
38 |
"Red Review": "Evaluate compliance of the Red Team document against the requirements and output a spreadsheet of non compliant findings by pws number, the goal of that pws section, what made it non compliant and your recommendations for recovery",
|
39 |
-
"Gold": "Create a
|
40 |
"Gold Review": "Perform a final compliance review against the requirements and output a spreadsheet of non compliant findings by pws number, the goal of that pws section, what made it non compliant and your recommendations for recovery",
|
41 |
"Virtual Board": "Based on the requirements and in particular the evaulation criteria, you will evaluate the proposal as if you were a contracting office and provide section by section evaluation as unsatisfactory, satisfactory, good, very good, excellent and why in a spreadsheet",
|
42 |
"LOE": "Generate a Level of Effort (LOE) breakdown as a spreadsheet"
|
@@ -87,10 +85,10 @@ app.layout = dbc.Container([
|
|
87 |
dbc.Button("Download Document", id="btn-download", color="success", className="mt-3"),
|
88 |
dcc.Download(id="download-document"),
|
89 |
html.Hr(),
|
90 |
-
html.Div(id='
|
91 |
dcc.Upload(
|
92 |
-
id='upload-
|
93 |
-
children=html.Div(['Drag and Drop or ', html.A('Select
|
94 |
style={
|
95 |
'width': '100%',
|
96 |
'height': '60px',
|
@@ -103,19 +101,8 @@ app.layout = dbc.Container([
|
|
103 |
},
|
104 |
multiple=False
|
105 |
),
|
106 |
-
html.Div(id='
|
107 |
]),
|
108 |
-
html.Div(id='document-choice', style={'display': 'none'}, children=[
|
109 |
-
dcc.RadioItems(
|
110 |
-
id='document-source',
|
111 |
-
options=[
|
112 |
-
{'label': 'Use Generated Document', 'value': 'generated'},
|
113 |
-
{'label': 'Use Uploaded Document', 'value': 'uploaded'}
|
114 |
-
],
|
115 |
-
value='generated'
|
116 |
-
)
|
117 |
-
]),
|
118 |
-
dbc.Button("Generate Document", id="btn-generate-document", color="primary", className="mt-3", style={'display': 'none'}),
|
119 |
dcc.Loading(
|
120 |
id="chat-loading",
|
121 |
type="dot",
|
@@ -168,13 +155,10 @@ def update_output(list_of_contents, list_of_names, existing_files):
|
|
168 |
]))
|
169 |
if existing_files is None:
|
170 |
existing_files = []
|
171 |
-
elif not isinstance(existing_files, list):
|
172 |
-
existing_files = [existing_files]
|
173 |
shredded_document = None # Reset shredded document when new files are uploaded
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
@app.callback(
|
179 |
Output('file-list', 'children', allow_duplicate=True),
|
180 |
Output('status-bar', 'children', allow_duplicate=True),
|
@@ -188,11 +172,9 @@ def remove_file(n_clicks, existing_files):
|
|
188 |
if not ctx.triggered:
|
189 |
raise dash.exceptions.PreventUpdate
|
190 |
removed_file = ctx.triggered[0]['prop_id'].split(',')[0].split(':')[-1].strip('}')
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
return [file for file in existing_files if file['props']['children'][1]['props']['children'] != removed_file], f"Document '{removed_file}' removed."
|
195 |
-
return dash.no_update, dash.no_update
|
196 |
|
197 |
def generate_document(document_type, file_contents):
|
198 |
prompt = f"""Generate a {document_type} based on the following project artifacts:
|
@@ -204,7 +186,7 @@ Instructions:
|
|
204 |
4. Start the output immediately with the document content.
|
205 |
5. IMPORTANT: If the document type is Pink, Red, Gold and not review type, loe or board
|
206 |
then your goal is to be compliant and compelling based on the
|
207 |
-
|
208 |
MicroHealth, limit bullets, answer the
|
209 |
requirement with what MicroHealth will do
|
210 |
to satisfy the requirement, the technical
|
@@ -232,126 +214,65 @@ Now, generate the {document_type}:
|
|
232 |
Output('document-preview', 'children'),
|
233 |
Output('loading-output', 'children'),
|
234 |
Output('status-bar', 'children', allow_duplicate=True),
|
235 |
-
Output('
|
236 |
-
|
237 |
-
|
238 |
-
[Input(f'btn-{doc_type.lower().replace(" ", "-")}', 'n_clicks') for doc_type in document_types.keys()],
|
239 |
prevent_initial_call=True
|
240 |
)
|
241 |
-
def
|
242 |
-
global document_type
|
243 |
ctx = dash.callback_context
|
244 |
if not ctx.triggered:
|
245 |
raise dash.exceptions.PreventUpdate
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
return html.Div("Ready to shred. Click 'Generate Document' to proceed."), "", dash.no_update, {'display': 'none'}, {'display': 'none'}, {'display': 'block'}
|
253 |
-
elif document_type in ["Pink", "Red", "Gold"]:
|
254 |
-
return html.Div(f"Ready to generate {document_type} document."), "", dash.no_update, {'display': 'block'}, {'display': 'flex'}, {'display': 'block'}
|
255 |
-
elif document_type in ["Pink Review", "Red Review", "Gold Review", "Virtual Board", "Loe"]:
|
256 |
-
return html.Div(f"Ready to generate {document_type}."), "", dash.no_update, {'display': 'block'}, {'display': 'flex'}, {'display': 'block'}
|
257 |
-
|
258 |
-
return dash.no_update, dash.no_update, dash.no_update, dash.no_update, dash.no_update, dash.no_update
|
259 |
|
260 |
-
@app.callback(
|
261 |
-
Output('document-preview', 'children', allow_duplicate=True),
|
262 |
-
Output('loading-output', 'children', allow_duplicate=True),
|
263 |
-
Output('status-bar', 'children', allow_duplicate=True),
|
264 |
-
Input('btn-generate-document', 'n_clicks'),
|
265 |
-
State('document-source', 'value'),
|
266 |
-
State('specific-document-name', 'children'),
|
267 |
-
prevent_initial_call=True
|
268 |
-
)
|
269 |
-
@app.callback(
|
270 |
-
Output('document-preview', 'children', allow_duplicate=True),
|
271 |
-
Output('loading-output', 'children', allow_duplicate=True),
|
272 |
-
Output('status-bar', 'children', allow_duplicate=True),
|
273 |
-
Input('btn-generate-document', 'n_clicks'),
|
274 |
-
State('document-source', 'value'),
|
275 |
-
State('specific-document-name', 'children'),
|
276 |
-
prevent_initial_call=True
|
277 |
-
)
|
278 |
-
@app.callback(
|
279 |
-
Output('document-preview', 'children', allow_duplicate=True),
|
280 |
-
Output('loading-output', 'children', allow_duplicate=True),
|
281 |
-
Output('status-bar', 'children', allow_duplicate=True),
|
282 |
-
Input('btn-generate-document', 'n_clicks'),
|
283 |
-
State('document-source', 'value'),
|
284 |
-
State('specific-document-name', 'children'),
|
285 |
-
prevent_initial_call=True
|
286 |
-
)
|
287 |
-
def generate_document_preview(n_clicks, document_source, specific_document):
|
288 |
-
global current_document, document_type, shredded_document, generated_documents
|
289 |
-
|
290 |
if document_type == "Shred":
|
291 |
if not uploaded_files:
|
292 |
-
return html.Div("Please upload a document before shredding."), "", "Please upload a document before shredding."
|
293 |
file_contents = list(uploaded_files.values())
|
294 |
try:
|
295 |
shredded_document = generate_document(document_type, file_contents)
|
296 |
-
|
297 |
-
return dcc.Markdown(shredded_document), f"{document_type} generated", "Document shredded successfully."
|
298 |
except Exception as e:
|
299 |
print(f"Error generating document: {str(e)}")
|
300 |
-
return html.Div(f"Error generating document: {str(e)}"), "Error", "An error occurred while shredding the document."
|
301 |
-
|
302 |
if shredded_document is None:
|
303 |
-
return html.Div("Please shred a document first."), "", "Please shred a document first."
|
304 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
305 |
try:
|
306 |
-
if document_type == "Pink":
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
current_document = generate_document(document_type, [shredded_document])
|
311 |
-
elif document_type == "Red":
|
312 |
-
if 'Pink Review' not in generated_documents:
|
313 |
-
return html.Div("Please complete Pink Review first."), "", "Please complete Pink Review first."
|
314 |
-
if document_source == 'uploaded' and specific_document:
|
315 |
-
current_document = generate_document(document_type, [specific_document, generated_documents['Pink Review'], shredded_document])
|
316 |
-
else:
|
317 |
-
current_document = generate_document(document_type, [generated_documents['Pink Review'], shredded_document])
|
318 |
-
elif document_type == "Gold":
|
319 |
-
if 'Red Review' not in generated_documents:
|
320 |
-
return html.Div("Please complete Red Review first."), "", "Please complete Red Review first."
|
321 |
-
if document_source == 'uploaded' and specific_document:
|
322 |
-
current_document = generate_document(document_type, [specific_document, generated_documents['Red Review'], shredded_document])
|
323 |
-
else:
|
324 |
-
current_document = generate_document(document_type, [generated_documents['Red Review'], shredded_document])
|
325 |
-
elif document_type in ["Pink Review", "Red Review", "Gold Review"]:
|
326 |
-
previous_document = generated_documents.get(document_type.split(' ')[0], None)
|
327 |
-
if not previous_document:
|
328 |
-
return html.Div(f"Please generate {document_type.split(' ')[0]} document first."), "", f"Please generate {document_type.split(' ')[0]} document first."
|
329 |
-
if document_source == 'uploaded' and specific_document:
|
330 |
-
current_document = generate_document(document_type, [specific_document, previous_document, shredded_document])
|
331 |
-
else:
|
332 |
-
current_document = generate_document(document_type, [previous_document, shredded_document])
|
333 |
-
elif document_type in ["Virtual Board", "Loe"]:
|
334 |
-
if 'Gold' not in generated_documents:
|
335 |
-
return html.Div("Please complete Gold document first."), "", "Please complete Gold document first."
|
336 |
-
if document_source == 'uploaded' and specific_document:
|
337 |
-
current_document = generate_document(document_type, [specific_document, generated_documents['Gold'], shredded_document])
|
338 |
-
else:
|
339 |
-
current_document = generate_document(document_type, [generated_documents['Gold'], shredded_document])
|
340 |
else:
|
341 |
current_document = generate_document(document_type, [shredded_document])
|
342 |
|
343 |
-
|
344 |
-
|
|
|
|
|
345 |
except Exception as e:
|
346 |
print(f"Error generating document: {str(e)}")
|
347 |
-
return html.Div(f"Error generating document: {str(e)}"), "Error", "An error occurred while generating the document."
|
348 |
|
349 |
@app.callback(
|
350 |
-
Output('
|
351 |
-
Input('upload-
|
352 |
-
State('upload-
|
353 |
)
|
354 |
-
def
|
355 |
if contents is not None:
|
356 |
return filename
|
357 |
return ""
|
@@ -393,14 +314,14 @@ def download_document(n_clicks):
|
|
393 |
if current_document is None:
|
394 |
raise dash.exceptions.PreventUpdate
|
395 |
|
396 |
-
if document_type
|
397 |
-
# Create a pandas DataFrame for
|
398 |
df = pd.read_csv(StringIO(current_document))
|
399 |
|
400 |
# Save the DataFrame to an Excel file
|
401 |
output = BytesIO()
|
402 |
with pd.ExcelWriter(output, engine='xlsxwriter') as writer:
|
403 |
-
df.to_excel(writer, sheet_name=
|
404 |
|
405 |
return dcc.send_bytes(output.getvalue(), f"{document_type}.xlsx")
|
406 |
else:
|
|
|
26 |
document_type = None
|
27 |
shredded_document = None
|
28 |
pink_review_document = None
|
|
|
|
|
29 |
|
30 |
# Document types and their descriptions
|
31 |
document_types = {
|
|
|
34 |
"Pink Review": "Evaluate compliance of the Pink Team document against the requirements and output a spreadsheet of non compliant findings by pws number, the goal of that pws section, what made it non compliant and your recommendations for recovery",
|
35 |
"Red": "Produce a Red Team document based on the Pink Review by pws sections. Your goal is to be compliant and compelling by recovering all the findings in Pink Review",
|
36 |
"Red Review": "Evaluate compliance of the Red Team document against the requirements and output a spreadsheet of non compliant findings by pws number, the goal of that pws section, what made it non compliant and your recommendations for recovery",
|
37 |
+
"Gold": "Create a Pink Team document based on the PWS response by pws sections. Your goal is to be compliant and compelling by recovering all the findings in Red Review",
|
38 |
"Gold Review": "Perform a final compliance review against the requirements and output a spreadsheet of non compliant findings by pws number, the goal of that pws section, what made it non compliant and your recommendations for recovery",
|
39 |
"Virtual Board": "Based on the requirements and in particular the evaulation criteria, you will evaluate the proposal as if you were a contracting office and provide section by section evaluation as unsatisfactory, satisfactory, good, very good, excellent and why in a spreadsheet",
|
40 |
"LOE": "Generate a Level of Effort (LOE) breakdown as a spreadsheet"
|
|
|
85 |
dbc.Button("Download Document", id="btn-download", color="success", className="mt-3"),
|
86 |
dcc.Download(id="download-document"),
|
87 |
html.Hr(),
|
88 |
+
html.Div(id='pink-review-upload', style={'display': 'none'}, children=[
|
89 |
dcc.Upload(
|
90 |
+
id='upload-pink-review',
|
91 |
+
children=html.Div(['Drag and Drop or ', html.A('Select Pink Review File')]),
|
92 |
style={
|
93 |
'width': '100%',
|
94 |
'height': '60px',
|
|
|
101 |
},
|
102 |
multiple=False
|
103 |
),
|
104 |
+
html.Div(id='pink-review-file-name')
|
105 |
]),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
106 |
dcc.Loading(
|
107 |
id="chat-loading",
|
108 |
type="dot",
|
|
|
155 |
]))
|
156 |
if existing_files is None:
|
157 |
existing_files = []
|
|
|
|
|
158 |
shredded_document = None # Reset shredded document when new files are uploaded
|
159 |
+
return existing_files + new_files, "Document uploaded. Please click 'Shred' to proceed."
|
160 |
+
return existing_files, "Please upload a document and click 'Shred' to begin."
|
161 |
+
|
|
|
162 |
@app.callback(
|
163 |
Output('file-list', 'children', allow_duplicate=True),
|
164 |
Output('status-bar', 'children', allow_duplicate=True),
|
|
|
172 |
if not ctx.triggered:
|
173 |
raise dash.exceptions.PreventUpdate
|
174 |
removed_file = ctx.triggered[0]['prop_id'].split(',')[0].split(':')[-1].strip('}')
|
175 |
+
uploaded_files.pop(removed_file, None)
|
176 |
+
shredded_document = None # Reset shredded document when a file is removed
|
177 |
+
return [file for file in existing_files if file['props']['children'][1]['props']['children'] != removed_file], "Document removed. Please upload a document and click 'Shred' to begin."
|
|
|
|
|
178 |
|
179 |
def generate_document(document_type, file_contents):
|
180 |
prompt = f"""Generate a {document_type} based on the following project artifacts:
|
|
|
186 |
4. Start the output immediately with the document content.
|
187 |
5. IMPORTANT: If the document type is Pink, Red, Gold and not review type, loe or board
|
188 |
then your goal is to be compliant and compelling based on the
|
189 |
+
requrements, write in paragraph in active voice as
|
190 |
MicroHealth, limit bullets, answer the
|
191 |
requirement with what MicroHealth will do
|
192 |
to satisfy the requirement, the technical
|
|
|
214 |
Output('document-preview', 'children'),
|
215 |
Output('loading-output', 'children'),
|
216 |
Output('status-bar', 'children', allow_duplicate=True),
|
217 |
+
Output('pink-review-upload', 'style'),
|
218 |
+
[Input(f'btn-{doc_type.lower().replace("_", "-")}', 'n_clicks') for doc_type in document_types.keys()],
|
219 |
+
State('pink-review-file-name', 'children'),
|
|
|
220 |
prevent_initial_call=True
|
221 |
)
|
222 |
+
def generate_document_preview(*args):
|
223 |
+
global current_document, document_type, shredded_document, pink_review_document
|
224 |
ctx = dash.callback_context
|
225 |
if not ctx.triggered:
|
226 |
raise dash.exceptions.PreventUpdate
|
227 |
+
button_id = ctx.triggered[0]['prop_id'].split('.')[0]
|
228 |
+
document_type = button_id.replace('btn-', '').replace('-', '_').title()
|
229 |
+
pink_review_file = args[-1]
|
230 |
+
|
231 |
+
if not uploaded_files and document_type != "Shred":
|
232 |
+
return html.Div("Please upload and shred a document first."), "", "Please upload and shred a document first.", {'display': 'none'}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
233 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
234 |
if document_type == "Shred":
|
235 |
if not uploaded_files:
|
236 |
+
return html.Div("Please upload a document before shredding."), "", "Please upload a document before shredding.", {'display': 'none'}
|
237 |
file_contents = list(uploaded_files.values())
|
238 |
try:
|
239 |
shredded_document = generate_document(document_type, file_contents)
|
240 |
+
return dcc.Markdown(shredded_document), f"{document_type} generated", "Document shredded. You can now proceed with other operations.", {'display': 'none'}
|
|
|
241 |
except Exception as e:
|
242 |
print(f"Error generating document: {str(e)}")
|
243 |
+
return html.Div(f"Error generating document: {str(e)}"), "Error", "An error occurred while shredding the document.", {'display': 'none'}
|
244 |
+
|
245 |
if shredded_document is None:
|
246 |
+
return html.Div("Please shred a document first."), "", "Please shred a document first.", {'display': 'none'}
|
247 |
+
|
248 |
+
if document_type == "Pink Review":
|
249 |
+
return html.Div("Please upload a Pink Team document or use the generated one."), "", "Please upload a Pink Team document or use the generated one.", {'display': 'block'}
|
250 |
+
|
251 |
+
if document_type in ["Red", "Red Review"] and pink_review_document is None:
|
252 |
+
return html.Div("Please complete Pink Review first."), "", "Please complete Pink Review first.", {'display': 'none'}
|
253 |
+
|
254 |
try:
|
255 |
+
if document_type == "Pink Review" and pink_review_file:
|
256 |
+
current_document = generate_document(document_type, [pink_review_file, shredded_document])
|
257 |
+
elif document_type in ["Red", "Red Review"]:
|
258 |
+
current_document = generate_document(document_type, [pink_review_document, shredded_document])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
259 |
else:
|
260 |
current_document = generate_document(document_type, [shredded_document])
|
261 |
|
262 |
+
if document_type == "Pink Review":
|
263 |
+
pink_review_document = current_document
|
264 |
+
|
265 |
+
return dcc.Markdown(current_document), f"{document_type} generated", f"{document_type} document generated successfully.", {'display': 'none'}
|
266 |
except Exception as e:
|
267 |
print(f"Error generating document: {str(e)}")
|
268 |
+
return html.Div(f"Error generating document: {str(e)}"), "Error", "An error occurred while generating the document.", {'display': 'none'}
|
269 |
|
270 |
@app.callback(
|
271 |
+
Output('pink-review-file-name', 'children'),
|
272 |
+
Input('upload-pink-review', 'contents'),
|
273 |
+
State('upload-pink-review', 'filename')
|
274 |
)
|
275 |
+
def update_pink_review_filename(contents, filename):
|
276 |
if contents is not None:
|
277 |
return filename
|
278 |
return ""
|
|
|
314 |
if current_document is None:
|
315 |
raise dash.exceptions.PreventUpdate
|
316 |
|
317 |
+
if document_type == "LOE":
|
318 |
+
# Create a pandas DataFrame for LOE
|
319 |
df = pd.read_csv(StringIO(current_document))
|
320 |
|
321 |
# Save the DataFrame to an Excel file
|
322 |
output = BytesIO()
|
323 |
with pd.ExcelWriter(output, engine='xlsxwriter') as writer:
|
324 |
+
df.to_excel(writer, sheet_name='LOE', index=False)
|
325 |
|
326 |
return dcc.send_bytes(output.getvalue(), f"{document_type}.xlsx")
|
327 |
else:
|