【初心者向け】Hugging Face Spaces 簡単無料WEBツール・ゲーム制作 -Spaceを作成し公開する-

Hugging Face Spaceの使い方・無料で利用可能な、ウェブアプリ・ゲーム公開の仕方をGradioを用いて作ったアプリを例に紹介。
Hugging FaceとGradio開発環境を利用してWebアプリをデプロイする方法について紹介する。

Hugging Face Spacesとは?

もともとは、機械学習やAIなどのデモをweb上で試せるツールですが、UIのフレームワークであるGradioなどを利用することができるため、これだけで、web上で動くツールを作ることができます。

今回の記事では、Hugging Face Spacesの使い方について初心者向けに紹介し、この記事を読めば、ご自身で自作アプリが作れるようになると思います。(プログラミングはGPTなどに手伝ってもらうこともできるので)

Hugging Face Spacesはリンクを送れば、どこからでも動かすことができるので、ちょっとしたツールや共有したい教材などを作り配布するなど、いろんなことに使えてとても便利です。記事内では、参考として、九九の練習アプリを作っています。

今回の記事のサンプル “九九練習アプリ”

サンプル九九アプリ

サンプル九九アプリ

今回の記事でサンプルとして作成するアプリです

huggingface.co

今回の記事は、以下の公式ページを参考に作成しています。

Spaces Overview 参考にした公式ページ(English)

Spaces Overview 参考にした公式ページ(English)

Hugging Face Spaceのリファレンスページ

huggingface.co

スペースでwebツールを作る手順

0. Hugging Face アカウント作成

Webから”Hugging Face”と検索しアカウントを作成してください。

1. Create a new Space (新しくスペースを作る)

Hugging Face にログインし、ユーザページを開く。ユーザページのユーザアイコンをクリックすると出てくるメニューから”New Space”をクリックすることでSpaceを新規作成できます。

Hugging Face Spaceの新規作成方法を示した画像。画像では、ユーザページからSpaceを作成する方法についてわかりやすく提示している。

画像 Spaceの新規作成はここから

2. Spaceの基本設定

 ”New Space”を押すと以下のような画面が表示されるので、新しく作るスペース(プロジェクト名)と短い説明などを記入し、”環境の設定(SDK)”を行います。

 環境の設定(SDK)については、詳しく後ほど説明しますので、ひとまず、Space名と説明及びライセンスを記入しましょう。

Hugging Face Spaceの作成ページのスクリーンショット。
入力項目の説明
項目名何を書けばいい?
Space nameスペースの名前、半角英数字及び、”-” と “_”が使えます。自分や配布先の人がわかるような名前がよいです。
Short descriptionこのスペースが何なのかの説明。
Licenseスペースのライセンス(プログラムの公開や商用利用などの規約)を設定。
よくわからなければ “mit”が無難なので、mitにしておく。

MITライセンスとは?

MITライセンスは「寛容な(Permissive)ライセンス」の代表格です。

  • ほぼ無制限の自由: ソースコードを利用、改変、再配布、商用利用することを、ほぼ誰にでも許可します。
  • 最低限の義務: 利用者が守るべきことは、「著作権表示(C)とライセンス条文(のコピー)を、ソフトウェアのコピーに含めること」だけです。
  • 無保証: 「このソフトを使って何か問題が起きても作者は責任を負いません」と明記されています。
Hugging Face Spaceで新規スペースを作るときの記入の一例。

Spaceの設定記入例 (ライセンスのところまで)

3. 開発環境(SDK)の選択

 開発環境とは、プログラムを動かす前提となるベース(基盤)となるもので、ツールや公開までの環境一式をまとめているものを”SDK(ソフトウェア開発キット)”と言います。

Hugging Face Spacesでは、今回の記事で利用する Gradioに加えて、Dockerコンテナと静的ウェブページ(HTML)がサポートされており、便利なテンプレートもいくつか提供されています。

Webツールだけを作る場合は、以下のような設定をするとよいです。

Hugging Face Spaceの環境設定について設定例を示した画像。

画像 環境設定例

※GPUを使えるようにしたりより性能のいいものを使う場合は有料(PRO版のサブスク)になるみたいです。

4.スペース作成完了

Hugging Face Spaceを新規で作成したときに表示される初期設定方法を手順立てて説明しているページ

画像 Create Spaceするとスペースの作成完了

環境設定できたら、下の方にある”Create Space”ボタンを押すことでスペースを作成できます。
正常に作成できたら上の画像の様なページが表示され、GITHUBとの連携手順を示してくれます。

