How to create multiple chat_input in same app

Grabbing information from Session State within a callback is indeed one way to pass information. Are you seeing the value in Session State before you click the form submit button? A helpful thing to debug is to st.write(st.session_state at the beginning and end of your whole script. (In your entrypoint file, add it immediately after your import statements and again as a final line (not in a function or conditioned on anything).

Since the first snippet is incomplete, I can’t really say what might be happening. It’s possible that something after the form submit button is overwriting those values. With the full Session State written within your app, you should be able to see at the end of your app page what is in Session State before you click the submit button.

what is happening is that u cannot apparently use this way. One has to use the session state in the “key” of each widget under st.form and access its value that way

Ah yes, sorry I didn’t look closely enough. You are correct; since you are using a form, you should have keys on the on the form widgets instead of taking the form-widget outputs and writing them to Session State. As shown above, Session State won’t be updated with the new widget values until after the callback executes. That is described here: Using forms - Streamlit Docs

I want to understand one thing from u.

Pls look at the below code. Thats all u need for this Q and shouldn’t be half q.

When I click the “Create segment” button, it also starts again generating the top messages in this code especially below ones:

message = “Fantastic, here’s what we have finally have:\n\n”
# for key, value in st.session_state.merged_arguments.items():
# message += f"{key}: {value}\n\n"
# message += “Let’s get your segment created!”

These are before the button and have been shown already to user and all I want is statements within button to be shown but not these again.

How do I prevent that? Do I need a callback and not IF Block within button?

 st.chat_input("Almost there, finalize segment...", disabled = True)
        with st.chat_message("assistant", avatar = "💁"):
            message = "Fantastic, here's what we have finally have:\n\n"
            # for key, value in st.session_state.merged_arguments.items():
            #     message += f"**{key}**: {value}\n\n"
            # message += "Let's get your segment created!"
            stream_message(message)
            time.sleep(1)
            display_validated_response(st.session_state.merged_arguments)
        with st.chat_message("assistant", avatar = "💁"):
            stream_message("\n\nLet's get your segment created!")

            # Place the button in the center column
            # Create three columns for centering, with the left column slightly larger
            _, center_col, _ = st.columns([1.4, 2, 0.8])

            # Place the button in the center column
            with center_col:
                st.markdown('<div class="centered-button">', unsafe_allow_html=True)
                if st.button("Create Segment"):
                    st.session_state.current_stage = "segment_details"
                    st.session_state.re_ask = False
                    st.switch_page("pages/2_🪢_Segment_Explainability.py")
                st.markdown('</div>', unsafe_allow_html=True)

I’m not sure with the incomplete code, but the thing to understand is that everything reruns when a button is clicked. Anything conditioned on a button doesn’t just get added to the screen; everything before it (up to and including the button) reruns after a click and then the part conditioned on the button executes.

If you are trying to replace some text with the click of a button, you’ll need to have a conditional on that preceding text, accordingly.

I can’t see what preceding conditionals you have, but yes, a likely better pattern is to toggle values in Session State with a callback. This ensures the values in Session State change before the rerun.

you dont need other code and its not incomplete. All I want to know is the code I sent, if I need to prevent top messages from again printing when clicked the button below, how to do that? Looks like IF block in a button isn’t useful as it will do any code before it rerun which I don’t want.

Can someone put the code lines under IF Button in a callback and it will work?

Here’s an example with a button and a callback: Button behavior and examples - Streamlit Docs

In your case, you might not need to pass an argument and can just define a function (with no arguments) that sets the values in Session State as desired.

I changed the above IF button like below

st.button(“Create Segment”,
on_click=lambda: (
setattr(st.session_state, “current_stage”, “segment_details”),
setattr(st.session_state, “re_ask”, False),
st.rerun()
))

However, I get a message:

Calling st.rerun() within a callback is a no-op.

I don’t want to define a callback function explictly for all buttons, so I am using lambda function directly inside a callback of button.

You can remove st.rerun() from lambda function. You cannot (and don’t to) call st.rerun() in a callback function. The app is already at the start of a rerun when the callback is being executed.

I also learnt that and removed it. but there’s a problem:

Original code:

 if st.form_submit_button("Submit Corrections"):
                           st.session_state.merged_arguments.update(edited_fields)
                           st.session_state.edit_mode = False
                           st.session_state.validate_substage = "initial"
                           st.rerun()

Lambda style code:

              st.form_submit_button("Submit Corrections", 
                        on_click=lambda: (
                            st.session_state.merged_arguments.update(edited_fields),
                            setattr(st.session_state, "edit_mode", False),
                            setattr(st.session_state, "validate_substage", "initial")
                            ))

problem is lambda one isn’t updating merged_arguments in line st.session_state.merged_arguments.update(edited_fields).

Callbacks (and their arguments) are established when the widget is rendered, not when widget is clicked/used. In the case of a form, you need to assign keys to the widgets within the form, then grab their new values from session state within the callback. I don’t know that you can accomplish this with a lambda function, but the traditional method is shown here: Using forms - Streamlit Docs