4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

今更ながら、gradioの使い方解説してみた!#Python

Last updated at Posted at 2025-05-19

こんにちは!@2626です。

久しぶりの投稿となりましたが、今回は gradio という python だけでフロントエンドを作成できるライブラリ今更見つけましたので、その使い方について紹介していきます!!!

背景

弊社では生成 AI の利活用を積極的に推進しており、「どうやって業務に使えるかな…。」と試行錯誤しているところでございます。しかし、業務に使う方法を考えるほど、「Web の生成 AI サービスでは痒いところに手が届かないな…。」という気持ちになることがあります。

例えば、生成 AI 界隈で人気を継続している RAG などの新しい技術を試したいときに、どうしても自分で作らないといけない場合があったりします。一方で、生成 AI 界隈の進化に対応するためには、自分で作るのにそれほど時間を掛けたくありません。作っている最中に「新しい仕組みが出てきた!」「新しいサービスが出てきた!」というのは珍しくありません。

特に、新しい生成 AI の仕組みやアーキテクチャを試したいときに、「Webフロントエンドにそれほど時間を掛けたくないな…。」と正直思っていました。これは筆者がバックエンド専門だったからというのも背景にあるかもしれません。そういった背景もあり、サクッと Web フロントエンドを作成できるツールがないかなと探っておりました。

gradio とは?

概要

Gradio(グラディオ) は、Pythonで機械学習モデルや関数のインターフェース(UI)を超簡単に作れるライブラリです。

Hugging Face などでも採用されており、Github の Issue でも、38.1k(2025/5/18 時点)となっており、今でも盛んに開発が行われています。

また、ChatBot の性能を比較することができる Web サイト、Chatbot Arena なんかも gradio で実装されていますね。

gradio の他の特徴としては、画像をアップロードして予測結果を返すモデル、テキストを入力して自然言語処理するツールなどを、たった数行のコードでWebアプリ化できます。公式にも似たような記載がありますが、下記のような特徴があると思います。

  • 数行のコードでWebアプリが完成
  • テキスト・画像・音声など豊富な入力/出力形式に対応
  • Hugging Faceと連携してデプロイも簡単
  • ローカルでも、インターネット経由でもすぐに使える

gradio vs Streamlit

同じようなライブラリとして、Streamlit などが有名でしょうか。筆者は Streamlit については詳しくないので、詳しい比較は他の方にお任せしますが、

  • シンプルに作って、簡単に動かしたいなら gradio
  • ある程度柔軟にUIを構築して使いやすくしたいなら Streamlit

という印象です。「gradio vs streamlit」なんかで検索すると記事が出てきますので、ご参照ください。

備考

なお、今回の説明に使用した gradio のバージョンは 5.25.2 です。執筆時点でバージョンの変更により、実装方法が変化している可能性がある点、予めご了承ください。

使い方

ではここから、実際のコーディングを見ながら解説していましょう。

Blocks

公式には、「Blocks is Gradio's low-level API that allows you to create more custom web applications and demos than Interfaces (yet still entirely in Python).」と書かれていますね。大まかには一画面の構成全体を作るものって言うイメージでしょうか。

もう一つ interface というものもありますが、

  • Interface:シンプルなUIを作る方法
  • Blocks:複数の入力・出力、細かいレイアウトやカスタマイズが可能な上級向けの方法

という認識です。使い方としては with 句で囲うことによって、一つのブロックを表現します。例えば

  • 名前の入力欄(Textbox)
  • 実行するボタン(Button)
  • ボタンを押すとメッセージを返す出力欄(Textbox)

を実装すると下記のようになります。

import gradio as gr

with gr.Blocks() as demo:
    gr.Markdown("## 名前を入力して挨拶しよう!")

    with gr.Row():
        name = gr.Textbox(label="お名前")
        greet_btn = gr.Button("挨拶する")

    output = gr.Textbox(label="メッセージ")

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

    greet_btn.click(fn=greet, inputs=name, outputs=output)

実際の画面はこちらです。

image.png

名前を入力し、「挨拶する」ボタンを押すと…

image.png

こんな感じで「こんにちは、やまだたろうさん!」と出力されましたね。

コンポーネント

ここまでTextBoxButtonを使った gradio の簡単なサンプルを見ました。ここからはTextBoxButtonを含む、様々なコンポーネントを紹介していきます。

Textbox

名前の通り、文字列を表示することのできるボックスのことです。ここでは、よく利用する引数を紹介していきます。

テキストボックスの活性・非活性

interactive=Falseにすることで、テキストボックスを入力不可にすることができます。

