rdz-falcon commited on
Commit
9180644
·
verified ·
1 Parent(s): c128d4b

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +152 -166
src/streamlit_app.py CHANGED
@@ -3,26 +3,21 @@ import numpy as np
3
  import pandas as pd
4
  import streamlit as st
5
 
6
- """
7
- # Welcome to Streamlit!
8
-
9
- Edit `/streamlit_app.py` to customize this app to your heart's desire :heart:.
10
- If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
11
- forums](https://discuss.streamlit.io).
12
 
13
- In the meantime, below is an example of what you can do with just a few lines of code:
14
- """
 
 
15
  import streamlit as st
16
  import pandas as pd
17
  import rag # Import the rag module
18
  import os # Import os for file path handling
19
 
20
- def main():
21
- st.set_page_config(layout="wide", page_title="Communication Board")
22
 
23
- # --- Session State Initialization ---
24
- # Check specifically for 'assistant' to ensure it's initialized
25
- if 'assistant' not in st.session_state:
 
26
  st.session_state.current_page = "main"
27
  st.session_state.show_custom_words = False
28
  st.session_state.custom_words = []
@@ -36,7 +31,7 @@ def main():
36
  st.session_state.text_output = ""
37
 
38
  # --- Theme Colors ---
39
- theme_colors = {
40
  "Default": {
41
  "bg": "#FFFFFF", "text": "#000000",
42
  "pronoun": "#FFFF99", "verb": "#CCFFCC",
@@ -66,40 +61,38 @@ def main():
66
  "misc": "#8B1A1A"
67
  }
68
  }
69
- colors = theme_colors[st.session_state.theme]
70
-
71
- # --- Helper Function to Initialize Assistant (Adapted from previous main.py) ---
72
- @st.cache_resource # Cache the assistant
73
- def initialize_assistant(doc_path):
74
- """Initializes the AACAssistant."""
75
  # Create a dummy document if it doesn't exist for demonstration
76
- if not os.path.exists(doc_path):
77
- st.sidebar.warning(f"Doc '{os.path.basename(doc_path)}' not found. Creating dummy.")
78
- try:
79
- with open(doc_path, "w") as f:
80
- f.write("""
81
- I grew up in Seattle and love the rain.
82
- My favorite hobby is playing chess.
83
- I have a dog named Max.
84
- I studied computer science.
85
- I enjoy sci-fi movies.
86
- """)
87
- except Exception as e:
88
- st.sidebar.error(f"Failed to create dummy doc: {e}")
89
- return None
90
  try:
91
- assistant = rag.AACAssistant(doc_path)
92
- st.sidebar.success("AAC Assistant Initialized.")
93
- return assistant
 
 
 
 
 
94
  except Exception as e:
 
 
 
 
 
 
 
95
  st.sidebar.error(f"Error initializing AAC Assistant: {e}")
96
  st.sidebar.error("Ensure Ollama/LM Studio running.")
97
  return None
98
 
99
- DEFAULT_DOCUMENT_PATH = "aac_user_experiences.txt"
100
-
101
- # --- CSS Styling ---
102
- css = f"""
103
  <style>
104
  .big-font {{
105
  font-size:{st.session_state.text_size}px !important;
@@ -181,29 +174,28 @@ def main():
181
  """
182
 
183
  # --- JS for Button Coloring (no delay, no setTimeout) ---
184
- js = """
185
- <script>
186
- function colorButtons() {
187
- const buttons = document.querySelectorAll('button[id^="key_"]');
188
- buttons.forEach(button => {
189
- const id = button.id;
190
- const parts = id.split('_');
191
- if (parts.length >= 4) {
192
- const category = parts[3];
193
- button.classList.add('btn-' + category);
194
- }
195
- });
196
- }
197
- document.addEventListener('DOMContentLoaded', colorButtons);
198
- new MutationObserver(colorButtons).observe(document.body, { childList: true, subtree: true });
199
- </script>
200
- """
201
-
202
- st.markdown(css, unsafe_allow_html=True)
203
- st.markdown(js, unsafe_allow_html=True)
204
 
