gradio icon indicating copy to clipboard operation
gradio copied to clipboard

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

Open hshen14 opened this issue 2 years ago • 12 comments

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).

hshen14 avatar Feb 01 '23 01:02 hshen14

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

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

abidlabs avatar May 10 '23 22:05 abidlabs

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

oaksharks avatar May 18 '23 04:05 oaksharks

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

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

abidlabs avatar May 19 '23 21:05 abidlabs

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?

oaksharks avatar May 23 '23 02:05 oaksharks

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
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.

deckar01 avatar Aug 27 '23 16:08 deckar01

@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.

arian81 avatar Feb 05 '24 17:02 arian81

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

abidlabs avatar Feb 05 '24 17:02 abidlabs

+1 to see this happen.

kerthcet avatar Feb 06 '24 03:02 kerthcet

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.

Moibe avatar Feb 28 '24 00:02 Moibe

@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).

JackismyShephard avatar Apr 26 '24 22:04 JackismyShephard