gr.Textbox(interactive=False)

テキストによる追加情報

placeholderを設定することで、プレースホルダ(ユーザが入力するまでにボックス内に表示されているテキスト)を設定することができます。また、infoを設定することで、補助的な説明文を追加できます。更に、valueを設定することで、初期値を設定することができます。

gr.Textbox(placeholder="ここに名前を入力してください", info="姓名の間は空けないでください")

image.png

行の設定

linesを設定することでテキストエリアの最低行数が設定でき、max_lengthで文字数の最大数を入力することができます。

gr.Textbox(lines=3, max_length=10)

image.png

ちなみに改行も1文字使うので注意です。

ボタンの設定

テキストボックスには、いくつかのボタンが用意されています。submit_btn, stop_btn, show_copy_buttonです。show_copy_buttonTrue/Falseを設定するだけですが、submit_btn, stop_btnstrになっているので、ボタンを自由に作成できます。(画像は埋め込むことができませんが…。)

gr.Textbox(show_copy_button=True, stop_btn=True, submit_btn=True)

image.png

gr.Textbox(submit_btn="▶ Submit", stop_btn="⏸ Stop")

image.png

MultimodalTextbox

テキスト入力だけでなく、ファイル添付もしたい場合、MultimodalTextboxを使うと便利です。ほとんどの設定はTextboxと同じです。(max_length以外は同じはず…。)その他、ファイル添付に関する引数が数多く用意されています。

ファイル添付の種類・数

引数file_types, file_countが用意されており、それぞれ添付できるファイルの種類、数を設定できます。file_types'image', '.json', '.mp4'などが設定可能で、特定の拡張子のみ、または特定のメディアタイプのみなど、設定が可能です。"file"を設定することで全てのファイルが添付可能…と思いきや、どんな拡張子のファイルを添付してもいいというわけではないようです。

file_countは数字を設定するのではなく、'single', 'multiple', 'directory'を設定します。字の通りですが、左から「添付できるファイルは1つのみ」「複数ファイル添付できる」「ディレクトリが可能」です。

また、sourcesを指定すると、ファイル添付を表すボタンと録音ボタンを実装可能です。

gr.MultimodalTextbox(file_count="multiple", file_types=["text"], sources=["microphone","upload"])

image.png

クリップのボタンを押すと、エクスプローラーが開きます。

image.png

今はfile_types=["text"]としているので、添付できるファイルは下記のようです。

image.png

Button

Gradio にはボタンも標準実装されています。

gr.Button(value="submit")

他にはsize(ボタンの大きさを設定する)、icon(ボタン内に画像を埋め込む)などが良く使われるでしょうか。

image.png

今のところ使用したことはありませんが、Buttonの派生クラスとしてClearButton, DownloadButton, DuplicateButton, LoginButton, UploadButtonなどがあるので、用途に合わせて使い分けてみてはいかがでしょうか?

Slider

スライダーも Gradio には用意されています。label, infoは Textbox と同様に設定できます。maximum, minimumで最大最小、stepでスライダーの1あたりの変化幅を定義できます。

gr.Slider(minimum=1, maximum=10, step=1)

image.png

Number

スライダーと似たような用途として、Numberを紹介します。Sliderと同じくmaximum, minimum, stepが利用できます。label, infoは ry)

gr.Number(minimum=1, maximum=10, step=1)

image.png

HTML, Markdown

gradio に文章を埋め込む際に、それぞれ HTML 形式、markdown 形式の文章を埋め込むことができます。

gr.Markdown("## 名前を入力して挨拶しよう!")

上記の場合、## 部分が markdown 形式として認識され、見出しとして表示されます。

File

ファイル添付をする領域を作成できます。MultimodalTextbox と同じように、file_typesfile_countを設定することができます。

gr.File()

image.png

Radio

ラジオボタンを実装できます。choicesで選択肢を設定します。

gr.Radio(choices=["hoge", "fuga"])

image.png

Audio, Video, Image

それぞれ、音声、動画、画像を表示することができます。画像はAnnotatedImage, ImageEditorのような派生クラスがあり、それぞれ「注釈付き画像」「画像の編集機能」が可能なようです。ImageMaskというものもあるようですが、それについては公式に記載がなく、あまりよく分かっていません。

gr.ImageEditor()
gr.ImageMask()

image.png

image.png

ここに貼り付けた例は上からImageEditor, ImageMask です。

これらのコンポーネントをまとめたいときは?

表形式、JSON形式を画面上に埋め込みたい場合など、紹介したいコンポーネントは色々あります。コンポーネントを全て紹介するときりが無いので、この辺りで割愛とさせていただきます。