205
  # --- Keyboard Layout ---
206
- layout = [
207
  [
208
  {"word": "I", "category": "pronoun"},
209
  {"word": "am", "category": "verb"},
@@ -303,101 +295,98 @@ def main():
303
  ]
304
 
305
  # --- Add Custom Words ---
306
- if st.session_state.custom_words:
307
- custom_row = []
308
- for idx, word_info in enumerate(st.session_state.custom_words):
309
- word = word_info["word"]
310
- category = word_info["category"]
311
- custom_row.append({"word": f"custom_{idx}_{word}", "display": word, "category": category})
312
- if len(custom_row) == 10:
313
- layout.append(custom_row)
314
- custom_row = []
315
- if custom_row:
316
- while len(custom_row) < 10:
317
- custom_row.append({"word": "", "category": "misc"})
318
  layout.append(custom_row)
 
 
 
 
 
319
 
320
  # --- Initialize Assistant ---
321
  # Attempt initialization only once or if it failed previously
322
- if st.session_state.assistant is None: # This check is now safe
323
- st.session_state.assistant = initialize_assistant(DEFAULT_DOCUMENT_PATH)
324
-
325
- # --- Output Box (move to top, before keyboard) ---
326
- st.title("Communication Board")
327
  # Use st.text_area directly for input and display, bound to session state
328
- st.session_state.text_output = st.text_area(
329
  "Compose Message:", value=st.session_state.text_output, height=100, key="main_text_output"
330
  )
331
 
332
  # --- Keyboard Rendering (no delay, instant update) ---
333
- send_action = False # Flag for SEND button
334
- def add_to_output(word):
335
- if word == "SPACE":
 
 
 
 
 
 
 
336
  st.session_state.text_output += " "
337
- elif word in [".", "?", "!", ",", "-"]:
338
- st.session_state.text_output += word
339
- elif word.isdigit() or (len(word) == 1 and word.isalpha()):
340
- st.session_state.text_output += word
341
- else:
342
- if st.session_state.text_output and not st.session_state.text_output.endswith(" "):
343
- st.session_state.text_output += " "
344
- st.session_state.text_output += word
345
 
346
- st.markdown("### Communication Keyboard")
347
- for row_idx, row in enumerate(layout):
348
- cols = st.columns(len(row))
349
- for col_idx, item in enumerate(cols):
350
- word_info = row[col_idx]
351
- if "word" not in word_info or word_info["word"] == "":
352
- continue
353
- word = word_info["word"]
354
- category = word_info["category"]
355
- display = word_info.get("display", word)
356
- key = f"key_{row_idx}_{col_idx}_{category}_{word}"
357
- def make_callback(w=word, d=display):
358
- def cb():
359
- if w.startswith("custom_") or w.startswith("letter_"):
360
- add_to_output(d)
361
- else:
362
- add_to_output(w)
363
- return cb
364
- with cols[col_idx]:
365
- st.button(
366
  display if word != "SPACE" else "␣",
367
  key=key,
368
  on_click=make_callback()
369
  )
370
 
371
  # --- Control Buttons ---
372
- col1, col2, col3, col4 = st.columns(4)
373
- with col1:
374
- if st.button("CLEAR", key="clear_btn", help="Clear all text", use_container_width=True, type="primary"):
375
- st.session_state.text_output = ""
376
- st.rerun() # Rerun to reflect change
377
- with col2:
378
- if st.button("SPEAK", key="speak_btn", help="Speak the current text", use_container_width=True, type="primary"):
379
- if st.session_state.text_output:
380
- st.toast(f"Speaking: {st.session_state.text_output}", icon="🔊")
381
- if st.button("⌫ DEL", key="backspace", help="Delete last character", use_container_width=True):
382
- if st.session_state.text_output:
383
- st.session_state.text_output = st.session_state.text_output[:-1]
384
- with col4:
385
- if st.button("⌫ WORD", key="backspace_word", help="Delete last word", use_container_width=True):
386
- if st.session_state.text_output:
387
- words = st.session_state.text_output.rstrip().split()
 
 
 
388
  if words:
389
- words.pop()
390
- st.session_state.text_output = " ".join(words)
391
- if words:
392
- st.session_state.text_output += " "
393
- with col3: # Use the 3rd column for SEND
394
- if st.button("SEND", key="send_btn", help="Send message to assistant", use_container_width=True, type="primary"):
395
- if st.session_state.text_output:
396
- send_action = True # Set flag to process sending
397
-
398
-
399
- # --- Settings Sidebar ---
400
- with st.sidebar:
401
  # --- Settings Section Commented Out ---
402
  # st.title("Settings")
403
  # st.subheader("Interface")
@@ -448,34 +437,31 @@ def main():
448
  # st.rerun()
449
  # --- End of Settings Section Commented Out ---
450
 
451
- st.divider()
452
- # --- Chat History Display in Sidebar ---
453
- st.subheader("Conversation")
454
- chat_container = st.container(height=400) # Fixed height container
455
- with chat_container:
456
- for message in st.session_state.messages:
457
- with st.chat_message(message["role"]):
458
- st.markdown(message["content"])
459
 
460
- # --- Process SEND Action ---
461
- if send_action and st.session_state.assistant:
462
- user_message = st.session_state.text_output
463
- st.session_state.messages.append({"role": "user", "content": user_message})
464
 
465
  # Process with AACAssistant
466
- try:
467
- # Get the response from the AACAssistant
468
- response = st.session_state.assistant.process_query(user_message)
469
- # Add assistant response to chat history
470
- st.session_state.messages.append({"role": "assistant", "content": response})
471
- except Exception as e:
472
- error_message = f"An error occurred: {e}"
473
- st.error(error_message) # Show error in main area
474
- st.session_state.messages.append({"role": "assistant", "content": f"*Error processing: {error_message}*"})
475
-
476
- # Clear the board's text area after sending
477
- st.session_state.text_output = ""
478
- st.rerun() # Rerun to update chat and clear board
479
 
480
- if __name__ == "__main__":
481
- main()
 
3
  import pandas as pd
4
  import streamlit as st
5
 
 
 
 
 
 
 
6
 
7
+ import streamlit as st
8
+ import pandas as pd
9
+ import rag # Import the rag module
10
+ import os # Import os for file path handling
11
  import streamlit as st
12
  import pandas as pd
13
  import rag # Import the rag module
14
  import os # Import os for file path handling
15
 
 
 
16
 
17
+ st.set_page_config(layout="wide", page_title="Communication Board")
18
+ # --- Session State Initialization ---
19
+ # Check specifically for 'assistant' to ensure it's initialized
20
+ if 'assistant' not in st.session_state:
21
  st.session_state.current_page = "main"
22
  st.session_state.show_custom_words = False
23
  st.session_state.custom_words = []
 
31
  st.session_state.text_output = ""
32
 
33
  # --- Theme Colors ---
34
+ theme_colors = {
35
  "Default": {
36
  "bg": "#FFFFFF", "text": "#000000",
37
  "pronoun": "#FFFF99", "verb": "#CCFFCC",
 
61
  "misc": "#8B1A1A"
62
  }
63
  }
64
+ colors = theme_colors[st.session_state.theme]
65
+ # --- Helper Function to Initialize Assistant (Adapted from previous main.py) ---
66
+ @st.cache_resource # Cache the assistant
67
+ def initialize_assistant(doc_path):
68
+ """Initializes the AACAssistant."""
 
69
  # Create a dummy document if it doesn't exist for demonstration
70
+ if not os.path.exists(doc_path):
71
+ st.sidebar.warning(f"Doc '{os.path.basename(doc_path)}' not found. Creating dummy.")
 
 
 
 
 
 
 
 
 
 
 
 
72
  try:
73
+ with open(doc_path, "w") as f:
74
+ f.write("""
75
+ I grew up in Seattle and love the rain.
76
+ My favorite hobby is playing chess.
77
+ I have a dog named Max.
78
+ I studied computer science.
79
+ I enjoy sci-fi movies.
80
+ """)
81
  except Exception as e:
82
+ st.sidebar.error(f"Failed to create dummy doc: {e}")
83
+ return None
84
+ try:
85
+ assistant = rag.AACAssistant(doc_path)
86
+ st.sidebar.success("AAC Assistant Initialized.")
87
+ return assistant
88
+ except Exception as e:
89
  st.sidebar.error(f"Error initializing AAC Assistant: {e}")
90
  st.sidebar.error("Ensure Ollama/LM Studio running.")
91
  return None
92
 
93
+ DEFAULT_DOCUMENT_PATH = "aac_user_experiences.txt"
94
+ # --- CSS Styling ---
95
+ css = f"""
 
96
  <style>
97
  .big-font {{
98
  font-size:{st.session_state.text_size}px !important;
 
174
  """
175
 
176
  # --- JS for Button Coloring (no delay, no setTimeout) ---
177
+ js = """
178
+ <script>
179
+ function colorButtons() {
180
+ const buttons = document.querySelectorAll('button[id^="key_"]');
181
+ buttons.forEach(button => {
182
+ const id = button.id;
183
+ const parts = id.split('_');
184
+ if (parts.length >= 4) {
185
+ const category = parts[3];
186
+ button.classList.add('btn-' + category);
187
+ }
188
+ });
189
+ }
190
+ document.addEventListener('DOMContentLoaded', colorButtons);
191
+ new MutationObserver(colorButtons).observe(document.body, { childList: true, subtree: true });
192
+ </script>
193
+ """
194
+ st.markdown(css, unsafe_allow_html=True)
195
+ st.markdown(js, unsafe_allow_html=True)
 
196
 
197
  # --- Keyboard Layout ---
198
+ layout = [
199
  [
200
  {"word": "I", "category": "pronoun"},
201
  {"word": "am", "category": "verb"},
 
295
  ]
296
 
297
  # --- Add Custom Words ---
298
+ if st.session_state.custom_words:
299
+ custom_row = []
300
+ for idx, word_info in enumerate(st.session_state.custom_words):
301
+ word = word_info["word"]
302
+ category = word_info["category"]
303
+ custom_row.append({"word": f"custom_{idx}_{word}", "display": word, "category": category})
304
+ if len(custom_row) == 10:
 
 
 
 
 
305
  layout.append(custom_row)
306
+ custom_row = []
307
+ if custom_row:
308
+ while len(custom_row) < 10:
309
+ custom_row.append({"word": "", "category": "misc"})
310
+ layout.append(custom_row)
311
 
312
  # --- Initialize Assistant ---
313
  # Attempt initialization only once or if it failed previously
314
+ if st.session_state.assistant is None: # This check is now safe
315
+ st.session_state.assistant = initialize_assistant(DEFAULT_DOCUMENT_PATH)
316
+ # --- Output Box (move to top, before keyboard) ---
317
+ st.title("Communication Board")
 
318
  # Use st.text_area directly for input and display, bound to session state
319
+ st.session_state.text_output = st.text_area(
320
  "Compose Message:", value=st.session_state.text_output, height=100, key="main_text_output"
321
  )
322
 
323
  # --- Keyboard Rendering (no delay, instant update) ---
324
+ send_action = False # Flag for SEND button
325
+ def add_to_output(word):
326
+ if word == "SPACE":
327
+ st.session_state.text_output += " "
328
+ elif word in [".", "?", "!", ",", "-"]:
329
+ st.session_state.text_output += word
330
+ elif word.isdigit() or (len(word) == 1 and word.isalpha()):
331
+ st.session_state.text_output += word
332
+ else:
333
+ if st.session_state.text_output and not st.session_state.text_output.endswith(" "):
334
  st.session_state.text_output += " "
335
+ st.session_state.text_output += word
 
 
 
 
 
 
 
336
 
337
+ st.markdown("### Communication Keyboard")
338
+ for row_idx, row in enumerate(layout):
339
+ cols = st.columns(len(row))
340
+ for col_idx, item in enumerate(cols):
341
+ word_info = row[col_idx]
342
+ if "word" not in word_info or word_info["word"] == "":
343
+ continue
344
+ word = word_info["word"]
345
+ category = word_info["category"]
346
+ display = word_info.get("display", word)
347
+ key = f"key_{row_idx}_{col_idx}_{category}_{word}"
348
+ def make_callback(w=word, d=display):
349
+ def cb():
350
+ if w.startswith("custom_") or w.startswith("letter_"):
351
+ add_to_output(d)
352
+ else:
353
+ add_to_output(w)
354
+ return cb
355
+ with cols[col_idx]:
356
+ st.button(
357
  display if word != "SPACE" else "␣",
358
  key=key,
359
  on_click=make_callback()
360
  )
361
 
362
  # --- Control Buttons ---
363
+ col1, col2, col3, col4 = st.columns(4)
364
+ with col1:
365
+ if st.button("CLEAR", key="clear_btn", help="Clear all text", use_container_width=True, type="primary"):
366
+ st.session_state.text_output = ""
367
+ st.rerun() # Rerun to reflect change
368
+ with col2:
369
+ if st.button("SPEAK", key="speak_btn", help="Speak the current text", use_container_width=True, type="primary"):
370
+ if st.session_state.text_output:
371
+ st.toast(f"Speaking: {st.session_state.text_output}", icon="🔊")
372
+ if st.button("⌫ DEL", key="backspace", help="Delete last character", use_container_width=True):
373
+ if st.session_state.text_output:
374
+ st.session_state.text_output = st.session_state.text_output[:-1]
375
+ with col4:
376
+ if st.button("⌫ WORD", key="backspace_word", help="Delete last word", use_container_width=True):
377
+ if st.session_state.text_output:
378
+ words = st.session_state.text_output.rstrip().split()
379
+ if words:
380
+ words.pop()
381
+ st.session_state.text_output = " ".join(words)
382
  if words:
383
+ st.session_state.text_output += " "
384
+ with col3: # Use the 3rd column for SEND
385
+ if st.button("SEND", key="send_btn", help="Send message to assistant", use_container_width=True, type="primary"):
386
+ if st.session_state.text_output:
387
+ send_action = True # Set flag to process sending
388
+ # --- Settings Sidebar ---
389
+ with st.sidebar:
 
 
 
 
 
390
  # --- Settings Section Commented Out ---
391
  # st.title("Settings")
392
  # st.subheader("Interface")
 
437
  # st.rerun()
438
  # --- End of Settings Section Commented Out ---
439
 
440
+ st.divider()
441
+ # --- Chat History Display in Sidebar ---
442
+ st.subheader("Conversation")
443
+ chat_container = st.container(height=400) # Fixed height container
444
+ with chat_container:
445
+ for message in st.session_state.messages:
446
+ with st.chat_message(message["role"]):
447
+ st.markdown(message["content"])
448
 
449
+ # --- Process SEND Action ---
450
+ if send_action and st.session_state.assistant:
451
+ user_message = st.session_state.text_output
452
+ st.session_state.messages.append({"role": "user", "content": user_message})
453
 
454
  # Process with AACAssistant
455
+ try:
456
+ # Get the response from the AACAssistant
457
+ response = st.session_state.assistant.process_query(user_message)
458
+ # Add assistant response to chat history
459
+ st.session_state.messages.append({"role": "assistant", "content": response})
460
+ except Exception as e:
461
+ error_message = f"An error occurred: {e}"
462
+ st.error(error_message) # Show error in main area
463
+ st.session_state.messages.append({"role": "assistant", "content": f"*Error processing: {error_message}*"})
464
+ # Clear the board's text area after sending
465
+ st.session_state.text_output = ""
466
+ st.rerun() # Rerun to update chat and clear board
 
467