🚅

【Gradio 入門】30 分で疑似 ChatGPT 作ってみた

2024/12/14に公開

■ はじめに

こんにちは。データシステム部 推薦基盤チームのかみけん(上國料)です。ZOZO では主に推薦システムの開発などをしています。
最近、推薦モデルの出力結果を定性評価するシステムを作りたいなぁと思っているのですが……フロントエンドの知識がほぼゼロで、「どうしよう?」となっちゃいました。

そこで目をつけたのが、最近話題の Gradio です。
実は使うのが初めてだったんですが、試してみたらなんと 30 分くらいでそれっぽいものが作れちゃいました。めちゃくちゃ簡単で驚きました… 😇

この記事では、Gradioを使う上での備忘録を兼ねて、その手順をまとめていきます。どなたかの参考になれば嬉しいです!

■ 概要

今回は、推薦モデルの定性評価システムに Gradio を活用するアイデアから、勉強がてら擬似的な ChatGPT (チャット機能と画像生成機能)を作成してみました。Gradio の簡単な設定と直感的なインターフェースのおかげで、初心者の自分でも手軽に動作するものを作れたので、その過程を共有します。

● デモ

チャット機能

画像生成機能

■ Gradio の魅力

https://www.gradio.app/

Gradio is the fastest way to demo your machine learning model with a friendly web interface so that anyone can use it, anywhere!

公式のドキュメントを引用しますが、簡単に機械学習モデルをデモできるインターフェースを提供してるライブラリです。

今回自分が Gradio を使って感じた「すげぇ…」ポイントは以下の通りです:

■ 疑似 ChatGPT を Gradio で作ってみた (in 30 min)

疑似 ChatGPT をつくる際に使用する言語モデルのライブラリは gpt4free です。
gpt4free は、無料で gpt-4 などの言語モデルにアクセスを提供しており、テキスト生成や、チャットボット作成、言語生成、翻訳などの多様な用途で利用可能です。
使い方は以下に記載されたコードかドキュメントを参考にしてください。

● 環境構築

今回は Workbench を使用します。Colab と同様に、セルに以下を打ち込んで実行したら環境構築終了です。

!pip install gradio pillow
!pip install -U g4f[all]

● ライブラリのインポートと初期化

次に、必要なライブラリをインポートし、GPTクライアントとセッション状態を初期化します。

import gradio as gr
import g4f
from g4f.client import Client
from PIL import Image, ImageFilter
import numpy as np

# GPTクライアントの初期化
client = Client()

# セッション状態の初期化
state = []

● チャット機能の実装

この関数では、チャットのメッセージを処理し、モデルからの応答を生成します。モデルは gpt-4o-mini を使用しています。
チャット履歴(state)をスタック方式で管理し、最新の 3 ペア( 6 エントリ)だけを保持する仕組みになっています。これにより、過去のメッセージが多すぎて処理が遅くなるのを防ぎます。

def chat_response(user_message):
    global state
        
    # チャット終了処理
    if user_message.lower() == "exit":
        state = []
        return [("システム", "チャットを終了しました。")]

    # 空メッセージ処理
    if not user_message.strip():
        return [("システム", "メッセージが空です。")]

    # ユーザーメッセージをスタックに追加
    state.append({"role": "user", "content": user_message})

    # スタックが最大容量を超えた場合、最古のメッセージを削除
    max_pairs = 3
    max_state_size = max_pairs * 2  # ユーザーとアシスタントで2エントリずつ
    if len(state) > max_state_size:
        state = state[-max_state_size:]

    try:
        # モデルからの応答生成
        response = client.chat.completions.create(
            model="gpt-4o-mini",
            messages=state,
        )
        gpt_message = response.choices[0].message.content
        
        # アシスタントの応答をスタックに追加
        state.append({"role": "assistant", "content": gpt_message})
        
        # 再度、スタックが最大容量を超えた場合、古めのメッセージを削除
        if len(state) > max_state_size:
            state = state[-max_state_size:]

        # 最新の 3 ペアを取得
        pairs = []
        for i in range(len(state)-2, -1, -2):
            if i+1 < len(state):
                pairs.insert(0, (state[i]["content"], state[i+1]["content"]))
                if len(pairs) == max_pairs:
                    break

        return pairs
    except Exception as e:
        # エラー処理
        state = []
        error_message = f"エラーが発生しました: {e}"
        return [("システム", error_message)]

● 画像生成機能の実装

ここでは、指定されたプロンプト(prompt)を基に画像を生成する機能を実装します。使用するモデルは dall-e-3 です。

def generate_image(prompt):
    """
    プロンプトに基づいて画像を生成します。
    """
    try:
        response = client.images.generate(
            model="dall-e-3",
            prompt=prompt,
            response_format="url"
        )
        image_url = response.data[0].url
        return image_url
    except Exception as e:
        return gr.Error(f"画像生成中にエラーが発生しました: {e}")

● Gradio インターフェースの構築

ここでは、Gradio を使ってチャット機能と画像生成機能を統合したユーザーインターフェースを構築します。gr.Blocks を利用してレイアウトを設計し、それぞれの機能を簡単に切り替えられるタブ形式で実装します。

with gr.Blocks() as demo:
    gr.Markdown("# 疑似 ChatGPT")

    with gr.Tab("チャット"):
        chatbot = gr.Chatbot(label="Chat Box")
        input = gr.Textbox(show_label=False, placeholder="メッセージを入力してね")
        input.submit(fn=chat_response, inputs=input, outputs=chatbot)
        input.submit(fn=lambda: "", inputs=None, outputs=input)

    with gr.Tab("画像生成"):
        prompt_input = gr.Textbox(label="プロンプト:", placeholder="例: クールなドラゴン")
        generate_button = gr.Button("画像生成")
        image_output = gr.Image(label="生成された画像")

        generate_button.click(
            fn=generate_image,
            inputs=[prompt_input],
            outputs=[image_output]
        )

● アプリケーションの起動

構築したインターフェースを起動するには以下のコードを使用します。
demo.launch() を実行すると、ローカルでサーバーが立ち上がり、アプリケーションをブラウザで利用可能です。

demo.launch(
    server_name="0.0.0.0",  # 任意のIPアドレスからアクセス可能
    server_port=8888,       # ポート番号
    share=True              # 共有URLを生成して外部アクセスを許可
)

■ まとめ

本ガイドでは、Gradio を使用して疑似 ChatGPT (チャット機能と画像生成機能)を実装しました。劇的に簡単でした。
最後に、Gradio を効果的に活用するためのポイントをまとめます。

● Appendix: Gradio 活用のポイント

  • gr.Blocksgr.Tabgr.Rowgr.Column を使えば、直感的でスッキリしたインターフェースが作れます。名前からして ML エンジニア向け感ありますよね。ちなみに、一つの関数だけで済ませたいなら、gr.Interface のほうが簡単です!
  • gr.Queue でリクエスト数を制限することも可能です。重い計算やサーバー負荷を伴うアプリケーションを構築する場合は試してみてください。
  • gr.State を使えば、ユーザーのセッション内で必要なデータを管理できます。これがあると、複雑な操作や状態をまたぐようなアプリケーションでも安心して動かせそうです。
株式会社ZOZO

Discussion