The endpoint works perfectly. However, I am trying to extend a little bit the functionality and I have some troubles.
My app is a chat app that receives the assistant responses via API. When I’m trying to access the streamlit context to add a new message in the conversation I receive the following error logged 3 times in the console: 2024-01-16 18:27:33.407 Thread 'MainThread': missing ScriptRunContext
class HelloHandler(RequestHandler):
def get(self):
with st.chat_message("assistant"):
st.markdown("Hello World")
self.write({'message': 'hello world'})
Let’s say for simplicity that each time a request is received in the REST API endpoint, some message should be displayed on the screen, and thus streamlit primitives should be called.
sorry, but generally that doesn’t make any sense. An API is for code to interact with. If you want to render UI/HTML then that a page. Fine/legit if that’s actually what you want and taking this approach to have more control over page requests like routing and other middleware. If that is what you want to do, to start with your handler class might need to inherit from a different class to make life easier returning HTML.
Re using ST components to render that HTML likely isn’t going to work given dropping down to this layer you are side stepping all the ST framework. Remember ST uses iframes and websockets to handle components. The framework is stateful to that extend.
if what you are try to do is have callback endpoint or similar that side effect the app and the UI renders things based on those then change the logic in the endpoint to update a datastore (in memory like session state, a database etc.) Then adjust your page UI logic to render based on the data source. If you want the UI to live update you might need some extra logic (or if you are lucky you might get it for free because of how ST works, I don’t know)
I’m not an ST expert by a long shot so might be wrong.
one more reply one this, maybe I’ll manage to make you understand my need. Let’s take the following example for what you can do using a classic framework (HTML+CSS+JS+some backend+external API):
User triggers a job in the UI
Backend sends to an external API the job (request payload containing a webhook_url). The job might take several minutes, so the API is designed asynchronous: returns a task_id but instead of backend checking the API from time to time, the API itself uses the webhook_url to post the job result once it’s done
Backend receives the job result from the external API
Backend REST API endpoint uses websockets to communicate with Frontend to display some info to the user.
That’s the “Why”
Starting from that, I need a similar behaviour in Streamlit:
0. Streamlit exposes a REST API endpoint (Tornado)
User sends message
Streamlit calls the external API (request payload containing webhook_url as the REST API endpoint). The job is posted by the external API
Backend receives the job result from the external API
And now… I am trying to mimic the web socket solution in Streamlit … by using directly the Streamlit context.
Hey,
yes, I understand what you want to achieve. It’s basically what I imagined in the last paragraph, in my previous reply.
My opinion is still that the approach in your solution either will not work or will be brittle.
IMHO the better approach is to decouple via a store of some sort. Getting the webhook handler to update session state attached to UI components is one thing you can try.
I can absolutely see the need for some webhook thing. I have been trying to see if I can create a multi-user chat bot in Streamlit, can by the looks of thigs it cant be done. This is a real shame because the widgets in Streamlit are amazing.
It is very off that Streamlit does not offer these types of features. They are pushing as a ML/ AI platform, and would this will involve long running processes.
Thanks for stopping by! We use cookies to help us understand how you interact with our website.
By clicking “Accept all”, you consent to our use of cookies. For more information, please see our privacy policy.
Cookie settings
Strictly necessary cookies
These cookies are necessary for the website to function and cannot be switched off. They are usually only set in response to actions made by you which amount to a request for services, such as setting your privacy preferences, logging in or filling in forms.
Performance cookies
These cookies allow us to count visits and traffic sources so we can measure and improve the performance of our site. They help us understand how visitors move around the site and which pages are most frequently visited.
Functional cookies
These cookies are used to record your choices and settings, maintain your preferences over time and recognize you when you return to our website. These cookies help us to personalize our content for you and remember your preferences.
Targeting cookies
These cookies may be deployed to our site by our advertising partners to build a profile of your interest and provide you with content that is relevant to you, including showing you relevant ads on other websites.