Spaces:
Paused
Paused
Update app.py
Browse files
app.py
CHANGED
@@ -25,6 +25,8 @@ uploaded_files = {}
|
|
25 |
current_document = None
|
26 |
document_type = None
|
27 |
shredded_document = None
|
|
|
|
|
28 |
generated_documents = {}
|
29 |
|
30 |
# Document types and their descriptions
|
@@ -81,7 +83,11 @@ app.layout = dbc.Container([
|
|
81 |
type="dot",
|
82 |
children=[html.Div(id="loading-output")]
|
83 |
),
|
84 |
-
html.Div(id='document-
|
|
|
|
|
|
|
|
|
85 |
dcc.Upload(
|
86 |
id='upload-specific-document',
|
87 |
children=html.Div(['Drag and Drop or ', html.A('Select Document')]),
|
@@ -109,11 +115,7 @@ app.layout = dbc.Container([
|
|
109 |
value='generated'
|
110 |
)
|
111 |
]),
|
112 |
-
dbc.Button("
|
113 |
-
html.Div(id='document-preview', className="border p-3 mb-3"),
|
114 |
-
dbc.Button("Download Document", id="btn-download", color="success", className="mt-3"),
|
115 |
-
dcc.Download(id="download-document"),
|
116 |
-
html.Hr(),
|
117 |
dcc.Loading(
|
118 |
id="chat-loading",
|
119 |
type="dot",
|
@@ -145,40 +147,7 @@ def process_document(contents, filename):
|
|
145 |
return f"Unsupported file format: {filename}. Please upload a PDF or DOCX file."
|
146 |
except Exception as e:
|
147 |
return f"Error processing document: {str(e)}"
|
148 |
-
def generate_document(document_type, file_contents):
|
149 |
-
print(f"Generating document for {document_type}") # Debug print
|
150 |
-
prompt = f"""Generate a {document_type} based on the following project artifacts:
|
151 |
-
{' '.join(file_contents)}
|
152 |
-
Instructions:
|
153 |
-
1. Create the {document_type} as a detailed document.
|
154 |
-
2. Use proper formatting and structure.
|
155 |
-
3. Include all necessary sections and details.
|
156 |
-
4. Start the output immediately with the document content.
|
157 |
-
5. IMPORTANT: If the document type is Pink, Red, Gold and not review type, loe or board
|
158 |
-
then your goal is to be compliant and compelling based on the
|
159 |
-
requirements, write in paragraph in active voice as
|
160 |
-
MicroHealth, limit bullets, answer the
|
161 |
-
requirement with what MicroHealth will do
|
162 |
-
to satisfy the requirement, the technical
|
163 |
-
approach with innovation for efficiency,
|
164 |
-
productivity, quality and measurable
|
165 |
-
outcomes, the industry standard that
|
166 |
-
methodology is based on if applicable,
|
167 |
-
detail the workflow or steps to accomplish
|
168 |
-
the requirement with labor categories that
|
169 |
-
will do those tasks in that workflow,
|
170 |
-
reference reputable research like gartner,
|
171 |
-
forrester, IDC, Deloitte, Accenture etc
|
172 |
-
with measures of success and substantiation
|
173 |
-
of MicroHealth's approach. Never use soft words
|
174 |
-
like maybe, could be, should, possible be definitive in your language and confident.
|
175 |
-
6. you must also take into account section L&M of the document which is the evaluation criteria
|
176 |
-
to be sure we address them.
|
177 |
-
Now, generate the {document_type}:
|
178 |
-
"""
|
179 |
|
180 |
-
response = model.generate_content(prompt)
|
181 |
-
return response.text
|
182 |
@app.callback(
|
183 |
Output('file-list', 'children'),
|
184 |
Output('status-bar', 'children'),
|
@@ -187,7 +156,6 @@ Now, generate the {document_type}:
|
|
187 |
State('file-list', 'children')
|
188 |
)
|
189 |
def update_output(list_of_contents, list_of_names, existing_files):
|
190 |
-
print("update_output callback triggered") # Debug print
|
191 |
global uploaded_files, shredded_document
|
192 |
if list_of_contents is not None:
|
193 |
new_files = []
|
@@ -201,9 +169,8 @@ def update_output(list_of_contents, list_of_names, existing_files):
|
|
201 |
if existing_files is None:
|
202 |
existing_files = []
|
203 |
shredded_document = None # Reset shredded document when new files are uploaded
|
204 |
-
return existing_files + new_files, "Document uploaded. Please
|
205 |
-
return existing_files, "Please upload a document to begin."
|
206 |
-
|
207 |
|
208 |
@app.callback(
|
209 |
Output('file-list', 'children', allow_duplicate=True),
|
@@ -220,92 +187,144 @@ def remove_file(n_clicks, existing_files):
|
|
220 |
removed_file = ctx.triggered[0]['prop_id'].split(',')[0].split(':')[-1].strip('}')
|
221 |
uploaded_files.pop(removed_file, None)
|
222 |
shredded_document = None # Reset shredded document when a file is removed
|
223 |
-
return [file for file in existing_files if file['props']['children'][1]['props']['children'] != removed_file], "Document removed. Please upload a document to begin."
|
224 |
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
243 |
|
244 |
@app.callback(
|
245 |
Output('document-preview', 'children'),
|
246 |
Output('loading-output', 'children'),
|
247 |
Output('status-bar', 'children', allow_duplicate=True),
|
248 |
-
|
|
|
|
|
|
|
|
|
249 |
State('document-source', 'value'),
|
250 |
State('specific-document-name', 'children'),
|
251 |
-
[State(f'btn-{doc_type.lower().replace("_", "-")}', 'n_clicks') for doc_type in document_types.keys()],
|
252 |
prevent_initial_call=True
|
253 |
)
|
254 |
-
def generate_document_preview(
|
255 |
-
print("generate_document_preview callback triggered") # Debug print
|
256 |
global current_document, document_type, shredded_document, generated_documents
|
257 |
ctx = dash.callback_context
|
258 |
if not ctx.triggered:
|
259 |
raise dash.exceptions.PreventUpdate
|
260 |
|
261 |
-
|
262 |
-
for i, arg in enumerate(args):
|
263 |
-
if arg is not None and arg > 0:
|
264 |
-
document_type = list(document_types.keys())[i]
|
265 |
-
break
|
266 |
|
267 |
-
if
|
268 |
-
|
269 |
-
|
270 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
271 |
if document_type == "Shred":
|
|
|
|
|
272 |
file_contents = list(uploaded_files.values())
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
279 |
if document_type == "Pink":
|
280 |
-
|
|
|
|
|
|
|
281 |
elif document_type == "Red":
|
282 |
-
if '
|
283 |
-
return html.Div("Please complete Pink Review first."), "", "Please complete Pink Review first."
|
284 |
-
|
|
|
|
|
|
|
285 |
elif document_type == "Gold":
|
286 |
-
if '
|
287 |
-
return html.Div("Please complete Red Review first."), "", "Please complete Red Review first."
|
288 |
-
|
289 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
290 |
if 'Gold' not in generated_documents:
|
291 |
-
return html.Div("Please complete Gold document first."), "", "Please complete Gold document first."
|
292 |
-
|
|
|
|
|
|
|
293 |
else:
|
294 |
current_document = generate_document(document_type, [shredded_document])
|
295 |
|
296 |
-
|
297 |
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
|
|
|
|
302 |
|
303 |
@app.callback(
|
304 |
Output('specific-document-name', 'children'),
|
305 |
Input('upload-specific-document', 'contents'),
|
306 |
State('upload-specific-document', 'filename')
|
307 |
)
|
308 |
-
def
|
309 |
if contents is not None:
|
310 |
return filename
|
311 |
return ""
|
@@ -347,26 +366,7 @@ def download_document(n_clicks):
|
|
347 |
if current_document is None:
|
348 |
raise dash.exceptions.PreventUpdate
|
349 |
|
350 |
-
if document_type in ["LOE", "
|
351 |
-
# Create a pandas DataFrame for spreadsheet-type documents
|
352 |
-
df = pd.read_csv(StringIO(current_document))
|
353 |
-
|
354 |
-
# Save the DataFrame to an Excel file
|
355 |
-
output = BytesIO()
|
356 |
-
with pd.ExcelWriter(output, engine='xlsxwriter') as writer:
|
357 |
-
df.to_excel
|
358 |
-
|
359 |
-
@app.callback(
|
360 |
-
Output("download-document", "data"),
|
361 |
-
Input("btn-download", "n_clicks"),
|
362 |
-
prevent_initial_call=True
|
363 |
-
)
|
364 |
-
def download_document(n_clicks):
|
365 |
-
global current_document, document_type
|
366 |
-
if current_document is None:
|
367 |
-
raise dash.exceptions.PreventUpdate
|
368 |
-
|
369 |
-
if document_type in ["LOE", "Pink Review", "Red Review", "Gold Review", "Virtual Board", "Shred"]:
|
370 |
# Create a pandas DataFrame for spreadsheet-type documents
|
371 |
df = pd.read_csv(StringIO(current_document))
|
372 |
|
@@ -389,8 +389,5 @@ def download_document(n_clicks):
|
|
389 |
|
390 |
if __name__ == '__main__':
|
391 |
print("Starting the Dash application...")
|
392 |
-
|
393 |
-
app.run(debug=True, host='0.0.0.0', port=7860)
|
394 |
-
except Exception as e:
|
395 |
-
print(f"An error occurred while running the app: {str(e)}")
|
396 |
print("Dash application has finished running.")
|
|
|
25 |
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
|
|
|
83 |
type="dot",
|
84 |
children=[html.Div(id="loading-output")]
|
85 |
),
|
86 |
+
html.Div(id='document-preview', className="border p-3 mb-3"),
|
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='document-upload', style={'display': 'none'}, children=[
|
91 |
dcc.Upload(
|
92 |
id='upload-specific-document',
|
93 |
children=html.Div(['Drag and Drop or ', html.A('Select Document')]),
|
|
|
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",
|
|
|
147 |
return f"Unsupported file format: {filename}. Please upload a PDF or DOCX file."
|
148 |
except Exception as e:
|
149 |
return f"Error processing document: {str(e)}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
150 |
|
|
|
|
|
151 |
@app.callback(
|
152 |
Output('file-list', 'children'),
|
153 |
Output('status-bar', 'children'),
|
|
|
156 |
State('file-list', 'children')
|
157 |
)
|
158 |
def update_output(list_of_contents, list_of_names, existing_files):
|
|
|
159 |
global uploaded_files, shredded_document
|
160 |
if list_of_contents is not None:
|
161 |
new_files = []
|
|
|
169 |
if existing_files is None:
|
170 |
existing_files = []
|
171 |
shredded_document = None # Reset shredded document when new files are uploaded
|
172 |
+
return existing_files + new_files, "Document uploaded. Please click 'Shred' to proceed."
|
173 |
+
return existing_files, "Please upload a document and click 'Shred' to begin."
|
|
|
174 |
|
175 |
@app.callback(
|
176 |
Output('file-list', 'children', allow_duplicate=True),
|
|
|
187 |
removed_file = ctx.triggered[0]['prop_id'].split(',')[0].split(':')[-1].strip('}')
|
188 |
uploaded_files.pop(removed_file, None)
|
189 |
shredded_document = None # Reset shredded document when a file is removed
|
190 |
+
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."
|
191 |
|
192 |
+
def generate_document(document_type, file_contents):
|
193 |
+
prompt = f"""Generate a {document_type} based on the following project artifacts:
|
194 |
+
{' '.join(file_contents)}
|
195 |
+
Instructions:
|
196 |
+
1. Create the {document_type} as a detailed document.
|
197 |
+
2. Use proper formatting and structure.
|
198 |
+
3. Include all necessary sections and details.
|
199 |
+
4. Start the output immediately with the document content.
|
200 |
+
5. IMPORTANT: If the document type is Pink, Red, Gold and not review type, loe or board
|
201 |
+
then your goal is to be compliant and compelling based on the
|
202 |
+
requirements, write in paragraph in active voice as
|
203 |
+
MicroHealth, limit bullets, answer the
|
204 |
+
requirement with what MicroHealth will do
|
205 |
+
to satisfy the requirement, the technical
|
206 |
+
approach with innovation for efficiency,
|
207 |
+
productivity, quality and measurable
|
208 |
+
outcomes, the industry standard that
|
209 |
+
methodology is based on if applicable,
|
210 |
+
detail the workflow or steps to accomplish
|
211 |
+
the requirement with labor categories that
|
212 |
+
will do those tasks in that workflow,
|
213 |
+
reference reputable research like gartner,
|
214 |
+
forrester, IDC, Deloitte, Accenture etc
|
215 |
+
with measures of success and substantiation
|
216 |
+
of MicroHealth's approach. Never use soft words
|
217 |
+
like maybe, could be, should, possible be definitive in your language and confident.
|
218 |
+
6. you must also take into account section L&M of the document which is the evaluation criteria
|
219 |
+
to be sure we address them.
|
220 |
+
Now, generate the {document_type}:
|
221 |
+
"""
|
222 |
+
|
223 |
+
response = model.generate_content(prompt)
|
224 |
+
return response.text
|
225 |
|
226 |
@app.callback(
|
227 |
Output('document-preview', 'children'),
|
228 |
Output('loading-output', 'children'),
|
229 |
Output('status-bar', 'children', allow_duplicate=True),
|
230 |
+
Output('document-upload', 'style'),
|
231 |
+
Output('document-choice', 'style'),
|
232 |
+
Output('btn-generate-document', 'style'),
|
233 |
+
[Input(f'btn-{doc_type.lower().replace("_", "-")}', 'n_clicks') for doc_type in document_types.keys()],
|
234 |
+
Input('btn-generate-document', 'n_clicks'),
|
235 |
State('document-source', 'value'),
|
236 |
State('specific-document-name', 'children'),
|
|
|
237 |
prevent_initial_call=True
|
238 |
)
|
239 |
+
def generate_document_preview(*args):
|
|
|
240 |
global current_document, document_type, shredded_document, generated_documents
|
241 |
ctx = dash.callback_context
|
242 |
if not ctx.triggered:
|
243 |
raise dash.exceptions.PreventUpdate
|
244 |
|
245 |
+
triggered_id = ctx.triggered[0]['prop_id'].split('.')[0]
|
|
|
|
|
|
|
|
|
246 |
|
247 |
+
if triggered_id.startswith('btn-'):
|
248 |
+
document_type = triggered_id.replace('btn-', '').replace('-', '_').title()
|
249 |
+
if document_type == "Shred":
|
250 |
+
return html.Div("Ready to shred. Click 'Generate Document' to proceed."), "", "Ready to shred.", {'display': 'none'}, {'display': 'none'}, {'display': 'block'}
|
251 |
+
elif document_type in ["Pink", "Red", "Gold"]:
|
252 |
+
return html.Div(f"Ready to generate {document_type} document."), "", f"Ready to generate {document_type} document.", {'display': 'block'}, {'display': 'flex'}, {'display': 'block'}
|
253 |
+
elif document_type in ["Pink_Review", "Red_Review", "Gold_Review", "Virtual_Board", "LOE"]:
|
254 |
+
return html.Div(f"Ready to generate {document_type}."), "", f"Ready to generate {document_type}.", {'display': 'block'}, {'display': 'flex'}, {'display': 'block'}
|
255 |
+
|
256 |
+
if triggered_id == 'btn-generate-document':
|
257 |
+
document_source = args[-2]
|
258 |
+
specific_document = args[-1]
|
259 |
+
|
260 |
if document_type == "Shred":
|
261 |
+
if not uploaded_files:
|
262 |
+
return html.Div("Please upload a document before shredding."), "", "Please upload a document before shredding.", {'display': 'none'}, {'display': 'none'}, {'display': 'none'}
|
263 |
file_contents = list(uploaded_files.values())
|
264 |
+
try:
|
265 |
+
shredded_document = generate_document(document_type, file_contents)
|
266 |
+
generated_documents['Shred'] = shredded_document
|
267 |
+
return dcc.Markdown(shredded_document), f"{document_type} generated", "Document shredded successfully.", {'display': 'none'}, {'display': 'none'}, {'display': 'none'}
|
268 |
+
except Exception as e:
|
269 |
+
print(f"Error generating document: {str(e)}")
|
270 |
+
return html.Div(f"Error generating document: {str(e)}"), "Error", "An error occurred while shredding the document.", {'display': 'none'}, {'display': 'none'}, {'display': 'none'}
|
271 |
+
|
272 |
+
if shredded_document is None:
|
273 |
+
return html.Div("Please shred a document first."), "", "Please shred a document first.", {'display': 'none'}, {'display': 'none'}, {'display': 'none'}
|
274 |
+
|
275 |
+
try:
|
276 |
if document_type == "Pink":
|
277 |
+
if document_source == 'uploaded' and specific_document:
|
278 |
+
current_document = generate_document(document_type, [specific_document, shredded_document])
|
279 |
+
else:
|
280 |
+
current_document = generate_document(document_type, [shredded_document])
|
281 |
elif document_type == "Red":
|
282 |
+
if 'Pink_Review' not in generated_documents:
|
283 |
+
return html.Div("Please complete Pink Review first."), "", "Please complete Pink Review first.", {'display': 'none'}, {'display': 'none'}, {'display': 'none'}
|
284 |
+
if document_source == 'uploaded' and specific_document:
|
285 |
+
current_document = generate_document(document_type, [specific_document, generated_documents['Pink_Review'], shredded_document])
|
286 |
+
else:
|
287 |
+
current_document = generate_document(document_type, [generated_documents['Pink_Review'], shredded_document])
|
288 |
elif document_type == "Gold":
|
289 |
+
if 'Red_Review' not in generated_documents:
|
290 |
+
return html.Div("Please complete Red Review first."), "", "Please complete Red Review first.", {'display': 'none'}, {'display': 'none'}, {'display': 'none'}
|
291 |
+
if document_source == 'uploaded' and specific_document:
|
292 |
+
current_document = generate_document(document_type, [specific_document, generated_documents['Red_Review'], shredded_document])
|
293 |
+
else:
|
294 |
+
current_document = generate_document(document_type, [generated_documents['Red_Review'], shredded_document])
|
295 |
+
elif document_type in ["Pink_Review", "Red_Review", "Gold_Review"]:
|
296 |
+
previous_document = generated_documents.get(document_type.split('_')[0], None)
|
297 |
+
if not previous_document:
|
298 |
+
return html.Div(f"Please generate {document_type.split('_')[0]} document first."), "", f"Please generate {document_type.split('_')[0]} document first.", {'display': 'none'}, {'display': 'none'}, {'display': 'none'}
|
299 |
+
if document_source == 'uploaded' and specific_document:
|
300 |
+
current_document = generate_document(document_type, [specific_document, previous_document, shredded_document])
|
301 |
+
else:
|
302 |
+
current_document = generate_document(document_type, [previous_document, shredded_document])
|
303 |
+
elif document_type in ["Virtual_Board", "LOE"]:
|
304 |
if 'Gold' not in generated_documents:
|
305 |
+
return html.Div("Please complete Gold document first."), "", "Please complete Gold document first.", {'display': 'none'}, {'display': 'none'}, {'display': 'none'}
|
306 |
+
if document_source == 'uploaded' and specific_document:
|
307 |
+
current_document = generate_document(document_type, [specific_document, generated_documents['Gold'], shredded_document])
|
308 |
+
else:
|
309 |
+
current_document = generate_document(document_type, [generated_documents['Gold'], shredded_document])
|
310 |
else:
|
311 |
current_document = generate_document(document_type, [shredded_document])
|
312 |
|
313 |
+
generated_documents[document_type] = current_document
|
314 |
|
315 |
+
return dcc.Markdown(current_document), f"{document_type} generated", f"{document_type} document generated successfully.", {'display': 'none'}, {'display': 'none'}, {'display': 'none'}
|
316 |
+
except Exception as e:
|
317 |
+
print(f"Error generating document: {str(e)}")
|
318 |
+
return html.Div(f"Error generating document: {str(e)}"), "Error", "An error occurred while generating the document.", {'display': 'none'}, {'display': 'none'}, {'display': 'none'}
|
319 |
+
|
320 |
+
raise dash.exceptions.PreventUpdate
|
321 |
|
322 |
@app.callback(
|
323 |
Output('specific-document-name', 'children'),
|
324 |
Input('upload-specific-document', 'contents'),
|
325 |
State('upload-specific-document', 'filename')
|
326 |
)
|
327 |
+
def update_specific_document_filename(contents, filename):
|
328 |
if contents is not None:
|
329 |
return filename
|
330 |
return ""
|
|
|
366 |
if current_document is None:
|
367 |
raise dash.exceptions.PreventUpdate
|
368 |
|
369 |
+
if document_type in ["LOE", "Pink_Review", "Red_Review", "Gold_Review", "Virtual_Board"]:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
370 |
# Create a pandas DataFrame for spreadsheet-type documents
|
371 |
df = pd.read_csv(StringIO(current_document))
|
372 |
|
|
|
389 |
|
390 |
if __name__ == '__main__':
|
391 |
print("Starting the Dash application...")
|
392 |
+
app.run(debug=False, host='0.0.0.0', port=7860)
|
|
|
|
|
|
|
393 |
print("Dash application has finished running.")
|