gradio-app / gradio

Build and share delightful machine learning apps, all in Python. 🌟 Star to support our work!
http://www.gradio.app
Apache License 2.0
32k stars 2.38k forks source link

Support session state across multiple pages or page refresh (e.g. with LocalStorage) #3106

Open hshen14 opened 1 year ago

hshen14 commented 1 year ago

Right now, the session state is either global shared between users or local within a page. We are seeing the needs to support session state across multiple pages.

E.g., we host a service on Hugging Face spaces, and we ask users to login with token first before using the spaces. The ideal case is users just need to login once but use the spaces multiple time without further login (even the page is refreshed, or multiple pages requires login status).

decent-engineer-decent-datascientist commented 1 year ago

@abidlabs is this something that's on the roadmap?

abidlabs commented 1 year ago

We’re planning on tackling it but probably not anytime soon as we have competing priorities at the moment

oaksharks commented 1 year ago

Hi, abidlabs, Is there a workaround to keep chat histroy in gr.Chatbot after refreshing a page?

decent-engineer-decent-datascientist commented 1 year ago

@abidlabs ^ that is my use case as well; curious what your recommended workaround is.

abidlabs commented 1 year ago

Hi folks! It is possible to use localstorage by using custom javascript for now. Here's a gradio app that does this: https://huggingface.co/spaces/radames/gradio_window_localStorage

oaksharks commented 1 year ago

Hi @abidlabs, How can I find the session data associated with the page after the user refreshes it using the above configuration? I mean, although it can store data, how can i find previous gr. State?

deckar01 commented 1 year ago

It would be nice to persist this on the backend so that authenticated sessions synchronize across devices also. I suspect this is actually simpler to implement. (I will assume in-memory persistence, because db-like schema migrations add significant complexity.)

Here is my current workaround:

import gradio as gr
from helper import persist

with gr.Blocks() as demo:
    foo_txt = persist(gr.Textbox())
    bar_txt = persist(gr.Textbox())

demo.launch(auth=[("a", "1"), ("b", "2")])
helper.py ```py from gradio.context import Context from gradio import Request def persist(component): sessions = {} def resume_session(value, request: Request): return sessions.get(request.username, value) def update_session(value, request: Request): sessions[request.username] = value Context.root_block.load(resume_session, inputs=[component], outputs=component) component.change(update_session, inputs=[component]) return component ```

I suppose this could be encapsulated in gradio for the slightly sweeter gr.Textbox(persist=True) syntax. A complete solution should probably also detect the auth type and choose the session key accordingly. It is also possible to use request cookies for the session ID so that the UX feels like LocalStorage for anonymous users.

arian81 commented 7 months ago

@abidlabs Hey is there any update on this? I think persisting sessions would be a very useful feature and I see this issue is from a year ago.

abidlabs commented 7 months ago

I agree, cc @aliabid94 perhaps if he has bandwidth.

kerthcet commented 7 months ago

+1 to see this happen.

Moibe commented 6 months ago

Hi folks! It is possible to use localstorage by using custom javascript for now. Here's a gradio app that does this: https://huggingface.co/spaces/radames/gradio_window_localStorage

It is a good example on how to set storage, but not on how to get storage. In the sample it gets the localStorage variable but never use it within the code. The results that the app display come directly from the input fields and not from the localStorage. For someone that is not an expert like me, it would have been very useful that this code also examples on how to retrieve the localStorage not just setting it.

JackismyShephard commented 4 months ago

@deckar01 Your solution is really neat and in my opinion preferable to using localstorage. The only problem is that it does not work with accordions or any other block types as they have no associated change function. It would be even neater if we could somehow also remember the state of accordions (i.e. whether they are closed or open and whether they are visible or not).