Hello Streamlit community!
I’m having an issue with the chat component. While conversing with my LLM, I want to display a button that can also execute code, particularly to display a stream. So, I’m using Streamlit buttons with the “on_click” and “kwargs” attributes. The code and logic work fine. However, the stream result displays at the top of the conversation instead of appearing at the end. Could anyone help me solve this issue?
Here’s a complete code to replicate my use case.
import streamlit as st
import time, random
# Simple history init
title = "Streaming problems from function callback"
st.set_page_config(page_title=title)
st.title(title)
if "messages" not in st.session_state:
st.session_state["messages"] = [{"role": "assistant", "content": "Hello"}]
def build_history(messages):
for msg in messages:
st.chat_message(msg["role"]).write(msg["content"])
build_history(st.session_state.messages)
# Simple streaming function to illustrate the problem
def stream_single_message_for_demo(message):
for token in message.split(" "):
time.sleep(random.random() * 0.15)
yield f"{token} "
# My callback function
def func(**kwargs):
full_buffer = st.chat_message("assistant").write_stream(stream_single_message_for_demo(kwargs["content"]))
st.session_state.messages.append({"role": "assistant", "content": full_buffer})
# My chat input
if prompt := st.chat_input():
# Display user message
st.chat_message("user").write(prompt)
st.session_state.messages.append({"role": "user", "content": prompt})
# Display assistant message, miror of user for this example
st.chat_message("assistant").write(prompt)
st.session_state.messages.append({"role": "assistant", "content": prompt})
# Streamlit builder function
builder = st.button
# Arguments to the final function
kargs = { "content": "This is a streamed message from function click, he should appear at the bottom, but is streamed at the top of the page!" }
# Arguments to streamlit component builder
args = { "label": "Click to stream the demo", "on_click": func, "kwargs": kargs }
# Building streamlit component
builder(**args)