GITHUBと連携の仕方

Githubは、ファイルやプログラムを共有したり、共同で編集したりすることができるツールです。
Hugging Face Spacesで公開するプログラムをそのままアップロードすることもできますが、自身のPCで作成したり、調整を行い。これで公開してもいいなと思ったら、Githubを介してアップロードするという手順で開発をするとバグや不具合の対応が簡単です。

Githubのアカウント作成とVSCodeの準備

※以下の手順はGithubのアカウントとVSCode環境があるものとして紹介していきますので、まだアカウントを持っていないという人は、Githubアカウント作成とリポジトリ(共有するプログラムや公開設定ができるプロジェクト)の方法を説明した記事を参考にアカウント作成してください。

1.作業用フォルダを作る

 管理をしやすくするため、私は、以下のようにWorkspaceフォルダを作ってその中にProject_~~というフォルダ構成で開発をすることが多いです。(windows及びubuntuなど関係なく)

これは、一例なので、使いやすいように、自身の作業環境に合わせて作ってください。

混乱しないワークディレクトリの構成例。

2.gitと連携する。

フォルダ作成できたら、VSCodeでプロジェクト用のフォルダを開きます。

(い) VSCodeで開き、フォルダを開く。

VScodeでフォルダを開く方法について、操作した例を画像で表示している。

先ほど作成したフォルダを開く。

VSCODEの起動画面

画像 VSCode作業画面

(ろ) VSCodeのターミナルを開き、Hugging Face Spacesの提示してくれたコードを実行

VSCodeのツールバーからterminalを開く。

VSCODEでTerminalを開く方法を示したが画像

“New Terminal”を押すと、初期設定のままなら下のドッキングパネルにTerminalが開きます。ここにコマンドをコピペしていきます。

VSCodeのターミナル画像。

VSCodeのターミナル
(VSCode内用のターミナルなので、windowsのパワーシェルなどとは若干異なるので注意)

gitと連携するための連携コード

一番上の git clone ~~~ と書いているコマンドをコピーしてVSCodeのターミナルにペーストし実行します。

Hugging Face Spacesのリポジトリをローカル環境に複製(クローン)するための「git clone」コマンドを示すスクリーンショット。コマンドをコピーするボタンも表示されている。

Terminalで実行すると、この記事のはじめの方で指定したスペース名と同じフォルダがダウンロードされます。
ここに、自身のアプリなどを作っていき、作成後アップロードコマンドを実行することでWeb上に公開できます。

3.app.pyを作成する。

ここまでで、開発準備が完了したので、アプリ本体を作っていきます。

app.pyというファイルを作成し、その中にプログラムをPythonプログラムを記述、デバッグを行いテストします。

gradioを使うので、以下のコードをTerminalで実行し、使えるようにします。

pip install gradio

今回の記事はPythonのプログラミング講座ではないので、プログラミングについては割愛しますが、以下のようなプログラムをサンプルとして置いておきますので、試してみたい場合は、app.pyというファイルを作りそこにコピペしてみてください。

サンプル 99ソフト

import gradio as gr
import random

