St.chat_message's order goes wrong

I’m trying to make small chatbot using streamlit as my fun project, but I wanted to make sign up function inside the chat itself.
Whenever I enter β€˜y’ into st.chat_input(), st.form() appears nicely.
But after I press st.form_submit_button() in st.form(), my previous chat β€˜y’ disappears and its order of texts scramble weirdly.
This is the code I was using.

from openai import OpenAI
import streamlit as st
import pandas as pd

st.title("Test")
st.caption("My Test powered by OpenAI LLM and Streamlit")

if "messages" not in st.session_state:
    st.session_state["messages"] = [{"role": "assistant", "content": "Hello!"}]
    st.session_state["signup"] = False
    st.session_state["pin"] = False

for msg in st.session_state.messages:
    st.chat_message(msg["role"]).write(msg["content"])
    try:
        user_database = pd.read_csv('your_local_directory')
    except FileNotFoundError:
        st.chat_message("assistant").write("Do you wanna join here?")
        st.session_state["pin"]=True
    else:
        st.chat_message("assistant").write('Please enter your username.')

if prompt := st.chat_input():
    st.chat_message("user").write(prompt)
if prompt == 'y':
    st.session_state["pin"]=True
    msg = "Okay! Nice to meet you sir. Please fill in the blanks for sign up."
    st.session_state.messages.append({"role": "assistant", "content": msg})
    st.chat_message("assistant").write(msg)
    st.session_state["signup"] = True
if st.session_state["signup"] == True:
    x=0
    with st.chat_message("assistant").form("Sign up Form"):
        username = st.text_input('Tell me the name you want to be called in here.')
        if username:
            x+=1
        password = st.text_input("Your Password", key="chatbot_api_key", type="password")
        if password:
            x+=1
        age = st.text_input('How old are you?')
        if age:
            x+=1
        nationality = st.text_input('Where are you from?')
        if nationality:
            x+=1
        city = st.text_input('Tell me which city are you living in.')
        if city:
            x+=1
        problem = st.text_input("What's your biggest problem right now?")
        if problem:
            x+=1
        col1,col2=st.columns([9,1])
        with col2:
            button=st.form_submit_button('ok')
        if button:
            if x==6:
                col1,col2,col3=st.columns([2,7,1])
                with col2:
                    st.write("This is your signup information.")
                    st.write("If you want to change your information, please fill it out now.")
                    st.write("""If you're happy with it, please say "I like it!" in the chat.""")
                    st.title('')
                df = pd.DataFrame({
                    "User Name": [username],
                    "Password": [password],
                    "age": [age],
                    "nationality": [nationality],
                    "city": [city],
                    "problem": [problem]
                })
                st.dataframe(df, use_container_width=True, hide_index=True)            
            else:
                pass

I’ll show you captured pictures of it.


At first it looks like this.
So I will give input β€˜y’ into st.chat_input(), and it returns something like this-


Now I’ll write every st.text_input(), like this just for the test.


Finally I’ll press st.form_submit_button().


Then it looks like this.
My first input, β€˜y’ is gone and its order of reply is scrambled.

Sorry, I’m just started learning about it so I’m total noob at it…
I wanna learn better and get better.
Can you tell me what I’ve done wrong about it?

Have a good day,
Johnny

edited: code block

We need to save the user input as well in the message history.

if prompt := st.chat_input():
    st.chat_message("user").write(prompt)
    st.session_state.messages.append({"role": "user", "content": prompt})

Hello @hyun_kyu_Cho,

Here’s an approach to restructuring your code to better manage message ordering and persistence:

import streamlit as st
import pandas as pd
import random

if "messages" not in st.session_state:
    st.session_state["messages"] = [{"role": "assistant", "content": "Hello!"}]
    st.session_state["signup"] = False

def add_message(role, content):
    st.session_state["messages"].append({"role": role, "content": content})

def display_messages():
    for msg in st.session_state["messages"]:
        st.chat_message(role=msg["role"], body=msg["content"])

display_messages()

# Handle chat input and signup process
prompt = st.chat_input()
if prompt:
    add_message("user", prompt)  # Add user's message to the session state

    if prompt.lower() == 'y' and not st.session_state["signup"]:
        add_message("assistant", "Okay! Nice to meet you. Please fill in the blanks for sign up.")
        st.session_state["signup"] = True  # Flag to indicate signup process has started

if st.session_state["signup"]:
    with st.form(key='signup_form'):
        username = st.text_input('Username')
        
        submitted = st.form_submit_button('Submit')
        if submitted:
            add_message("assistant", "Thanks for submitting your information!")
            st.session_state["signup"] = False  # Optionally reset signup flag

display_messages()

Kind Regards,
Sahir Maharaj
Data Scientist | AI Engineer

P.S. Lets connect on LinkedIn!

➀ Website: https://sahirmaharaj.com
➀ Email: sahir@sahirmaharaj.com
➀ Want me to build your solution? Lets chat about how I can assist!
➀ Join my Medium community of 30k readers! Sharing my knowledge about data science and AI
➀ 100+ FREE Power BI Themes: Download Now

1 Like

Thank you. I started using this and it helped.

ohh so if I use chat_input into function form, then I can use this more than once right? interesting.

1 Like

Thank you