Useful App Elements ------------------- Streamlit offers easy ways to interact with data and customize layouts for your app. Please see the `API reference `__. Features created by users in the Streamlit community are also included on the reference page as `components `__. App layouts and containers to organize elements within your app can be found `here `__. Magic and st.write ~~~~~~~~~~~~~~~~~~ Streamlit’s `Magic `__ feature utilizes ``st.write()`` to render code when variables or literal values are on an individual line of code. ``st.write()`` is Streamlit’s `“Swiss Army knife” `__ and decides how to best render the argument passed through in the app. Arguments can include strings, dataframes, errors, Matplotlib figures, Plotly figures, and more. .. code:: sos x = 10 'x', x # 👈 Draw the string 'x' and then the value of x Magic will render this in the app like: .. figure:: ../../img/streamlit/streamlit-magic.png :alt: A screenshot showing Magic’s rendering in app A screenshot showing Magic’s rendering in app .. code:: sos # Also works with most supported chart types import matplotlib.pyplot as plt import numpy as np arr = np.random.normal(1, 1, size=100) fig, ax = plt.subplots() ax.hist(arr, bins=20) fig # 👈 Draw a Matplotlib chart A Matplotlib chart will be drawn: .. figure:: ../../img/streamlit/streamlit-magic-mpl.png :alt: A screenshot showing Magic’s rendering in app A screenshot showing Magic’s rendering in app .. code:: sos import pandas as pd df = pd.DataFrame({ 'first column': [1, 2, 3, 4], 'second column': [10, 20, 30, 40] }) df # 👈 Draw the dataframe The dataframe will be appear with interactive column headers: .. figure:: ../../img/streamlit/streamlit-simple-df-interactive.gif :alt: A gif showing interactive columns of the simple dataframe A gif showing interactive columns of the simple dataframe Text Display ~~~~~~~~~~~~ See `documentation `__. Various text formats are shown below. Streamlit also supports `LaTeX `__ and `preformatted `__ text. .. code:: sos st.title("App Title") st.header("This is a header") st.subheader("This is a subheader") st.markdown("This is ***markdown*** text") st.caption("This is a caption") st.divider() .. figure:: ../../img/streamlit/streamlit-text.png :alt: Screenshot showing text on app Screenshot showing text on app Streamlit can also display code blocks. The default language syntax highlighting is Python. Syntax highlighting of other languages are also `available `__ or use ``language="none"`` for none. .. code:: sos code = '''def hello(): print("Hello, Streamlit!")''' st.code(code, language='python') .. figure:: ../../img/streamlit/streamlit-codeblock.png :alt: Screenshot showing code block on app Screenshot showing code block on app Interactive Widgets ~~~~~~~~~~~~~~~~~~~ See `documentation `__ for the full list and options. Selection Widgets ^^^^^^^^^^^^^^^^^ These include checkboxes, radio buttons, toggle buttons, and dropdown windows. .. code:: sos checked = st.checkbox('Box checked?') if checked: st.write('Yes') else: st.write('No') |Screenshot of checkbox| |image1| .. |Screenshot of checkbox| image:: ../../img/streamlit/streamlit-cb1.png .. |image1| image:: ../../img/streamlit/streamlit-cb0.png Slider ^^^^^^ .. code:: sos st.slider("Slider Label", # short caption to display with slider min_value=0, # minimum permitted value max_value=100, # maximum permitted value value=25, # starting value upon render, otherwise defaults to min_value key = "step_slider") # unique widget identifier (auto-generated unless specified) .. figure:: ../../img/streamlit/streamlit-slider.gif :alt: Gif showing slider widget in action Gif showing slider widget in action File Uploader ^^^^^^^^^^^^^ .. code:: sos uploaded_files = st.file_uploader("Choose a file", accept_multiple_files=True) for uploaded_file in uploaded_files: bytes_data = uploaded_file.read() st.write("filename:", uploaded_file.name) This will display the following after selecting file ``app.py`` with the widget: .. figure:: ../../img/streamlit/streamlit-file-upl.png :alt: Screenshot showing uploaded file Screenshot showing uploaded file Data Visualization ~~~~~~~~~~~~~~~~~~ Streamlit offers many ways to visualize and interact with data. See `data elements `__ and `chart elements `__ documentation for the full list and options. Some basic tools are shown below. Dataframes ^^^^^^^^^^ Many dataframe types (e.g., pandas, numpy) can be rendered using ``st.dataframe()``. These are displayed as an interactive table. Static tables are also available using ``st.table()``. Width and height are automatically assigned unless specified. .. code:: sos import streamlit as st import pandas as pd from sklearn import datasets iris = datasets.load_iris() df = pd.DataFrame(iris.data, columns=iris.feature_names) st.dataframe(df) # same as st.write(df) .. figure:: ../../img/streamlit/streamlit-df.png :alt: Screenshot showing dataframe Screenshot showing dataframe Data Editor ^^^^^^^^^^^ Streamlit also offers a `data editor widget `__ to enable editable dataframes using ``st.data_editor()``. Editable data is rendered into a table-like UI. Columns can be customized with ``st.column_config`` (see `documentation `__). *Note:* ``st.data_editor()`` offers a ``num_rows`` option that enables users to add or delete rows on the app. The default value for ``num_rows`` is ``fixed`` (e.g., disabled). If ``num_rows`` is set to ``dynamic``, the user can add or delete rows but loses column sorting ability. *Note:* ``st.data_editor()`` also offers a ``disabled`` option that renders the column uneditable so that values are fixed. The ``disabled`` option is disabled by default, allowing editing of values. To disable editing of specific columns, specify column names for this option (e.g., ``disabled=["columnName"]``). Columns that are disabled will **NOT** show the following icon: .. code:: sos import streamlit as st import pandas as pd # original dataframe df = pd.DataFrame( [ {"item": "P10 Tips", "count": 4, "category": "General Supply", "stockroom": True}, {"item": "P200 Tips", "count": 5, "category": "General Supply", "stockroom": True}, {"item": "P1000 Tips", "count": 3, "category": "General Supply", "stockroom": True}, {"item": "Goat Anti-Rb AF488", "count": 2, "category": "Antibodies", "stockroom": False}, {"item": "Donkey Anti-Rat AF647", "count": 3, "category": "Antibodies", "stockroom": False}, ] ) # customize dataframe edited_df = st.data_editor( df, # source dataframe num_rows="dynamic", # enable addition and removal of rows column_config={ "item": "Item Name", # rename variable/column title "count": st.column_config.NumberColumn( "Inventory", # rename variable/column title help="Number of boxes currently in inventory", # hover-over tooltip min_value=1, max_value=10, # arbitrary max value for inventory count step=1, format="%d", # integer format ), "category": st.column_config.SelectboxColumn( "Category", options=[ # dropdown options "General Supply", "Antibodies", "Enzymes", ], ), "stockroom": st.column_config.CheckboxColumn( "Stockroom", # rename variable/column title help="Can be purchased from stockroom?", # hover-over tooltip ), }, disabled=["item", "stockroom"], # column names listed here will disable value editing hide_index=True, ) low_inventory = edited_df.loc[edited_df["count"] <= 3]["item"] need_inventory = low_inventory.tolist() new_line = " \n" st.write(f"The following items have LOW INVENTORY (less than 3 units left): \n \n {new_line.join(need_inventory)}") .. figure:: ../../img/streamlit/streamlit-data-editor-values.gif :alt: A gif showing dataframe editing A gif showing dataframe editing .. figure:: ../../img/streamlit/streamlit-data-editor-dropdown.gif :alt: A gif showing dataframe editing A gif showing dataframe editing .. figure:: ../../img/streamlit/streamlit-data-editor-other.gif :alt: A gif showing dataframe editing A gif showing dataframe editing Plots ~~~~~ Streamlit offers many ways to plot data. Streamlit offers simple “native” commands (e.g., ``st.scatter_chart()``) and supports many charting libraries (see `documentation `__). Supported libraries include `Matplotlib `__, `Altair `__, `Plotly `__, `Bokeh `__, and more. An example is shown below using the same ``iris`` dataset from above. .. code:: sos import matplotlib.pyplot as plt fig, ax = plt.subplots() scatter = ax.scatter(iris.data[:, 0], iris.data[:, 1], c=iris.target) ax.set(xlabel=iris.feature_names[0], ylabel=iris.feature_names[1]) ax.legend(scatter.legend_elements()[0], iris.target_names, loc="lower right", title="Classes") st.pyplot(fig) .. figure:: ../../img/streamlit/streamlit-iris.png :alt: Screenshot showing scatter plot of dataframe Screenshot showing scatter plot of dataframe Chat Elements ~~~~~~~~~~~~~ Streamlit offers chat elements that can be applied to develop powerful conversational AI tools. See documentation on `chat elements `__ and `session state `__ for more details. Session state will store chat history inside the user session. Streamlit also supports more mature, third-party elements for advanced chatting capabilities. Built-In Chat ^^^^^^^^^^^^^ A basic chat box is shown below. Using ``st.chat_input()`` will provide a chat input widget where the user can type in a message. The returned value of this widget will be the user’s input. See more details `here `__. .. code:: sos import streamlit as st prompt = st.chat_input("Say something") if prompt: st.write(f"User has sent the following prompt: {prompt}") .. figure:: ../../img/streamlit/streamlit-chat.gif :alt: Screenshot showing chat box Screenshot showing chat box Using ``st.chat_message()`` will render a message container (similar to “text bubbles”) that can return any Streamlit element using the ``with`` notation. ``st.chat_message()`` requires a ``name`` parameter assigning a name to the message author that cannot be left empty. Default avatars will be assigned when ``name`` is set to ``user``, ``human``, ``assistant``, or ``ai``. Custom strings and avatars are allowed. See more details `here `__. .. code:: sos import streamlit as st with st.chat_message("assistant"): # same avatar as "ai" st.write("Hello 👋") with st.chat_message("user"): # same avatar as "human" st.write("Hello 👋") with st.chat_message("dinobot", avatar="🦖"): # custom name and avatar st.write("Hello 👋") .. figure:: ../../img/streamlit/streamlit-chat-avatars.png :alt: Screenshot showing different chat avatars Screenshot showing different chat avatars The following code example is equivalent to the one above but does not use the preferred ``with`` notation. .. code:: sos import streamlit as st message = st.chat_message("dinobot", avatar="🦖") message.write("Hello 👋") A chat bot can now be created by combining ``st.chat_message()``, ``st.chat_input()``, and ``session state``. The following code is a simple chatbot GUI example that provides a skeleton for more sophisticated chatbots. These can also be enhanced to create a `ChatGPT-like experience `__ using `OpenAI `__ and `Streamlit secrets `__. .. code:: sos import streamlit as st import random # randomly select from a list of responses provided below import time # adds delay to simulate chatbot "thinking" before responding st.title("Simple Chatbot") # Initialize chat history if "messages" not in st.session_state: st.session_state.messages = [] # Display chat messages from history on app rerun (but resets when refreshing app window) for message in st.session_state.messages: with st.chat_message(message["role"]): st.markdown(message["content"]) # Accept user input if prompt := st.chat_input("What is up?"): # `:=` operator assigns user input and checks if it's not `None` # Display user message in chat message container with st.chat_message("user"): st.markdown(prompt) # Add user message to chat history st.session_state.messages.append({"role": "user", "content": prompt}) # Display assistant response in chat message container with st.chat_message("assistant"): message_placeholder = st.empty() full_response = "" assistant_response = random.choice( [ "Hello there! How can I assist you today?", "Hi, human! Is there anything I can help you with?", "Do you need help?", ] ) # Simulate stream of response with milliseconds delay for chunk in assistant_response.split(): full_response += chunk + " " time.sleep(0.05) # Add a blinking cursor to simulate typing message_placeholder.markdown(full_response + "▌") message_placeholder.markdown(full_response) # Add assistant response to chat history st.session_state.messages.append({"role": "assistant", "content": full_response}) .. figure:: ../../img/streamlit/streamlit-chat-simplegui.gif :alt: A gif showing the simple chatbot gui in action A gif showing the simple chatbot gui in action Third-Party Chat ^^^^^^^^^^^^^^^^ Streamlit highlights many third-party features developed by users in the Streamlit Community, including `st-chat `__ which provides an alternative chatbot UI. PolusAI uses this interface as the framework to build the **Ask Athena** bots. To use st-chat, install the package into the conda environment using the terminal by typing ``pip install streamlit-chat``. After successful installation, import the ``message`` function from ``streamlit_chat`` inside your ``app.py`` file. .. code:: sos import streamlit as st from streamlit_chat import message Chat messages can be displayed using ``message()``. Passing the argument ``is_user = TRUE`` will align the message to the right and assign a separate avatar. .. code:: sos message("Hello User. I am a bot.") message("Hello bot!", is_user=True) .. figure:: ../../img/streamlit/st-chat-simple.png :alt: A screenshot of simple messages using st-chat A screenshot of simple messages using st-chat Session states are usually initialized as empty lists (i.e., ``[]``). If you would like to preload messages into the session history, these messages can be inserted into the corresponding session state using ``default = ['string 1', 'string 2']``.\` .. code:: sos # initializes values in session state st.session_state.setdefault("generated", default=[]) st.session_state.setdefault("past", default=[]) Combining additional third-party components, such as ``streamlit.components.v1``, messages can also integrate HTML. .. code:: sos from streamlit.components.v1 import html The following example incorporates HTML, starts the session with pre-defined messages, and preloads these messages into the chat window upon initializing the app. .. code:: sos # define example variables img_path = "https://www.groundzeroweb.com/wp-content/uploads/2017/05/Funny-Cat-Memes-11.jpg" youtube_embed = ''' ''' # pre-define user input messages as an example to be preloaded in chat history st.session_state.setdefault( 'past', ['show me a funny cat meme', 'and a funny cat video'] ) # pre-define bot response messages as an example to be preloaded in chat history st.session_state.setdefault( 'generated', [{'type': 'normal', 'data': f''}, {'type': 'normal', 'data': f'{youtube_embed}'}] ) # create chat window placeholder chat_placeholder = st.empty() # preload pre-defined messages in session state history inside chat window with chat_placeholder.container(): for i in range(len(st.session_state['generated'])): # output user input message(st.session_state['past'][i], is_user=True, key=f"{i}_user") # output bot output message( st.session_state['generated'][i]['data'], key=f"{i}", allow_html=True, is_table=True if st.session_state['generated'][i]['type']=='table' else False ) .. figure:: ../../img/streamlit/st-chat-preload.png :alt: A screenshot of preloaded chat using st-chat A screenshot of preloaded chat using st-chat