# 1. 九九の読み仮名データ (辞書)
KUKU_YOMI = {
    1: {1: "いんいちが いち", 2: "いんにが に", 3: "いんさんが さん", 4: "いんしが し", 5: "いんごが ご", 6: "いんろくが ろく", 7: "いんしちが しち", 8: "いんぱちが はち", 9: "いんくが く"},
    2: {1: "にいちが に", 2: "ににんが し", 3: "にさんが ろく", 4: "にしが はち", 5: "にご じゅう", 6: "にろく じゅうに", 7: "にしち じゅうし", 8: "にはち じゅうろく", 9: "にく じゅうはち"},
    3: {1: "さんいちが さん", 2: "さんにが ろく", 3: "さざんが く", 4: "さんし じゅうに", 5: "さんご じゅうご", 6: "さぶろく じゅうはち", 7: "さんしち にじゅういち", 8: "さんぱ にじゅうし", 9: "さんく にじゅうしち"},
    4: {1: "しいちが し", 2: "しにが はち", 3: "しさん じゅうに", 4: "しし じゅうろく", 5: "しご にじゅう", 6: "しろく にじゅうし", 7: "ししち にじゅうはち", 8: "しは さんじゅうに", 9: "しく さんじゅうろく"},
    5: {1: "ごいちが ご", 2: "ごに じゅう", 3: "ごさん じゅうご", 4: "ごし にじゅう", 5: "ごご にじゅうご", 6: "ごろく さんじゅう", 7: "ごしち さんじゅうご", 8: "ごは しじゅう", 9: "ごっく しじゅうご"},
    6: {1: "ろくいちが ろく", 2: "ろくに じゅうに", 3: "ろくさん じゅうはち", 4: "ろくし にじゅうし", 5: "ろくご さんじゅう", 6: "ろくろく さんじゅうろく", 7: "ろくしち しじゅうに", 8: "ろくは しじゅうはち", 9: "ろっく ごじゅうし"},
    7: {1: "しちいちが しち", 2: "しちに じゅうし", 3: "しちさん にじゅういち", 4: "しちし にじゅうはち", 5: "しちご さんじゅうご", 6: "しちろく しじゅうに", 7: "しちしち しじゅうく", 8: "しちは ごじゅうろく", 9: "しちく ろくじゅうさん"},
    8: {1: "はちいちが はち", 2: "はちに じゅうろく", 3: "はちさん にじゅうし", 4: "はちし さんじゅうに", 5: "はちご しじゅう", 6: "はちろく しじゅうはち", 7: "はちしち ごじゅうろく", 8: "はっぱ ろくじゅうし", 9: "はっく しちじゅうに"},
    9: {1: "くいちが く", 2: "くに じゅうはち", 3: "くさん にじゅうしち", 4: "くし さんじゅうろく", 5: "くご しじゅうご", 6: "くろく ごじゅうし", 7: "くしち ろくじゅうさん", 8: "くは しちじゅうに", 9: "くく はちじゅういち"},
}


# 2. ロジック(Python関数)

def new_question(mode):
    """
    新しい問題を生成する。
    mode("ランダム", "1の段" など)に応じて出題内容を変える。
    """
    yomi_text = "" # 読み仮名(デフォルトは空)
    
    if mode == "ランダム":
        a = random.randint(1, 9)
        b = random.randint(1, 9)
    else:
        # "Xの段" から X を取り出す
        a = int(mode.split('の')[0]) 
        b = random.randint(1, 9)
        
        # 読み仮名データを取得 (例: "さざんが く")
        full_reading = KUKU_YOMI[a][b] 
        
        # 読み仮名を " " で分割し、解答部分を "??" に置き換える
        # rsplit(' ', 1) で「最後のスペース」だけで分割 (例: ['さざんが', 'く'])
        parts = full_reading.rsplit(' ', 1) 
        reading_prefix = parts[0]           # (例: "さざんが")
        
        yomi_text = f"### {reading_prefix} ??" # (例: "### さざんが ??")

    correct_answer = a * b
    question_text = f"## {a} x {b} は?"
    
    # [読み仮名, 問題文, 答え(Stateへ), 現在モード(Stateへ), 結果クリア, 入力欄クリア]
    # 戻り値は、outputsで指定したコンポーネントに順番に渡される
    return yomi_text, question_text, correct_answer, mode, "", None

def check_answer(user_answer, secret_answer):
    """
    答えを判定する
    """
    if user_answer is None:
        return "こたえをいれてね!"
        
    if int(user_answer) == secret_answer:
        return "## せいかい!すごい! "
    else:
        return f"## おしい... ほんとうは {secret_answer} でした"

# 3. GradioのUIを構築 (gr.Blocks)
with gr.Blocks(theme=gr.themes.Soft()) as demo:
    gr.Markdown("#  九九(くく) れんしゅうアプリ ")

    # 重要な裏方(State)
    secret = gr.State() # 答えを記憶
    current_mode_state = gr.State("ランダム") # 現在のモードを記憶

    # UIコンポーネント
    with gr.Row():
        mode_radio = gr.Radio(
            choices=["ランダム", "1の段", "2の段", "3の段", "4の段", "5の段", "6の段", "7の段", "8の段", "9の段"],
            value="ランダム",
            label="れんしゅうモードを えらんでね"
        )
    
    # 読み仮名表示エリア
    yomi_display = gr.Markdown(value="")
    
    # 問題文表示エリア
    question_display = gr.Markdown(value="...") 

    with gr.Row():
        user_input = gr.Number(label="こたえは?", step=1)

    with gr.Row():
        check_button = gr.Button("こたえあわせ", variant="primary")
        next_button = gr.Button("つぎのもんだい")

    # 判定結果表示エリア
    result_output = gr.Markdown()

    # 4. イベントと関数を接続
    # (このイベント接続も変更なし)

    # (A) ページ読み込み時
    demo.load(
        fn=new_question,
        inputs=[current_mode_state],
        outputs=[yomi_display, question_display, secret, current_mode_state, result_output, user_input]
    )

    # (B) モード選択(Radio)が変更された時
    mode_radio.change(
        fn=new_question,
        inputs=[mode_radio],
        outputs=[yomi_display, question_display, secret, current_mode_state, result_output, user_input]
    )

    # (C) "こたえあわせ"ボタンがクリックされた時
    check_button.click(
        fn=check_answer,
        inputs=[user_input, secret], 
        outputs=[result_output]     
    )

    # (D) "つぎのもんだい"ボタンがクリックされた時
    next_button.click(
        fn=new_question,
        inputs=[current_mode_state],
        outputs=[yomi_display, question_display, secret, current_mode_state, result_output, user_input]
    )

