usmanyousaf commited on
Commit
4bf10ed
·
verified ·
1 Parent(s): 93b8dc2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +90 -47
app.py CHANGED
@@ -1,3 +1,6 @@
 
 
 
1
  import datetime
2
  import logging
3
  import pathlib
@@ -68,7 +71,7 @@ def _get_icons_list() -> List[str]:
68
  """
69
  Get a list of available icons names without the dir name and file extension.
70
 
71
- :return: A list of the icons.
72
  """
73
 
74
  return ice.get_icons_list()
@@ -99,7 +102,7 @@ def build_ui():
99
  Display the input elements for content generation.
100
  """
101
 
102
- st.title("AI SlideMaker")
103
  st.subheader(APP_TEXT['caption'])
104
  st.markdown(
105
  '![Visitors](https://api.visitorbadge.io/api/visitors?path=https%3A%2F%2Fhuggingface.co%2Fspaces%2Fbarunsaha%2Fslide-deck-ai&countColor=%23263759)' # noqa: E501
@@ -118,11 +121,21 @@ def set_up_chat_ui():
118
 
119
  with st.expander('Usage Instructions'):
120
  st.markdown(GlobalConfig.CHAT_USAGE_INSTRUCTIONS)
 
 
 
 
 
121
 
122
  st.info(
123
- "This is part of an FYP project (module 1)."
 
 
 
124
  )
125
 
 
 
126
  st.chat_message('ai').write(
127
  random.choice(APP_TEXT['ai_greetings'])
128
  )
@@ -136,6 +149,8 @@ def set_up_chat_ui():
136
 
137
  prompt_template = ChatPromptTemplate.from_template(template)
138
 
 
 
139
  for msg in history.messages:
140
  msg_type = msg.type
141
  if msg_type == 'user':
@@ -188,6 +203,7 @@ def set_up_chat_ui():
188
  for chunk in _get_llm().stream(formatted_template):
189
  response += chunk
190
 
 
191
  progress_percentage = min(
192
  len(response) / GlobalConfig.LLM_MODEL_MAX_OUTPUT_LENGTH, 0.95
193
  )
@@ -223,13 +239,18 @@ def set_up_chat_ui():
223
  history.add_user_message(prompt)
224
  history.add_ai_message(response)
225
 
 
 
 
226
  response_cleaned = text_helper.get_clean_json(response)
227
 
228
  logger.info(
229
  'Cleaned JSON response:: original length: %d | cleaned length: %d',
230
  len(response), len(response_cleaned)
231
  )
 
232
 
 
233
  progress_bar.progress(
234
  GlobalConfig.LLM_PROGRESS_MAX,
235
  text='Finding photos online and generating the slide deck...'
@@ -254,7 +275,7 @@ def generate_slide_deck(json_str: str) -> Union[pathlib.Path, None]:
254
  deck, the path may be to an empty file.
255
 
256
  :param json_str: The content in *valid* JSON format.
257
- :return: The path to the .pptx file or None in case of error.
258
  """
259
 
260
  try:
@@ -305,77 +326,99 @@ def generate_slide_deck(json_str: str) -> Union[pathlib.Path, None]:
305
  else:
306
  temp = tempfile.NamedTemporaryFile(delete=False, suffix='.pptx')
307
  path = pathlib.Path(temp.name)
308
- st.session_state[DOWNLOAD_FILE_KEY] = path
 
 
 
309
 
310
- pptx_helper.create_pptx_from_json(parsed_data, pptx_template, path)
 
 
 
 
 
 
 
 
 
311
 
312
  return path
313
 
314
 
315
- def _display_download_button(path: pathlib.Path):
316
  """
317
- Show a download button for the PPTX file.
318
 
319
- :param path: The path to the .pptx file.
320
  """
321
 
322
- file_name = path.name
323
- current_time = datetime.datetime.now()
324
- timestamp = current_time.strftime('%Y-%m-%d')
325
 
326
- with open(path, 'rb') as out_file:
327
- st.download_button(
328
- label='Download Your Slide Deck!',
329
- data=out_file,
330
- file_name=f'{file_name[:-5]}_{timestamp}.pptx',
331
- mime='application/vnd.openxmlformats-officedocument.presentationml.presentation'
332
- )
333
 
 
334
 
