bluenevus commited on
Commit
06b2f8b
·
1 Parent(s): 83fcc35

Update app.py via AI Editor

Browse files
Files changed (1) hide show
  1. app.py +171 -170
app.py CHANGED
@@ -27,6 +27,9 @@ shredded_document = None
27
  pink_review_document = None
28
  uploaded_doc_contents = {}
29
 
 
 
 
30
  document_types = {
31
  "Shred": "Ignore all other instructions and generate only requirements spreadsheet of the Project Work Statement (PWS) identified by action words like shall, will, perform etc. by pws section, requirement. Do not write as if you're responding to the proposal. Its a spreadsheet to distill the requirements, not microhealth's approach",
32
  "Pink": "Create a Pink Team document based on the PWS outline. Your goal is to be compliant and compelling.",
@@ -40,88 +43,60 @@ document_types = {
40
  }
41
 
42
  def get_right_col_content(selected_type):
43
- if selected_type == "Shred":
44
- return dbc.Card(
45
- dbc.CardBody([
46
- html.Div([
47
- html.Div(className="blinking-dot", style={'margin':'0 auto','width':'16px','height':'16px'}),
48
- ], style={'textAlign':'center', 'marginBottom':'10px'}),
49
- dcc.Loading(
50
- id="loading-indicator",
51
- type="dot",
52
- children=[html.Div(id="loading-output")]
53
- ),
54
- html.Div(id='document-preview', className="border p-3 mb-3"),
55
- dbc.Button("Download Document", id="btn-download", color="success", className="mt-3"),
56
- dcc.Download(id="download-document"),
57
- html.Hr(),
58
- dcc.Loading(
59
- id="chat-loading",
60
- type="dot",
61
- children=[
62
- dbc.Input(id="chat-input", type="text", placeholder="Chat with AI to update document...", className="mb-2", style={'whiteSpace':'pre-wrap'}),
63
- dbc.Button("Send", id="btn-send-chat", color="primary", className="mb-3"),
64
- html.Div(id="chat-output")
65
- ]
66
- )
67
- ])
68
- )
69
- else:
70
- return dbc.Card(
71
- dbc.CardBody([
72
- html.Div([
73
- html.Div(className="blinking-dot", style={'margin':'0 auto','width':'16px','height':'16px'}),
74
- ], style={'textAlign':'center', 'marginBottom':'10px'}),
75
- dcc.Loading(
76
- id="loading-indicator",
77
- type="dot",
78
- children=[html.Div(id="loading-output")]
79
- ),
80
- html.Div(id='document-preview', className="border p-3 mb-3"),
81
- dbc.Button("Download Document", id="btn-download", color="success", className="mt-3"),
82
- dcc.Download(id="download-document"),
83
- html.Hr(),
84
- html.Div([
85
- html.Label(f"Upload {selected_type} Document"),
86
- dcc.Upload(
87
- id={'type': 'upload-doc-type', 'index': selected_type},
88
- children=html.Div(['Drag and Drop or ', html.A('Select File')]),
89
- style={
90
- 'width': '100%',
91
- 'height': '60px',
92
- 'lineHeight': '60px',
93
- 'borderWidth': '1px',
94
- 'borderStyle': 'dashed',
95
- 'borderRadius': '5px',
96
- 'textAlign': 'center',
97
- 'margin': '10px 0'
98
- },
99
- multiple=False
100
- ),
101
- html.Div(id={'type': 'uploaded-doc-name', 'index': selected_type}),
102
- dbc.RadioItems(
103
- id={'type': 'radio-doc-source', 'index': selected_type},
104
- options=[
105
- {'label': 'Loaded Document', 'value': 'loaded'},
106
- {'label': 'Uploaded Document', 'value': 'uploaded'}
107
- ],
108
- value='loaded',
109
- inline=True,
110
- className="mb-2"
111
- ),
112
- dbc.Button("Generate Document", id={'type': 'btn-generate-doc', 'index': selected_type}, color="primary", className="mb-3"),
113
- ], id={'type': 'doc-type-controls', 'index': selected_type}),
114
- dcc.Loading(
115
- id="chat-loading",
116
- type="dot",
117
- children=[
118
- dbc.Input(id="chat-input", type="text", placeholder="Chat with AI to update document...", className="mb-2", style={'whiteSpace':'pre-wrap'}),
119
- dbc.Button("Send", id="btn-send-chat", color="primary", className="mb-3"),
120
- html.Div(id="chat-output")
121
- ]
122
- )
123
- ])
124
- )
125
 
126
  app.layout = dbc.Container([
127
  dcc.Store(id='selected-doc-type', data="Shred"),
@@ -279,40 +254,6 @@ def remove_file(n_clicks, existing_files):
279
  @app.callback(
280
  Output('document-preview', 'children'),
281
  Output('loading-output', 'children'),
282
- Input({'type': 'btn-doc-type', 'index': 'Shred'}, 'n_clicks'),
283
- prevent_initial_call=True
284
- )
285
- def generate_shred_doc(n_clicks):
286
- global current_document, document_type, shredded_document
287
- if not uploaded_files:
288
- return html.Div("Please upload a document before shredding."), ""
289
- file_contents = list(uploaded_files.values())
290
- try:
291
- shredded_document = generate_document("Shred", file_contents)
292
- current_document = shredded_document
293
- return dcc.Markdown(shredded_document), "Shred generated"
294
- except Exception as e:
295
- logging.error(f"Error generating document: {str(e)}")
296
- return html.Div(f"Error generating document: {str(e)}"), "Error"
297
-
298
- @app.callback(
299
- Output({'type': 'uploaded-doc-name', 'index': MATCH}, 'children'),
300
- Output({'type': 'upload-doc-type', 'index': MATCH}, 'contents'),
301
- Output({'type': 'radio-doc-source', 'index': MATCH}, 'value'),
302
- Input({'type': 'upload-doc-type', 'index': MATCH}, 'contents'),
303
- State({'type': 'upload-doc-type', 'index': MATCH}, 'filename'),
304
- State({'type': 'upload-doc-type', 'index': MATCH}, 'id')
305
- )
306
- def update_uploaded_doc_name(contents, filename, id_dict):
307
- if contents is not None:
308
- uploaded_doc_contents[id_dict['index']] = (contents, filename)
309
- logging.info(f"{id_dict['index']} file uploaded: {filename}")
310
- return filename, contents, "uploaded"
311
- return "", None, "loaded"
312
-
313
- @app.callback(
314
- Output('document-preview', 'children', allow_duplicate=True),
315
- Output('loading-output', 'children', allow_duplicate=True),
316
  Input({'type': 'btn-generate-doc', 'index': ALL}, 'n_clicks'),
317
  State({'type': 'btn-generate-doc', 'index': ALL}, 'id'),
318
  State({'type': 'radio-doc-source', 'index': ALL}, 'value'),
@@ -320,7 +261,7 @@ def update_uploaded_doc_name(contents, filename, id_dict):
320
  State({'type': 'upload-doc-type', 'index': ALL}, 'filename'),
321
  prevent_initial_call=True
322
  )
323
- def generate_other_doc(n_clicks_list, btn_ids, radio_values, upload_contents, upload_filenames):
324
  global current_document, document_type, shredded_document, pink_review_document
325
  ctx = callback_context
326
  if not ctx.triggered:
@@ -332,15 +273,29 @@ def generate_other_doc(n_clicks_list, btn_ids, radio_values, upload_contents, up
332
  doc_type = btn_ids[idx]['index']
333
  document_type = doc_type
334
 
 
 
 
 
 
 
 
335
  if doc_type == "Shred":
336
- raise dash.exceptions.PreventUpdate
 
 
 
 
 
 
 
 
 
337
 
 
338
  if shredded_document is None:
339
  return html.Div("Please shred a document first."), ""
340
 
341
- source = radio_values[idx] if radio_values and len(radio_values) > idx else 'loaded'
342
- doc_content = None
343
-
344
  if source == 'uploaded':
345
  if upload_contents and len(upload_contents) > idx and upload_contents[idx] and upload_filenames and len(upload_filenames) > idx and upload_filenames[idx]:
346
  doc_content = process_document(upload_contents[idx], upload_filenames[idx])
@@ -368,50 +323,79 @@ def generate_other_doc(n_clicks_list, btn_ids, radio_values, upload_contents, up
368
 
369
  try:
370
  if doc_type == "Pink Review":
371
- current_document = generate_document(doc_type, [doc_content, shredded_document])
372
- pink_review_document = current_document
373
- elif doc_type in ["Red", "Red Review"]:
374
- current_document = generate_document(doc_type, [doc_content, shredded_document])
 
 
 
 
 
 
 
 
 
 
 
375
  else:
376
- current_document = generate_document(doc_type, [doc_content])
377
- logging.info(f"{doc_type} document generated successfully.")
378
- return dcc.Markdown(current_document), f"{doc_type} generated"
 
379
  except Exception as e:
380
  logging.error(f"Error generating document: {str(e)}")
381
  return html.Div(f"Error generating document: {str(e)}"), "Error"
382
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
383
  def generate_document(document_type, file_contents):
384
- prompt = f"""Generate a {document_type} based on the following project artifacts:
 
 
 
 
 
 
 
385
  {' '.join(file_contents)}
386
  Instructions:
387
  1. Create the {document_type} as a detailed document.
388
  2. Use proper formatting and structure.
389
  3. Include all necessary sections and details.
390
  4. Start the output immediately with the document content.
391
- 5. IMPORTANT: If the document type is Pink, Red, Gold and not
392
- Pink Review, Red Review, Gold Review, or spreadsheet, loe or virtual board
393
- then your goal is to be compliant and compelling based on the
394
- requrements, write in paragraph in active voice as
395
- MicroHealth, limit bullets, answer the
396
- requirement with what MicroHealth will do
397
- to satisfy the requirement, the technical
398
- approach with innovation for efficiency,
399
- productivity, quality and measurable
400
- outcomes, the industry standard that
401
- methodology is based on if applicable,
402
- detail the workflow or steps to accomplish
403
- the requirement with labor categories that
404
- will do those tasks in that workflow,
405
- reference reputable research like gartner,
406
- forrester, IDC, Deloitte, Accenture etc
407
- with measures of success and substantiation
408
- of MicroHealth's approach. Never use soft words
409
- like maybe, could be, should, possible be definitive in your language and confident.
410
- 6. you must also take into account section L&M of the document which is the evaluation criteria
411
- to be sure we address them.
412
  Now, generate the {document_type}:
413
  """
414
-
415
  logging.info(f"Generating document for type: {document_type}")
416
  try:
417
  response = openai.ChatCompletion.create(
@@ -435,24 +419,34 @@ Now, generate the {document_type}:
435
  Output('document-preview', 'children', allow_duplicate=True),
436
  Input('btn-send-chat', 'n_clicks'),
437
  State('chat-input', 'value'),
 
438
  prevent_initial_call=True
439
  )
440
- def update_document_via_chat(n_clicks, chat_input):
441
  global current_document, document_type
442
  if not chat_input or current_document is None:
443
  raise dash.exceptions.PreventUpdate
444
-
445
- prompt = f"""Update the following {document_type} based on this instruction: {chat_input}
 
 
 
 
 
 
 
 
 
 
446
  Current document:
447
  {current_document}
448
  Instructions:
449
  1. Provide the updated document content.
450
  2. Maintain proper formatting and structure.
451
  3. Incorporate the requested changes seamlessly.
452
- Now, provide the updated {document_type}:
453
  """
454
-
455
- logging.info(f"Updating document via chat for {document_type} instruction: {chat_input}")
456
  try:
457
  response = openai.ChatCompletion.create(
458
  model="gpt-4-1106-preview",
@@ -465,7 +459,11 @@ Now, provide the updated {document_type}:
465
  )
466
  current_document = response['choices'][0]['message']['content']
467
  logging.info("Document updated via chat successfully.")
468
- return f"Document updated based on: {chat_input}", dcc.Markdown(current_document)
 
 
 
 
469
  except Exception as e:
470
  logging.error(f"Error updating document via chat: {str(e)}")
471
  return f"Error updating document: {str(e)}", html.Div(f"Error updating document: {str(e)}")
@@ -473,35 +471,38 @@ Now, provide the updated {document_type}:
473
  @app.callback(
474
  Output("download-document", "data"),
475
  Input("btn-download", "n_clicks"),
 
476
  prevent_initial_call=True
477
  )
478
- def download_document(n_clicks):
479
- global current_document, document_type
480
  if current_document is None:
481
  raise dash.exceptions.PreventUpdate
482
-
483
- if document_type == "LOE":
484
  try:
485
  df = pd.read_csv(StringIO(current_document))
486
  output = BytesIO()
487
  with pd.ExcelWriter(output, engine='xlsxwriter') as writer:
488
- df.to_excel(writer, sheet_name='LOE', index=False)
489
- logging.info("LOE document downloaded as Excel.")
490
- return dcc.send_bytes(output.getvalue(), f"{document_type}.xlsx")
 
491
  except Exception as e:
492
- logging.error(f"Error downloading LOE document: {str(e)}")
493
- return dcc.send_string(f"Error downloading LOE: {str(e)}", f"{document_type}_error.txt")
494
  else:
495
  try:
496
  doc = Document()
497
  doc.add_paragraph(current_document)
498
  output = BytesIO()
499
  doc.save(output)
500
- logging.info("Document downloaded as Word.")
501
- return dcc.send_bytes(output.getvalue(), f"{document_type}.docx")
 
502
  except Exception as e:
503
  logging.error(f"Error downloading document: {str(e)}")
504
- return dcc.send_string(f"Error downloading document: {str(e)}", f"{document_type}_error.txt")
505
 
506
  if __name__ == '__main__':
507
  print("Starting the Dash application...")
 
27
  pink_review_document = None
28
  uploaded_doc_contents = {}
29
 
30
+ spreadsheet_types = ["Shred", "Pink Review", "Red Review", "Gold Review", "Virtual Board", "LOE"]
31
+ narrative_types = ["Pink", "Red", "Gold"]
32
+
33
  document_types = {
34
  "Shred": "Ignore all other instructions and generate only requirements spreadsheet of the Project Work Statement (PWS) identified by action words like shall, will, perform etc. by pws section, requirement. Do not write as if you're responding to the proposal. Its a spreadsheet to distill the requirements, not microhealth's approach",
35
  "Pink": "Create a Pink Team document based on the PWS outline. Your goal is to be compliant and compelling.",
 
43
  }
44
 
45
  def get_right_col_content(selected_type):
46
+ controls = []
47
+ controls.append(html.Div([
48
+ html.Div(className="blinking-dot", style={'margin':'0 auto','width':'16px','height':'16px'}),
49
+ ], style={'textAlign':'center', 'marginBottom':'10px'}))
50
+ controls.append(dcc.Loading(
51
+ id="loading-indicator",
52
+ type="dot",
53
+ children=[html.Div(id="loading-output")]
54
+ ))
55
+ controls.append(html.Div(id='document-preview', className="border p-3 mb-3"))
56
+ controls.append(dbc.Button("Download Document", id="btn-download", color="success", className="mt-3"))
57
+ controls.append(dcc.Download(id="download-document"))
58
+ controls.append(html.Hr())
59
+ if selected_type != "Shred":
60
+ controls.append(html.Div([
61
+ html.Label(f"Upload {selected_type} Document"),
62
+ dcc.Upload(
63
+ id={'type': 'upload-doc-type', 'index': selected_type},
64
+ children=html.Div(['Drag and Drop or ', html.A('Select File')]),
65
+ style={
66
+ 'width': '100%',
67
+ 'height': '60px',
68
+ 'lineHeight': '60px',
69
+ 'borderWidth': '1px',
70
+ 'borderStyle': 'dashed',
71
+ 'borderRadius': '5px',
72
+ 'textAlign': 'center',
73
+ 'margin': '10px 0'
74
+ },
75
+ multiple=False
76
+ ),
77
+ html.Div(id={'type': 'uploaded-doc-name', 'index': selected_type}),
78
+ dbc.RadioItems(
79
+ id={'type': 'radio-doc-source', 'index': selected_type},
80
+ options=[
81
+ {'label': 'Loaded Document', 'value': 'loaded'},
82
+ {'label': 'Uploaded Document', 'value': 'uploaded'}
83
+ ],
84
+ value='loaded',
85
+ inline=True,
86
+ className="mb-2"
87
+ ),
88
+ dbc.Button("Generate Document", id={'type': 'btn-generate-doc', 'index': selected_type}, color="primary", className="mb-3"),
89
+ ], id={'type': 'doc-type-controls', 'index': selected_type}))
90
+ controls.append(dcc.Loading(
91
+ id="chat-loading",
92
+ type="dot",
93
+ children=[
94
+ dbc.Input(id="chat-input", type="text", placeholder="Chat with AI to update document...", className="mb-2", style={'whiteSpace':'pre-wrap'}),
95
+ dbc.Button("Send", id="btn-send-chat", color="primary", className="mb-3"),
96
+ html.Div(id="chat-output")
97
+ ]
98
+ ))
99
+ return dbc.Card(dbc.CardBody(controls))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
 
101
  app.layout = dbc.Container([
102
  dcc.Store(id='selected-doc-type', data="Shred"),
 
254
  @app.callback(
255
  Output('document-preview', 'children'),
256
  Output('loading-output', 'children'),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
257
  Input({'type': 'btn-generate-doc', 'index': ALL}, 'n_clicks'),
258
  State({'type': 'btn-generate-doc', 'index': ALL}, 'id'),
259
  State({'type': 'radio-doc-source', 'index': ALL}, 'value'),
 
261
  State({'type': 'upload-doc-type', 'index': ALL}, 'filename'),
262
  prevent_initial_call=True
263
  )
264
+ def generate_any_doc(n_clicks_list, btn_ids, radio_values, upload_contents, upload_filenames):
265
  global current_document, document_type, shredded_document, pink_review_document
266
  ctx = callback_context
267
  if not ctx.triggered:
 
273
  doc_type = btn_ids[idx]['index']
274
  document_type = doc_type
275
 
276
+ if not uploaded_files and doc_type == "Shred":
277
+ return html.Div("Please upload a document before shredding."), ""
278
+
279
+ # Source selection
280
+ source = radio_values[idx] if radio_values and len(radio_values) > idx else 'loaded'
281
+ doc_content = None
282
+
283
  if doc_type == "Shred":
284
+ file_contents = list(uploaded_files.values())
285
+ try:
286
+ generated = generate_document(doc_type, file_contents)
287
+ current_document = generated
288
+ shredded_document = generated
289
+ preview = spreadsheet_preview(generated)
290
+ return preview, "Shred generated"
291
+ except Exception as e:
292
+ logging.error(f"Error generating document: {str(e)}")
293
+ return html.Div(f"Error generating document: {str(e)}"), "Error"
294
 
295
+ # For all other types
296
  if shredded_document is None:
297
  return html.Div("Please shred a document first."), ""
298
 
 
 
 
299
  if source == 'uploaded':
300
  if upload_contents and len(upload_contents) > idx and upload_contents[idx] and upload_filenames and len(upload_filenames) > idx and upload_filenames[idx]:
301
  doc_content = process_document(upload_contents[idx], upload_filenames[idx])
 
323
 
324
  try:
325
  if doc_type == "Pink Review":
326
+ generated = generate_document(doc_type, [doc_content, shredded_document])
327
+ pink_review_document = generated
328
+ current_document = generated
329
+ preview = spreadsheet_preview(generated)
330
+ return preview, f"{doc_type} generated"
331
+ elif doc_type in ["Red Review", "Gold Review", "Virtual Board", "LOE"]:
332
+ generated = generate_document(doc_type, [doc_content, shredded_document])
333
+ current_document = generated
334
+ preview = spreadsheet_preview(generated)
335
+ return preview, f"{doc_type} generated"
336
+ elif doc_type in ["Pink", "Red", "Gold"]:
337
+ generated = generate_document(doc_type, [doc_content])
338
+ current_document = generated
339
+ preview = dcc.Markdown(generated)
340
+ return preview, f"{doc_type} generated"
341
  else:
342
+ generated = generate_document(doc_type, [doc_content])
343
+ current_document = generated
344
+ preview = dcc.Markdown(generated)
345
+ return preview, f"{doc_type} generated"
346
  except Exception as e:
347
  logging.error(f"Error generating document: {str(e)}")
348
  return html.Div(f"Error generating document: {str(e)}"), "Error"
349
 
350
+ @app.callback(
351
+ Output({'type': 'uploaded-doc-name', 'index': MATCH}, 'children'),
352
+ Output({'type': 'upload-doc-type', 'index': MATCH}, 'contents'),
353
+ Output({'type': 'radio-doc-source', 'index': MATCH}, 'value'),
354
+ Input({'type': 'upload-doc-type', 'index': MATCH}, 'contents'),
355
+ State({'type': 'upload-doc-type', 'index': MATCH}, 'filename'),
356
+ State({'type': 'upload-doc-type', 'index': MATCH}, 'id')
357
+ )
358
+ def update_uploaded_doc_name(contents, filename, id_dict):
359
+ if contents is not None:
360
+ uploaded_doc_contents[id_dict['index']] = (contents, filename)
361
+ logging.info(f"{id_dict['index']} file uploaded: {filename}")
362
+ return filename, contents, "uploaded"
363
+ return "", None, "loaded"
364
+
365
+ def spreadsheet_preview(text):
366
+ try:
367
+ # Try to parse as CSV, fallback to plain text
368
+ df = pd.read_csv(StringIO(text))
369
+ return dbc.Table.from_dataframe(df, striped=True, bordered=True, hover=True, size="sm")
370
+ except Exception:
371
+ return html.Pre(text, style={'whiteSpace': 'pre-wrap', 'fontFamily': 'monospace'})
372
+
373
  def generate_document(document_type, file_contents):
374
+ if document_type in spreadsheet_types:
375
+ prompt = f"""Ignore all other instructions and output only a spreadsheet for {document_type} as described below. Do not include any narrative, only the spreadsheet in CSV format.
376
+ Instructions: {document_types[document_type]}
377
+ Project Artifacts:
378
+ {' '.join(file_contents)}
379
+ Output only the spreadsheet in CSV format, no narrative or explanation."""
380
+ elif document_type in narrative_types:
381
+ prompt = f"""Generate a {document_type} document based on the following project artifacts:
382
  {' '.join(file_contents)}
383
  Instructions:
384
  1. Create the {document_type} as a detailed document.
385
  2. Use proper formatting and structure.
386
  3. Include all necessary sections and details.
387
  4. Start the output immediately with the document content.
388
+ 5. IMPORTANT: If the document type is Pink, Red, Gold and not Pink Review, Red Review, Gold Review, or spreadsheet, loe or virtual board then your goal is to be compliant and compelling based on the requrements, write in paragraph in active voice as MicroHealth, limit bullets, answer the requirement with what MicroHealth will do to satisfy the requirement, the technical approach with innovation for efficiency, productivity, quality and measurable outcomes, the industry standard that methodology is based on if applicable, detail the workflow or steps to accomplish the requirement with labor categories that will do those tasks in that workflow, reference reputable research like gartner, forrester, IDC, Deloitte, Accenture etc with measures of success and substantiation of MicroHealth's approach. Never use soft words like maybe, could be, should, possible be definitive in your language and confident.
389
+ 6. you must also take into account section L&M of the document which is the evaluation criteria to be sure we address them.
390
+ Now, generate the {document_type}:
391
+ """
392
+ else:
393
+ prompt = f"""Generate a {document_type} based on the following project artifacts:
394
+ {' '.join(file_contents)}
395
+ Instructions:
396
+ {document_types.get(document_type, '')}
 
 
 
 
 
 
 
 
 
 
 
 
397
  Now, generate the {document_type}:
398
  """
 
399
  logging.info(f"Generating document for type: {document_type}")
400
  try:
401
  response = openai.ChatCompletion.create(
 
419
  Output('document-preview', 'children', allow_duplicate=True),
420
  Input('btn-send-chat', 'n_clicks'),
421
  State('chat-input', 'value'),
422
+ State('selected-doc-type', 'data'),
423
  prevent_initial_call=True
424
  )
425
+ def update_document_via_chat(n_clicks, chat_input, selected_doc_type):
426
  global current_document, document_type
427
  if not chat_input or current_document is None:
428
  raise dash.exceptions.PreventUpdate
429
+
430
+ if selected_doc_type in spreadsheet_types:
431
+ prompt = f"""Update the following {selected_doc_type} spreadsheet based on this instruction: {chat_input}
432
+ Current spreadsheet (CSV format):
433
+ {current_document}
434
+ Instructions:
435
+ 1. Provide the updated spreadsheet in CSV format only.
436
+ 2. Do not include any narrative, only the spreadsheet in CSV.
437
+ Now, provide the updated {selected_doc_type} spreadsheet:
438
+ """
439
+ else:
440
+ prompt = f"""Update the following {selected_doc_type} document based on this instruction: {chat_input}
441
  Current document:
442
  {current_document}
443
  Instructions:
444
  1. Provide the updated document content.
445
  2. Maintain proper formatting and structure.
446
  3. Incorporate the requested changes seamlessly.
447
+ Now, provide the updated {selected_doc_type}:
448
  """
449
+ logging.info(f"Updating document via chat for {selected_doc_type} instruction: {chat_input}")
 
450
  try:
451
  response = openai.ChatCompletion.create(
452
  model="gpt-4-1106-preview",
 
459
  )
460
  current_document = response['choices'][0]['message']['content']
461
  logging.info("Document updated via chat successfully.")
462
+ if selected_doc_type in spreadsheet_types:
463
+ preview = spreadsheet_preview(current_document)
464
+ else:
465
+ preview = dcc.Markdown(current_document)
466
+ return f"Document updated based on: {chat_input}", preview
467
  except Exception as e:
468
  logging.error(f"Error updating document via chat: {str(e)}")
469
  return f"Error updating document: {str(e)}", html.Div(f"Error updating document: {str(e)}")
 
471
  @app.callback(
472
  Output("download-document", "data"),
473
  Input("btn-download", "n_clicks"),
474
+ State('selected-doc-type', 'data'),
475
  prevent_initial_call=True
476
  )
477
+ def download_document(n_clicks, selected_doc_type):
478
+ global current_document
479
  if current_document is None:
480
  raise dash.exceptions.PreventUpdate
481
+
482
+ if selected_doc_type in spreadsheet_types:
483
  try:
484
  df = pd.read_csv(StringIO(current_document))
485
  output = BytesIO()
486
  with pd.ExcelWriter(output, engine='xlsxwriter') as writer:
487
+ df.to_excel(writer, sheet_name=selected_doc_type, index=False)
488
+ logging.info(f"{selected_doc_type} document downloaded as Excel.")
489
+ output.seek(0)
490
+ return dcc.send_bytes(output.read(), f"{selected_doc_type}.xlsx")
491
  except Exception as e:
492
+ logging.error(f"Error downloading {selected_doc_type} document: {str(e)}")
493
+ return dcc.send_string(f"Error downloading {selected_doc_type}: {str(e)}", f"{selected_doc_type}_error.txt")
494
  else:
495
  try:
496
  doc = Document()
497
  doc.add_paragraph(current_document)
498
  output = BytesIO()
499
  doc.save(output)
500
+ logging.info(f"{selected_doc_type} document downloaded as Word.")
501
+ output.seek(0)
502
+ return dcc.send_bytes(output.read(), f"{selected_doc_type}.docx")
503
  except Exception as e:
504
  logging.error(f"Error downloading document: {str(e)}")
505
+ return dcc.send_string(f"Error downloading document: {str(e)}", f"{selected_doc_type}_error.txt")
506
 
507
  if __name__ == '__main__':
508
  print("Starting the Dash application...")