# アプリを起動
demo.launch()
VSCode(Visual Studio Code)を使ってGradioで作成した「九九練習アプリ」をローカル環境でデバッグしているスクリーンショット。ターミナルにはローカルURLが表示されている。
Hugging Face Spacesにデプロイする前に、VSCodeを使ってローカルPCでアプリの動作確認。

99練習アプリを自身のPCでテストしたときの実行画像

Gitに上げるディレクトリ

フォルダ構成は以下のように、スペースと同じ名前のフォルダの配下が全部アップロードされるので、ここに個人情報などがわかるような書き込みはしない。

Gradioを用いて作成し、Hugging Face Spaceにアップロードするフォルダ構成

フォルダ構成は画像に倣うこと。

Git コマンドを用いてアップロード

Terminalにスペースで提示してくれたコードを実行する。

Hugging Face SpacesとGitを連携する方法を示すスクリーンショット。app.pyをコミット・プッシュするためのGitコマンド例と、それをコピーするボタンが矢印で強調されている。
Hugging Face SpacesはGitとの連携も簡単。app.pyをプッシュするコマンドが自動で案内されます。

アップロード完了

git pushでアップロードすると自動的に、HuggingFaceSpaceがアプリを構築してくれます。これには軽いものなら数分程度重いものはそれなりに時間がかかるので、おとなしく待ちましょう。

今回は10秒くらいで構築できたみたいです。

Hugging Face Spaces上でデプロイが完了した自作の「九九練習アプリ」のスクリーンショット。Gradioで作成されており、「ランダム」や「1の段」から「9の段」までの練習モードが選択できる。
PythonとGradioだけで作成し、Hugging Face Spacesに公開した「九九練習アプリ」の完成画面。

公開完了すると、先ほど自身のPCで試したものと同じようにウェブページから作ったアプリを操作sるうことができるようになります。

ここまでで、スペースの構築からアプリのデプロイ(公開)まで完了しました。作ったアプリの共有は、アプリのアドレスをブラウザなどからコピーして渡すだけです。

Hugging Face Spacesで作成したGradioアプリの共有方法。アプリのアドレスを示したスクリーンショット。
Hugging Face Spacesで作成したGradioアプリの共有方法。アプリのアドレスを示したスクリーンショット。
完成したサンプル九九アプリ

完成したサンプル九九アプリ

今回の記事でサンプルとして作成するアプリです

huggingface.co

まとめ

 今回の記事では、Hugging Face Spaceをもちいて、無料でアプリを公開する手順について紹介しました。

例では九九アプリを作りましたが、データをうまく工夫すれば、

漢字練習などほかの練習アプリクイズアプリ

割引のいくらお得?計算アプリなど、

または、催し物などを少しIT化できると思います。

いろいろ試してみてはいかがでしょうか?

これまでにスペースで作ったアプリとその記事

ステガノグラフィ & データ↔画像変換ツール

ステガノグラフィ & データ↔画像変換ツール

文字↔画像の変換とLSB法を試せるwebページ(自作)

huggingface.co
ステガノグラフィの仕組みを表す概念図。一見普通の風景画像に、パズルのようにデータを隠す・埋め込む情報秘匿技術を視覚的に表現したイラスト。

【ステガノグラフィ入門】#4 サンプルソフト公開 ~スパイ映画だけの話じゃない!画像にメッセージを忍ばせる驚きの技術とは?~

[自由研究]ステガノグラフィを誰でも体験できるフリーウェブソフトを作成したので紹介します。

ここまで読んでいただきありがとうございます。

では、次の記事で。 lumenHero