では、これらのコンポーネントを並べたり、一つにまとめたい場合、どうすればいいでしょうか?その回答がRowColumn, Accordionなどのブロックレイアウトです。

Accordion

アコーディオンメニューを実装したい場合はこれを使います。openの引数を使うことで初期状態を設定できます。

with gr.Accordion(label="hoge"):
    gr.Markdown("## 名前を入力して挨拶しよう!")
    gr.Button("挨拶する")

上記のように実装することで、このようなアコーディオンメニューが簡単に作れますね!

image.png

右上の ▼ ボタンでアコーディオンを閉じたり開いたりできます。

Row, Column

コンポーネントを横(縦)に並べて配置したい場合は、Row(Column)を使用します。Accordionと同じように、with句を使用します。それぞれの例を下記に記載しておきます。

with gr.Row():
    gr.Markdown("## 名前を入力して挨拶しよう!")
    name = gr.Textbox()
    greet_btn = gr.Button("挨拶する")

image.png

with gr.Column():
    gr.Markdown("## 名前を入力して挨拶しよう!")
    name = gr.Textbox()
    greet_btn = gr.Button("挨拶する")

image.png

これらのサンプルを見てお気づきかもしれませんが、デフォルトの設定では全ての幅が同じになっています。今回の例では、Markdown, Textbox, Buttonは全て同じ幅になっていますね。これらの幅を設定するためにはscaleという引数を使用します。

with gr.Row():
    with gr.Column(scale=1):
        gr.Markdown("## 名前を入力して挨拶しよう!")
    with gr.Column(scale=3):
        name = gr.Textbox()
    with gr.Column(scale=2):
        greet_btn = gr.Button("挨拶する")

上記のように実装すれば、

image.png

画像のように、各コンポーネント幅がscaleに応じて設定されていることが分かります。

Group

先ほど、各コンポーネントの幅をwith gr.Column(scale=1):のように指定しましたが、Groupを使うことも可能です。

Groupはコンポーネントを一つにまとめる効果があります。

with gr.Group():
    gr.Markdown("## 名前を入力して挨拶しよう!")
    name = gr.Textbox()
    greet_btn = gr.Button("挨拶する")

上記のように設定すると、

image.png

Markdown, Textbox, Buttonが一つのグループとして表示されます。

Tab

ブロックレイアウトで最後に紹介するのは、Tabです。その名の通り、タブを設定できます。label引数を使うことで、タブに表示する名称を記載することができます。

with gr.Tab(label="出会いの挨拶"):
    gr.Markdown("## 名前を入力して挨拶しよう!")
    name = gr.Textbox()
    greet_btn = gr.Button("挨拶する")
with gr.Tab(label="別れの挨拶"):
    gr.Markdown("## 名前を入力して挨拶しよう!")
    name = gr.Textbox()
    greet_btn = gr.Button("挨拶する")

image.png

ユーザ操作を保存するには…?

ここでブロックレイアウトからコンポーネントに話を戻します。Web アプリとして当たり前のことですが、ユーザの操作が他のユーザに漏れ出てしまうことがあってはいけません。

例えば、AさんがFileで定義されたコンポーネントにaaa.txtを添付したとして、それが別の利用者Bさんが同じWebサービスを開いたときに添付されていたら困りますよね?ダウンロードされてしまうと、簡単に情報が漏れ出てしまいます。

それを防ぐために gradio では State, BrowserStateが用意されています。

State

公式では「フォームでよく使用されるコンポーネント(例:テキストボックス、ドロップダウン)の基本クラスです。」と記載されています。しかし、ただの基本クラスではなく、ユーザ操作の一時保存が可能です。「元に戻す」などを実装したい場合に利用できます。下記に簡単なサンプルを作ってみました。

state = gr.State("")
gr.Markdown("## 名前を入力して挨拶しよう!")
name = gr.Textbox()
greet_btn = gr.Button("挨拶する")
reset_btn = gr.Button("呼び戻す")
output = gr.Textbox(label="メッセージ")

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

greet_btn.click(fn=greet, inputs=name, outputs=[output,state])
reset_btn.click(fn=lambda x: x, inputs=state, outputs=name)

細かい実装は省略して、stateというのが用意されていることが分かります。

image.png

画像の通り、stateは画面上にはどこにも表示されていません。

image.png

今、「挨拶する」ボタンを押したので、stateには「やまだたろう」が保存されています。

image.png

「たなかはなこ」を入力した上で「呼び戻す」ボタンを押すと…。

image.png