335
- def _is_it_refinement() -> bool:
 
336
  """
337
- Whether the slide deck is a refinement of a previous response.
338
 
339
- :return: True if the slide deck is a refinement.
340
  """
341
 
342
- return IS_IT_REFINEMENT in st.session_state and st.session_state[IS_IT_REFINEMENT]
 
 
343
 
344
 
345
- def _get_user_messages() -> List[str]:
346
  """
347
- Return all user messages from the session state.
348
 
349
- :return: A list of user messages.
350
  """
351
 
352
- return [
353
- msg.content for msg in st.session_state[CHAT_MESSAGES]
354
- if msg.type == 'user'
355
- ]
356
 
357
 
358
- def _get_last_response() -> str:
359
  """
360
- Get the last AI message.
361
 
362
- :return: The AI's last message.
363
  """
364
 
365
- return [
366
- msg.content for msg in st.session_state[CHAT_MESSAGES]
367
- if msg.type == 'ai'
368
- ][-1]
369
 
370
- # App entry point
371
- if __name__ == '__main__':
372
- st.set_page_config(
373
- page_title="AI SlideMaker",
374
- layout="centered",
375
- initial_sidebar_state="expanded",
376
- menu_items={
377
- 'About': 'This project is an FYP project (module 1).'
378
- }
379
- )
 
 
 
 
 
 
 
 
 
 
 
380
 
381
  build_ui()
 
 
 
 
 
1
+ """
2
+ Streamlit app containing the UI and the application logic.
3
+ """
4
  import datetime
5
  import logging
6
  import pathlib
 
71
  """
72
  Get a list of available icons names without the dir name and file extension.
73
 
74
+ :return: A llist of the icons.
75
  """
76
 
77
  return ice.get_icons_list()
 
102
  Display the input elements for content generation.
103
  """
104
 
105
+ st.title(APP_TEXT['app_name'])
106
  st.subheader(APP_TEXT['caption'])
107
  st.markdown(
108
  '![Visitors](https://api.visitorbadge.io/api/visitors?path=https%3A%2F%2Fhuggingface.co%2Fspaces%2Fbarunsaha%2Fslide-deck-ai&countColor=%23263759)' # noqa: E501
 
121
 
122
  with st.expander('Usage Instructions'):
123
  st.markdown(GlobalConfig.CHAT_USAGE_INSTRUCTIONS)
124
+ st.markdown(
125
+ '[SlideDeck AI](https://github.com/barun-saha/slide-deck-ai) is an Open-Source project.' # noqa: E501
126
+ ' It is is powered by' # noqa: E501
127
+ ' [Mistral-Nemo-Instruct-2407](https://huggingface.co/mistralai/Mistral-Nemo-Instruct-2407).' # noqa: E501
128
+ )
129
 
130
  st.info(
131
+ 'If you like SlideDeck AI, please consider leaving a heart ❤️ on the'
132
+ ' [Hugging Face Space](https://huggingface.co/spaces/barunsaha/slide-deck-ai/) or'
133
+ ' a star ⭐ on [GitHub](https://github.com/barun-saha/slide-deck-ai).'
134
+ ' Your [feedback](https://forms.gle/JECFBGhjvSj7moBx9) is appreciated.'
135
  )
136
 
137
+ # view_messages = st.expander('View the messages in the session state')
138
+
139
  st.chat_message('ai').write(
140
  random.choice(APP_TEXT['ai_greetings'])
141
  )
 
149
 
150
  prompt_template = ChatPromptTemplate.from_template(template)
151
 
152
+ # Since Streamlit app reloads at every interaction, display the chat history
153
+ # from the save session state
154
  for msg in history.messages:
155
  msg_type = msg.type
156
  if msg_type == 'user':
 
203
  for chunk in _get_llm().stream(formatted_template):
204
  response += chunk
205
 
206
+ # Update the progress bar
207
  progress_percentage = min(
208
  len(response) / GlobalConfig.LLM_MODEL_MAX_OUTPUT_LENGTH, 0.95
209
  )
 
239
  history.add_user_message(prompt)
240
  history.add_ai_message(response)
241
 
242
+ # The content has been generated as JSON
243
+ # There maybe trailing ``` at the end of the response -- remove them
244
+ # To be careful: ``` may be part of the content as well when code is generated
245
  response_cleaned = text_helper.get_clean_json(response)
246
 
247
  logger.info(
248
  'Cleaned JSON response:: original length: %d | cleaned length: %d',
249
  len(response), len(response_cleaned)
250
  )
251
+ # logger.debug('Cleaned JSON: %s', response_cleaned)
252
 
253
+ # Now create the PPT file
254
  progress_bar.progress(
255
  GlobalConfig.LLM_PROGRESS_MAX,
256
  text='Finding photos online and generating the slide deck...'
 
275
  deck, the path may be to an empty file.
276
 
277
  :param json_str: The content in *valid* JSON format.
278
+ :return: The path to the .pptx file or `None` in case of error.
279
  """
