こしあん
2023-01-24

Gradioでセッションの概念を導入する


2.2k{icon} {views}


Gradioでユーザー名などセッションごとに変数を記録したいときはよくあります。gr.Stateで簡単にできるので、アンチパターンとセットで紹介していきます。

アンチパターン:グローバル変数で状態を記録する

例えば、以下のようにログインした人の名前を記録して、挨拶するようなアプリを考えてみましょう。以下はアンチパターンです。

import gradio as gr

_USERNAME = None

def login(username):
    global _USERNAME
    _USERNAME = username
    return f"{username}さんがログインしました!"

def greet():
    global _USERNAME
    return f"{_USERNAME}さん、こんにちは!"

with gr.Blocks() as demo:
    with gr.Row():
        with gr.Column():
            tb_username = gr.Textbox(label="Input your name")
            button_login = gr.Button(value="Login")
        with gr.Column():
            message = gr.Markdown()
            button_greet = gr.Button(value="Greet")

    button_login.click(login, tb_username, message)
    button_greet.click(greet, None, message)

if __name__ == "__main__":
    demo.launch()

どの点がよくないのか見てみましょう。ブラウザを2つ使います。プログラムを実行したあとず最初のブラウザで開き、名前を「Joe Biden」にしてLogin→Greetしてみます。

これでうまくいっているように思えます。別ブラウザで同じURLを開き、名前を「Kim Jong-un」にしてLoginしてみます。

もとのブラウザに戻り、「Greet」を押してみましょう。

「Joe Biden」としてログインしたはずなのに、「Kim Jong-unさん、こんにちは!」と表示されてしまいました。これはユーザー名をセッションごとに記録していないので、Loginのたびにグローバル変数が上書きされてしまうからです。

解決策:gr.Stateを使う

このようなときのために、セッションごとのステートを記録できるオブジェクトgr.Stateが用意されています。Block以下でこのように使います。

import gradio as gr

def login(username, state):
    state["username"] = username
    return f"{username}さんがログインしました!", state

def greet(state):
    return f"{state['username']}さん、こんにちは!", state

with gr.Blocks() as demo:
    state = gr.State({
        "username": None
    })
    with gr.Row():
        with gr.Column():
            tb_username = gr.Textbox(label="Input your name")
            button_login = gr.Button(value="Login")
        with gr.Column():
            message = gr.Markdown()
            button_greet = gr.Button(value="Greet")

    button_login.click(login, [tb_username, state], [message, state])
    button_greet.click(greet, state, [message, state])

if __name__ == "__main__":
    demo.launch()

変更点は以下の通りです。

  • セッションの状態を記録するstateを追加
  • login, greet関数内の引数と返り値にstateを追加

これでユーザー名がセッションごとに記録されるので、Joe Bidenのセッションで「Kim Jong-unさん、こんにちは!」と表示されなくなります。



Shikoan's ML Blogの中の人が運営しているサークル「じゅ~しぃ~すくりぷと」の本のご案内

技術書コーナー

北海道の駅巡りコーナー


One Comment

Add a Comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です