この通り、stateに保存されている「やまだたろう」さんが戻ってきました!

確かにStateは便利なのですが、リロードをするとStateの情報が消えてしまう という弱点があります。それを解決できるのがBrowserStateです。今回はこれ以上詳しく解説しませんが、一時的に保存したいのであればState、リロードしても保存したいのであればBrowserStateで、基本的な使い方は同じです。筆者は前に設定した内容をリロードの度にいちいち設定し直すのが大変なときにBrowserStateを使うことがありましたので、合わせて紹介しておきました。

イベントリスナー

ここまでコンポーネントやブロックについて説明していきました。しかし、これだけでは Web 画面の構成を決めることしかできません。gradio では、ボタンを押すなどのイベントリスナーを実装することができます。ただし、gradio のイベントリスナーの実装は少し癖のあるものになっていますので、その実装方法について説明していきます。

name = gr.Textbox()
greet_btn = gr.Button("挨拶する")
output = gr.Textbox(label="メッセージ")

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

greet_btn.click(fn=greet, inputs=name, outputs=output)

上記の例では、greet_btnのボタンを押したときのイベントリスナーをgreet関数で定義しています。

fn

イベント処理時に呼び出される関数を表しています。

inputs

イベント処理に渡す関数の引数を表します。複数渡す場合は list にする必要があります。次に説明するoutputと合わせて注意しないといけないのは、ここで設定する値は gradio のコンポーネントである必要がある という点です。

name = "やまだたろう"
(中略)
greet_btn.click(fn=greet, inputs=name, outputs=output)

これでは、inputsに設定している値が文字列なので、エラーが出力されます。ちなみにfnに渡す引数は関数であればいいので、functoolsを用いて

name = "やまだたろう"
(中略)
greet_btn.click(
    fn=functools.partial(greet, name=name),
    inputs=None,
    outputs=output
)

のようにしてあげれば、文字列であってもfnに設定することが可能です。その他、簡単な処理であれば Lambda 式を使うことも可能です。

greet_btn.click(
    fn=lambda x: f"こんにちは、{x}さん!",
    inputs=name,
    outputs=output
)

複数の引数を設定したい場合は、リスト形式で設定します。

a = gr.Number()
b = gr.Number()
(中略)
btn.click(
    fn=lambda x, y: x+y,
    inputs=[a, b],
    outputs=output
)

show_api

API の公開/非公開を設定することができます。gradio では、「APIを介して使用」というボタンが用意されており、これをクリックすることで API を確認することができます。

image.png

image.png

False に設定することで非表示にすることができます。

queue

キューを設定することができます。これによって、ボタン押下などのイベント処理がキューに保存され、順番に処理できるようになります。例えば、複数人が使う Web サービスでイベント処理に大きな負荷がかかる場合に使ったりします。

cancels

例えば少しずつ文字列を表示していくような Chat システムを作りたいとして、途中でイベント処理を止めたいということもあるかと思います。その場合、cancelsという引数が有効です。

cancelsには停止したいイベントリスナーを記載します。例えば下記のように、click イベントに変数名を付けて、リストに設定してあげます。なお、リストで設定できるように、複数のイベントをまとめて設定することが可能です。

submit_btn = gr.Button("処理実行")
stop_btn = gr.Button("処理停止")
msg_box = gr.Textbox("結果を表示")

def hoge():
    # (時間のかかる処理)
    yield message

event = submit_btn.click(fn=hoge, inputs=None, outputs=msg_box)
stop_btn.click(fn=None, calcels=[event])

イベントリスナー、ちょっとした応用編

これまで、ボタン押下でTextboxの文字列を更新する例を見てきましたが、「選択する値によって非表示にしたい」など、文字列を入れること以外のイベント処理を行いたい場合があると思います。その場合はgr.updateを使うことで解決できます。

name = gr.Textbox()
greet_btn = gr.Button("挨拶する")
output = gr.Textbox(label="メッセージ")

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

greet_btn.click(fn=greet, inputs=name, outputs=output)

今回はdisplay_btnを押すとname = gr.Textbox()が非表示になる例を考えてみます。

state = gr.State(True)
name = gr.Textbox()
display_btn = gr.Button("表示を切り替える")
(中略)
display_btn.click(fn=display_btn_click, inputs=[state], outputs=[name, state])

まずは同じようにclickイベントを定義します。stateが引数、戻り値に入っていますが、これは今のTextboxの表示状態を表しています。そして、関数display_btn_clickの戻り値でupdateを使用します。

def display_btn_click(state):
    return gr.update(visible=not state), not state

