How to create a DIY comment component in streamlit apps

Normally when we develop a Machine Learning model and use Streamlit to turn it into a web application, comment section is practically useful for us to get interactive discussion or feedbacks from the viewers. Unfortunately, at the time of writing this blog, it seemed like Streamlit does not offer any component to suit this purpose.

This requirement happened to me when it come to building one of my first streamlit applications, and I was actually searching in Streamlit community but it was no luck as no component to suit my need. Therefore I thought why we don't build a simple comment section just using the csv file for database storage. 

The example below illustrates how the comment section looks like. It starts with a simple data analysis stuff (or you can place your ML model here) following with the comment section which includes all the comments from viewers and a form for submitting new comments. The link for demostration is as follow https://comment-section.streamlit.app/


Before jumping into the detail of coding explanation, I will first show the format of the csv file to store viewer's comments. From the figure below, the first three columns are inputs from the viewer, last two columns capture our replies if any. These columns will be rendered in the streamlit web page, for example the comment from Jane in the figure above. This csv file is stored in the same folder with the main python code. 


Importing the libraries

import streamlit as st
import pandas as pd
from datetime import datetime

Creating a chart analysis

This code snippet simply creates a dataframe for monthly sales, then renders this dataframe and a bar chart on the streamlit columns. 
 
#writing chart title 
st.title('Monthly sales analysis')
st.write('')

#creating data frame for monthly sales
df = pd.DataFrame({'Month' : ['Jan', 'Feb', 'Mar','Apr', 'May','Jun'],
                   'Sales': [1000, 2000, 1540, 1700, 1320, 1120]})

#rendering dataframe on the left and chart on the right panel
col1, col2 = st.columns([1,3])   
with col1:
  st.dataframe(df)
with col2:
  st.bar_chart(df,x='Month',y='Sales')

Loading a viewers' comments database

As mentioned earlier, this example uses the csv file for storing viewers' comments. Alternatively, you can connect to other data sources e.g. SQL Server or Google sheet instead. This csv file is loaded for the first time then can be stored in the Streamlit session state when the page re-runs or re-renders but not refreshing. This is useful to avoid accessing the csv file if not necessary.

#check if 'comment' is not existed in session state then load csv and store in the session state
if 'comment' not in st.session_state:
    df_comment = pd.read_csv('comment.csv')
    st.session_state.comment = df_comment
#or if 'commment' is existed then restore the csv comment from the session state 
else:
    df_comment = st.session_state.comment

Rendering the comment section

All the viewers' comments and a submission form are rendered within the streamlit container component called expander. Each comment will be loaded from the csv dataset and concatenated to the comment and reply template.   

with st.expander('💬 Open comment section'):
   #formating the output of comments and replies
   COMMENT_TEMPLATE = '**{}** - {}\n\n|    {}'
   REPLY_TEMPLATE = '\n\n      |    **Reply**: {} - {}'
  
   #iterate each comment in the dataset and render it on the web page      
   for _, comment in df_comment.iterrows():
      str = COMMENT_TEMPLATE.format(comment['Name'],comment['Date'],comment['Comment']) +\ 
            ('' if pd.isnull(comment['Reply']) 
                else REPLY_TEMPLATE.format(comment['Reply'],comment['Reply Date']))

   st.markdown(str)

Adding new comments

This sub-section uses Streamlit component called form which is a container that visually groups all elements and widgets together with a submit button. When users click submit then new comment will be added in the dataframe and physically writen into the csv file. Then the web page is forced to re-run to refresh all new comments. 

with st.form('comment_section', clear_on_submit=True):
   #adding text inputs for name and comment, and a submit button
   name = st.text_input('Name')
   comment = st.text_area('Comment')
   submit = st.form_submit_button('Submit')
                    
   if submit and name!= '' and comment!='':
      #getting server local time
      date = datetime.now().strftime("%d/%m/%Y, %H:%M:%S")
      #adding new comment to the comment dataframe
      df_comment = df_comment.append({'Name':name,'Comment':comment,'Date':date}, ignore_index=True)
      #overwriting the dataframe into csv comment file
      df_comment.to_csv('comment.csv',index=False)
      #update the session state to flag a new comment is justed added
      if st.session_state.just_submitted == False:
         st.session_state.just_submitted = True
      #delete the session state to force to refresh all comments
      del st.session_state.comment
      st.experimental_rerun()

To response to the comments, just simply open the csv file and input your comment, date and save it. This example can be run locally or deployed into a shareable web application using Streamlit. To do so, we need to create a  new repository in Github, load the python code, csv data and the requirements file, create account in Streamlit and link to the Github. 



I hope this example could help and all the source code can be found in the link below. Cheer!


No comments:

Post a Comment