280
 
281
  try:
 
326
  else:
327
  temp = tempfile.NamedTemporaryFile(delete=False, suffix='.pptx')
328
  path = pathlib.Path(temp.name)
329
+ st.session_state[DOWNLOAD_FILE_KEY] = str(path)
330
+
331
+ if temp:
332
+ temp.close()
333
 
334
+ try:
335
+ logger.debug('Creating PPTX file: %s...', st.session_state[DOWNLOAD_FILE_KEY])
336
+ pptx_helper.generate_powerpoint_presentation(
337
+ parsed_data,
338
+ slides_template=pptx_template,
339
+ output_file_path=path
340
+ )
341
+ except Exception as ex:
342
+ st.error(APP_TEXT['content_generation_error'])
343
+ logger.error('Caught a generic exception: %s', str(ex))
344
 
345
  return path
346
 
347
 
348
+ def _is_it_refinement() -> bool:
349
  """
350
+ Whether it is the initial prompt or a refinement.
351
 
352
+ :return: True if it is the initial prompt; False otherwise.
353
  """
354
 
355
+ if IS_IT_REFINEMENT in st.session_state:
356
+ return True
 
357
 
358
+ if len(st.session_state[CHAT_MESSAGES]) >= 2:
359
+ # Prepare for the next call
360
+ st.session_state[IS_IT_REFINEMENT] = True
361
+ return True
 
 
 
362
 
363
+ return False
364
 
365
+
366
+ def _get_user_messages() -> List[str]:
367
  """
368
+ Get a list of user messages submitted until now from the session state.
369
 
370
+ :return: The list of user messages.
371
  """
372
 
373
+ return [
374
+ msg.content for msg in st.session_state[CHAT_MESSAGES] if isinstance(msg, HumanMessage)
375
+ ]
376
 
377
 
378
+ def _get_last_response() -> str:
379
  """
380
+ Get the last response generated by AI.
381
 
382
+ :return: The response text.
383
  """
384
 
385
+ return st.session_state[CHAT_MESSAGES][-1].content
 
 
 
386
 
387
 
388
+ def _display_messages_history(view_messages: st.expander):
389
  """
390
+ Display the history of messages.
391
 
392
+ :param view_messages: The list of AI and Human messages.
393
  """
394
 
395
+ with view_messages:
396
+ view_messages.json(st.session_state[CHAT_MESSAGES])
 
 
397
 
398
+
399
+ def _display_download_button(file_path: pathlib.Path):
400
+ """
401
+ Display a download button to download a slide deck.
402
+
403
+ :param file_path: The path of the .pptx file.
404
+ """
405
+
406
+ with open(file_path, 'rb') as download_file:
407
+ st.download_button(
408
+ 'Download PPTX file ⬇️',
409
+ data=download_file,
410
+ file_name='Presentation.pptx',
411
+ key=datetime.datetime.now()
412
+ )
413
+
414
+
415
+ def main():
416
+ """
417
+ Trigger application run.
418
+ """
419
 
420
  build_ui()
421
+
422
+
423
+ if __name__ == '__main__':
424
+ main()