これまで紹介していませんでしたがコンポーネントの表示/非表示にはvisibleを使用します。そして、この引数をupdateで渡すことによって、表示/非表示が切り替わります。

image.png

「表示を切り替える」ボタンを押すことで、Textbox が消えることが分かります。

image.png

その他、interactiveを用いると Textbox に入力不可にできたりもするので、活用してみてください。

イベント処理の色んな書き方

gradio では、デコレータを用いた書き方もサポートされています。

これまでの書き方

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

greet_btn.click(fn=greet, inputs=name, outputs=output)

デコレータを使った書き方

@greet_btn.click(inputs=name, outputs=output)
def greet(name):
    return f"こんにちは、{name}さん!"

デコレータで書く場合も同じように引数を設定できるので、どちらを使うかはお好みで。

イベントそのものの種類について

次に、イベントの種類を紹介していきます。ここまでclickを例に紹介していきましたが、その他にもいくつか用意されております。コンポーネントによっては用意されていないイベントもありますので、どのコンポーネントにどのイベントが用意されているのかは公式をご確認ください。

load, unload

Web 画面を開いた(閉じた)ときに処理をしたい場合にこのイベントが役に立ちます。例えば画面遷移した瞬間に DB から必要な値を取得したい場合、loadが利用できます。

with gr.Blocks() as demo:
    output = gr.Textbox()

    def get_hoge():
        # (DBから値を取ってくるような処理)
        return result

    demo.load(fn=get_hoge, inputs=None, outputs=output)

focus, blur

Textbox などで、フォーカスされた(フォーカスが外れた)ときにイベントを実行したい場合、focusblurが便利です。

change, input

Textbox などで、値が変更されたときにイベントを実行したい場合、change, inputが便利です。これらはSliderRadio, Dropdownなどでも用意されているので、よく使われます。が、筆者はあまり違いが分かっておらず、画像の通り(画像では分かりにくいかもしれませんが)同じようにイベント処理が実行されてしまいます…。

def on_input(text):
    return f"inputイベント: {text}"

def on_change(text):
    return f"changeイベント: {text}"

textbox = gr.Textbox(label="ここに入力してみてね")
out1 = gr.Textbox(label="リアルタイム反応")
out2 = gr.Textbox(label="確定後反応")

textbox.input(on_input, inputs=textbox, outputs=out1)
textbox.change(on_change, inputs=textbox, outputs=out2)

image.png

(ご存じの方がおられましたらコメントいただければ幸いです…。)

イベント処理、ちょっとした応用編②

最後に紹介するのは、イベントリスナーのつなげ方です。Aという処理をしてからBという処理をしたいときはthen, successでつなげることによって実現できます。

name = gr.Textbox()
greet_btn = gr.Button("挨拶する")
output = gr.Textbox(label="メッセージ")

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

greet_btn.click(fn=greet, inputs=name, outputs=output)

例えば、greet 関数を実行した後、更に何かしらの処理をしたい場合、下記のようにして実装します。

greet_btn.click(
    fn=greet, inputs=name, outputs=output
).then(
    fn=hoge, ()  
)

引数も他のイベントリスナーと同様、fn, inputs, outputs等用意されておりますので、これまでのイベントリスナーと同じように利用できます。

なお、thensuccessの使い分けですが、thenはイベント関数の成否に関わらず処理されますが、successはイベント関数が成功した場合のみ呼び出されます。処理が失敗した時に後続のイベント処理をしたくない場合にはsuccessを使用してください。

ただし、gradio のイベント処理の成否は Exception が raise されたかどうかで判定するため、successの使いどころは少し難しいかもしれません。エラーハンドリングの難しさについてはこちらの記事をご参照ください。

まとめ

ここまで gradio の様々な機能について紹介していきました。始めのほうで述べた通り、サクッと Web アプリを作って試したいときに gradio は有効な手段の一つになるかと思います。公式を見ればわかる部分も多いかと思いますが、イベント処理の書き方に癖を感じる部分が多かったので、自分の知識習得を兼ねて今回記事にしてみました。gradio の書き方にお困りの方の一助になれば幸いです。

また、これ以外にも様々なコンポーネント、イベント処理が用意されているので興味があれば公式ホームページを参照ください。

gradio の今後

最近生成 AI 界隈で流行?を見せている MCPgradio で用意されており、今も進化を見せております。リアルタイムな音声対話を実現できる FastRTC に gradio コンポーネントが用意されているので、これらの記事もいつか書いてみたいですね。

ここまでお読みいただきありがとうございます!よき gradio ライフを!

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?