1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

json-rpc 事始め with ChatGPT

Last updated at Posted at 2025-09-20

MCP入門 〜面倒なことはAIエージェントにやらせよう〜 by からあげ を聞きながら
https://qiita.com/kaizen_nagoya/items/54b648c838fae8d57e38

を書いていてjson-rpcを知った

ChaatGPT

json-rpcをwikipedia以外の10の参考文献を示してご説明ください。

ChatGPT:

JSON-RPCは、リモートプロシージャコール(RPC)を実現するための軽量なプロトコルで、JSON形式でメッセージをやり取りします。以下に、Wikipedia以外の信頼性の高い10の参考文献を挙げ、それぞれの観点からJSON-RPCの概要を説明します。

  1. JSON-RPC 2.0 Specification https://chatgpt.com/c/68cdf734-12e0-832f-b810-2551e0accbdc#:~:text=JSON%2DRPC%202.0-,Specification
    公式仕様書であり、JSON-RPC 2.0のメッセージ構造、エラーハンドリング、バッチリクエストなどの詳細が記載されています。
  2. WebOb 1.8.7 Documentation https://chatgpt.com/c/68cdf734-12e0-832f-b810-2551e0accbdc#:~:text=2.%20WebOb%201.8.7-,Documentation
    PythonのWebフレームワークWebObを使用したJSON-RPCエンドポイントの実装例が示されています。実際のコードを通じて、JSON-RPCの利用方法を学べます。
  3. Wallarm: What is JSON-RPC? https://chatgpt.com/c/68cdf734-12e0-832f-b810-2551e0accbdc#:~:text=Wallarm:%20What%20is-,JSON,-%2DRPC
    JSON-RPCの基本的な概念、利点、通知機能や複数呼び出しの処理能力について解説しています。特にパフォーマンス面での利点が強調されています。
  4. DhiWise: What Is JSON-RPC? https://chatgpt.com/c/68cdf734-12e0-832f-b810-2551e0accbdc#:~:text=DhiWise:%20What%20Is%20JSON%2D-,RPC
    JSON-RPCの概要、実際の例、他のRPCプロトコルとの比較を通じて、開発者向けにJSON-RPCの理解を深める記事です。
  5. GoQuorum: JSON-RPC API Security https://chatgpt.com/c/68cdf734-12e0-832f-b810-2551e0accbdc#:~:text=JSON%2DRPC%20API-,Security
    GoQuorumクライアントにおけるJSON-RPC APIのセキュリティ対策について説明しています。セキュリティプラグインインターフェースを使用した保護方法が紹介されています。
  6. Stack Overflow: JSON-RPC 2.0 Standard Responses https://stackoverflow.com/questions/34912647/json-rpc-2-0-standard-responses?utm_source=chatgpt.com
    JSON-RPC 2.0の標準的なレスポンス形式、エラーハンドリング、エラーコードの使用方法についての議論が行われています。
  7. Traffic Server: JSON RPC Errors https://chatgpt.com/c/68cdf734-12e0-832f-b810-2551e0accbdc#:~:text=Server:%20JSON%20RPC-,Errors
    JSON-RPCのエラーコードとその説明がリスト形式で提供されています。エラーハンドリングの実装に役立つ情報です。
  8. A2A Protocol: What is JSON-RPC 2.0 https://chatgpt.com/c/68cdf734-12e0-832f-b810-2551e0accbdc#:~:text=8.%20A2A%20Protocol:-,What,-is%20JSON%2DRPC
    JSON-RPC 2.0の詳細な解説と実装のベストプラクティスが紹介されています。開発者向けに実用的な情報が提供されています。
  9. SR Linux: JSON-RPC Basics https://chatgpt.com/c/68cdf734-12e0-832f-b810-2551e0accbdc#:~:text=Linux:%20JSON%2DRPC-,Basics
    SR LinuxのJSON-RPCインターフェースを使用した基本的な管理タスクの実行方法が説明されています。curlユーティリティを通じての操作例が示されています。
  10. Medium: JSON-RPC: The Engine of Bitcoin and Fintech https://chatgpt.com/c/68cdf734-12e0-832f-b810-2551e0accbdc
    Bitcoinやフィンテック分野におけるJSON-RPCの役割とその重要性について解説しています。特にブロックチェーン技術との関連が強調されています。
    これらの参考文献を通じて、JSON-RPCの基本的な理解から実際の実装、セキュリティ対策、他のRPCプロトコルとの比較まで、幅広い情報を得ることができます。特に開発者やシステム設計者にとって、実践的な知識を深めるための有用なリソースとなるでしょう。

JSON-RPCの生成AI連携をご紹介ください。

ChatGPT:

JSON-RPCと生成AIの連携についてご説明します。ここでは、仕組み・実装例・活用事例を整理して解説します。

  1. JSON-RPCと生成AIの基本的な関係
    JSON-RPC:リモートプロシージャコールの軽量プロトコルで、クライアントがサーバーにメソッド呼び出し(method)、パラメータ(params)、ID(id)を送信し、結果(result)やエラー(error)を受け取ります。
    生成AI:例えばOpenAIのGPTシリーズなど。テキスト、画像、コードなどを生成可能。
    連携のポイント:
    クライアントがJSON-RPC経由で生成AIのメソッドを呼び出す。
    パラメータとしてプロンプトや生成条件をJSON形式で渡す。
    AIが生成した結果をJSON-RPCレスポンスで返す。
  2. 実装例(Python + JSON-RPC + GPT)
from jsonrpcserver import method, serve
import openai

openai.api_key = "YOUR_API_KEY"

@method
def generate_text(prompt: str, max_tokens: int = 50):
    """JSON-RPC経由でテキスト生成AIを呼び出す"""
    response = openai.ChatCompletion.create(
        model="gpt-5-mini",
        messages=[{"role": "user", "content": prompt}],
        max_tokens=max_tokens
    )
    return response.choices[0].message["content"]

if __name__ == "__main__":
    print("JSON-RPC AI Server running on localhost:5000")
    serve("localhost", 5000)
クライアントは以下のように呼び出せます
{
  "jsonrpc": "2.0",
  "method": "generate_text",
  "params": {"prompt": "明日の天気を教えて", "max_tokens": 30},
  "id": 1
}
レスポンス例
{
  "jsonrpc": "2.0",
  "result": "明日の東京の天気は晴れのち曇り、最高気温は25度です。",
  "id": 1
}
  1. 活用例
    チャットボット・FAQ生成
    Webアプリでユーザーの質問をJSON-RPC経由でAIに送信し、自動応答を返す。
    コード生成支援
    IDEや開発ツールがJSON-RPCでAIにコード補完を依頼。
    自然言語→SQL変換
    データベースクライアントがAIにSQL文生成を依頼し、JSON-RPCで返却。
    マルチモーダル生成
    画像生成AIと連携し、JSON-RPC経由でテキストプロンプトから画像URLを取得。
  2. メリット
    軽量:HTTPやWebSocketで簡単にやり取り可能。
    言語非依存:Python、JavaScript、Goなど複数言語でクライアント・サーバー実装が可能。
    非同期対応:複数の生成リクエストを同時に処理可能。
  3. 注意点
    APIキーや認証の管理:生成AIの利用には認証が必要。JSON-RPCだけではセキュリティ対策が不十分な場合がある。
    レスポンスサイズ:大規模な生成結果を送信する場合、バッチ処理や分割送信が有効。
    エラーハンドリング:生成AIの失敗やタイムアウトもJSON-RPCエラーとして扱う必要がある。
    もし希望であれば、**「JSON-RPC経由で画像生成AIと連携する完全サンプル」**も作成できます。
    作りますか?

はい。お願いします。

ChatGPT:

では、JSON-RPC経由で画像生成AI(例:OpenAIのDALL·EやStable Diffusion)と連携するサンプルを作成します。Pythonを使い、サーバー・クライアント構成で示します。

  1. サーバー側(JSON-RPC + 画像生成AI)
from jsonrpcserver import method, serve
import openai
import base64

openai.api_key = "YOUR_API_KEY"

@method
def generate_image(prompt: str, size: str = "512x512"):
    """
    JSON-RPC経由で画像生成AIを呼び出す
    Returns: Base64文字列で画像データを返す
    """
    response = openai.Image.create(
        prompt=prompt,
        n=1,
        size=size
    )
    image_url = response['data'][0]['url']

    # 画像URLを直接返す場合
    return {"prompt": prompt, "image_url": image_url}

if __name__ == "__main__":
    print("JSON-RPC Image AI Server running on localhost:5000")
    serve("localhost", 5000)
ポイント
openai.Image.create() で画像生成
レスポンスはURLでもBase64エンコードしたバイナリでも可能
2. クライアント側JSON-RPC呼び出し
import requests
import json

url = "http://localhost:5000/"

# JSON-RPCリクエスト
payload = {
    "jsonrpc": "2.0",
    "method": "generate_image",
    "params": {"prompt": "A futuristic city skyline at sunset", "size": "512x512"},
    "id": 1
}

response = requests.post(url, json=payload)
result = response.json()

print("Generated Image URL:", result['result']['image_url'])

'3. 応用例
Webアプリ統合
フロントエンドでJSON-RPC経由でAIにリクエストし、画像を直接表示。
チャットボット連携
ユーザーが入力した文章から画像生成し、チャット画面に返す。
バッチ生成
複数プロンプトを配列として送信、JSON-RPCのバッチリクエストでまとめて画像生成。
'4. 注意点
APIキーの管理:サーバー側に安全に保存し、直接クライアントに渡さない。
生成時間の考慮:大きな画像サイズは生成に時間がかかるため、非同期処理や進捗表示が推奨。
セキュリティ:JSON-RPCは認証なしでは誰でもアクセス可能。トークンやIP制限を導入する。
もし希望なら、次のステップとして 「生成された画像をBase64で直接JSON-RPCレスポンスとして返す完全版」 も作成できます。
作りますか?

はい。お願いします。

ChatGPT:

了解です。では、JSON-RPC経由で生成AIが作った画像を Base64エンコード して直接レスポンスとして返す完全版サンプルを作ります。Pythonでの実装例です。

  1. サーバー側(JSON-RPC + 画像生成AI + Base64)
from jsonrpcserver import method, serve
import openai
import requests
import base64
from io import BytesIO

openai.api_key = "YOUR_API_KEY"

@method
def generate_image_base64(prompt: str, size: str = "512x512"):
    """
    JSON-RPC経由で画像生成AIを呼び出し、
    生成画像をBase64文字列として返す
    """
    # 画像生成
    response = openai.Image.create(
        prompt=prompt,
        n=1,
        size=size
    )
    image_url = response['data'][0]['url']

    # 画像をダウンロード
    img_response = requests.get(image_url)
    img_bytes = BytesIO(img_response.content)

    # Base64エンコード
    img_b64 = base64.b64encode(img_bytes.getvalue()).decode('utf-8')

    return {
        "prompt": prompt,
        "size": size,
        "image_base64": img_b64
    }

if __name__ == "__main__":
    print("JSON-RPC Image AI Server (Base64) running on localhost:5000")
    serve("localhost", 5000)
2. クライアント側JSON-RPC呼び出し + Base64受信
import requests
import json
import base64

url = "http://localhost:5000/"

# JSON-RPCリクエスト
payload = {
    "jsonrpc": "2.0",
    "method": "generate_image_base64",
    "params": {"prompt": "A cyberpunk cityscape at night", "size": "512x512"},
    "id": 1
}

response = requests.post(url, json=payload)
result = response.json()

# Base64をデコードして画像として保存
img_b64 = result['result']['image_base64']
img_data = base64.b64decode(img_b64)

with open("generated_image.png", "wb") as f:
    f.write(img_data)

print("Image saved as generated_image.png")

'3. ポイント
Base64での返却
HTTPレスポンスでバイナリ画像を直接返すより簡単にJSON内に埋め込める。
サイズ調整
生成サイズが大きいとレスポンスが重くなるため注意(例:1024×1024はBase64サイズが大きくなる)。
非同期化の検討
大量生成や高解像度生成では非同期処理やキューを使うと安全。
このサンプル構成で、JSON-RPC経由で生成AIにリクエスト → Base64画像を受け取り → クライアントで保存まで完全に自動化できます。
希望であれば、Webブラウザ上でJSON-RPC経由でBase64画像を即時表示するHTML/JavaScriptサンプルも作れます。
作りますか?

はい。お願いします。

ChatGPT:

では、JSON-RPC経由で生成AIからBase64画像を受け取り、Webブラウザ上で即時表示するHTML + JavaScriptサンプルを作成します。

  1. 前提
    サーバー側は先ほど作った generate_image_base64 JSON-RPCメソッドが稼働中。
    ブラウザからHTTP POSTでJSON-RPCリクエストを送信して画像を取得します。
  2. HTML + JavaScriptサンプル
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>JSON-RPC 画像生成デモ</title>
<style>
  body { font-family: Arial, sans-serif; padding: 20px; }
  input, button { padding: 8px; margin: 5px 0; width: 100%; }
  img { max-width: 512px; margin-top: 20px; border: 1px solid #ccc; }
</style>
</head>
<body>
<h1>JSON-RPC 画像生成デモ</h1>

<input type="text" id="prompt" placeholder="画像生成プロンプトを入力">
<button id="generateBtn">生成</button>

<div>
  <h3>生成画像</h3>
  <img id="generatedImage" alt="生成画像">
</div>

<script>
document.getElementById("generateBtn").addEventListener("click", async () => {
    const prompt = document.getElementById("prompt").value;
    if (!prompt) {
        alert("プロンプトを入力してください");
        return;
    }

    const payload = {
        jsonrpc: "2.0",
        method: "generate_image_base64",
        params: { prompt: prompt, size: "512x512" },
        id: 1
    };

    try {
        const response = await fetch("http://localhost:5000/", {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify(payload)
        });
        const data = await response.json();
        const imgB64 = data.result.image_base64;
        const imgElement = document.getElementById("generatedImage");
        imgElement.src = "data:image/png;base64," + imgB64;
    } catch (err) {
        console.error(err);
        alert("画像生成に失敗しました");
    }
});
</script>
</body>
</html>

'3. ポイント
Base64を直接 に埋め込む
data:image/png;base64, + Base64文字列で表示可能
JSON-RPC呼び出し
fetchでHTTP POSTし、JSON-RPCリクエストを送信
非同期処理
async/await でサーバー応答を待って表示
クロスオリジン
ブラウザからローカルサーバーにアクセスする場合、サーバーで CORS許可 が必要(Flaskやjsonrpcserverでは cors オプションを追加)。
これで、ブラウザ上でプロンプトを入力 → JSON-RPC経由で生成AIにリクエスト → Base64画像を即座に表示、までのフローが実現できます。
希望であれば、CORS対応済みでサーバーも含めたフルワークフローのサンプルに改良できます。
作りますか?

はい。お願いします。

ChatGPT:

では、JSON-RPCサーバー側で CORS対応 し、ブラウザから直接アクセスできるフルワークフローサンプルを作成します。Python + jsonrpcserver + flask を使用します。

  1. サーバー側(CORS対応)
from flask import Flask, request, jsonify
from jsonrpcserver import method, dispatch
import openai
import requests
import base64
from io import BytesIO
from flask_cors import CORS  # CORS対応用

openai.api_key = "YOUR_API_KEY"

app = Flask(__name__)
CORS(app)  # すべてのオリジンからのアクセスを許可

@method
def generate_image_base64(prompt: str, size: str = "512x512"):
    """
    JSON-RPC経由で画像生成AIを呼び出し、
    生成画像をBase64文字列として返す
    """
    # 画像生成
    response = openai.Image.create(
        prompt=prompt,
        n=1,
        size=size
    )
    image_url = response['data'][0]['url']

    # 画像をダウンロード
    img_response = requests.get(image_url)
    img_bytes = BytesIO(img_response.content)

    # Base64エンコード
    img_b64 = base64.b64encode(img_bytes.getvalue()).decode('utf-8')

    return {
        "prompt": prompt,
        "size": size,
        "image_base64": img_b64
    }

@app.route("/", methods=["POST"])
def index():
    request_json = request.get_json()
    response = dispatch(request_json)
    return jsonify(response), 200

if __name__ == "__main__":
    print("JSON-RPC Image AI Server (CORS対応) running on http://localhost:5000")
    app.run(host="0.0.0.0", port=5000)
flask_cors.CORS を使用してブラウザからのアクセスを許可
JSON-RPCのリクエストは / エンドポイントにPOST
2. クライアント側ブラウザHTML + JavaScript
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>JSON-RPC 画像生成デモ (CORS対応)</title>
<style>
  body { font-family: Arial, sans-serif; padding: 20px; }
  input, button { padding: 8px; margin: 5px 0; width: 100%; }
  img { max-width: 512px; margin-top: 20px; border: 1px solid #ccc; }
</style>
</head>
<body>
<h1>JSON-RPC 画像生成デモ (CORS対応)</h1>

<input type="text" id="prompt" placeholder="画像生成プロンプトを入力">
<button id="generateBtn">生成</button>

<div>
  <h3>生成画像</h3>
  <img id="generatedImage" alt="生成画像">
</div>

<script>
document.getElementById("generateBtn").addEventListener("click", async () => {
    const prompt = document.getElementById("prompt").value;
    if (!prompt) {
        alert("プロンプトを入力してください");
        return;
    }

    const payload = {
        jsonrpc: "2.0",
        method: "generate_image_base64",
        params: { prompt: prompt, size: "512x512" },
        id: 1
    };

    try {
        const response = await fetch("http://localhost:5000/", {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify(payload)
        });
        const data = await response.json();
        const imgB64 = data.result.image_base64;
        document.getElementById("generatedImage").src = "data:image/png;base64," + imgB64;
    } catch (err) {
        console.error(err);
        alert("画像生成に失敗しました");
    }
});
</script>
</body>
</html>

'3. ポイント
CORS対応済み
ブラウザがローカルサーバーに直接アクセス可能
Base64画像埋め込み
に data:image/png;base64,... として直接表示
フルワークフロー
プロンプト入力 → JSON-RPC呼び出し → AI生成 → Base64返却 → ブラウザ表示
この構成で、ブラウザからJSON-RPCを通じて安全に生成AIと連携し、画像を即時表示できます。
希望であれば、複数プロンプトをバッチ生成して一括表示するサンプルにも拡張可能です。
作りますか?

はい。お願いします。

ChatGPT:

では、複数プロンプトをJSON-RPC経由でバッチ生成し、ブラウザ上に一括表示するサンプルを作成します。

  1. サーバー側(Flask + JSON-RPC + バッチ対応)
from flask import Flask, request, jsonify
from jsonrpcserver import method, dispatch
import openai
import requests
import base64
from io import BytesIO
from flask_cors import CORS

openai.api_key = "YOUR_API_KEY"

app = Flask(__name__)
CORS(app)

@method
def generate_images_base64(prompts: list, size: str = "512x512"):
    """
    JSON-RPCで複数プロンプトの画像を生成してBase64で返す
    prompts: ["プロンプト1", "プロンプト2", ...]
    """
    results = []
    for prompt in prompts:
        # 画像生成
        response = openai.Image.create(prompt=prompt, n=1, size=size)
        image_url = response['data'][0]['url']

        # 画像ダウンロード
        img_response = requests.get(image_url)
        img_bytes = BytesIO(img_response.content)
        img_b64 = base64.b64encode(img_bytes.getvalue()).decode('utf-8')

        results.append({"prompt": prompt, "size": size, "image_base64": img_b64})

    return results

@app.route("/", methods=["POST"])
def index():
    request_json = request.get_json()
    response = dispatch(request_json)
    return jsonify(response), 200

if __name__ == "__main__":
    print("JSON-RPC Batch Image AI Server running on http://localhost:5000")
    app.run(host="0.0.0.0", port=5000)

'2. クライアント側(ブラウザ HTML + JS)

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>JSON-RPC バッチ画像生成デモ</title>
<style>
  body { font-family: Arial, sans-serif; padding: 20px; }
  textarea, button { padding: 8px; margin: 5px 0; width: 100%; }
  img { max-width: 512px; margin: 10px 0; border: 1px solid #ccc; display:block; }
</style>
</head>
<body>
<h1>JSON-RPC バッチ画像生成デモ</h1>

<textarea id="prompts" rows="5" placeholder="各行に1つのプロンプトを入力"></textarea>
<button id="generateBtn">生成</button>

<div id="imagesContainer"></div>

<script>
document.getElementById("generateBtn").addEventListener("click", async () => {
    const promptsText = document.getElementById("prompts").value.trim();
    if (!promptsText) {
        alert("プロンプトを入力してください");
        return;
    }

    const prompts = promptsText.split("\n").map(p => p.trim()).filter(p => p);

    const payload = {
        jsonrpc: "2.0",
        method: "generate_images_base64",
        params: { prompts: prompts, size: "512x512" },
        id: 1
    };

    try {
        const response = await fetch("http://localhost:5000/", {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify(payload)
        });
        const data = await response.json();
        const imagesContainer = document.getElementById("imagesContainer");
        imagesContainer.innerHTML = "";

        data.result.forEach(item => {
            const img = document.createElement("img");
            img.src = "data:image/png;base64," + item.image_base64;
            img.alt = item.prompt;
            imagesContainer.appendChild(img);
        });

    } catch (err) {
        console.error(err);
        alert("画像生成に失敗しました");
    }
});
</script>
</body>
</html>

'3. ポイント
複数プロンプト対応
クライアントから prompts: ["prompt1", "prompt2", ...] を送信
サーバー側でループ処理してBase64画像を返却
ブラウザで一括表示

<div> 内に <img> 要素を動的に追加して表示

CORS対応済み
ブラウザから直接ローカルサーバーにアクセス可能
これで、ブラウザに複数プロンプトを入力 → JSON-RPCでAIにバッチ生成 → 生成画像を即時表示、というフルワークフローが完成します。
必要であれば、生成進捗をリアルタイムで表示する仕組みも追加可能です。
追加しますか?

はい。お願いします。

ChatGPT:

では、生成AIのバッチ処理で 進捗をリアルタイム表示 する仕組みを追加したサンプルを作成します。ブラウザでどの画像が生成済みか順次表示できるようにします。

  1. サーバー側(Flask + JSON-RPC + SSE対応)
    リアルタイム進捗を送るために Server-Sent Events (SSE) を使用します。バッチ生成中、生成済み画像を順次ブラウザに送信します。
from flask import Flask, request, Response, jsonify
from jsonrpcserver import method, dispatch
import openai
import requests
import base64
from io import BytesIO
from flask_cors import CORS
import time
import json

openai.api_key = "YOUR_API_KEY"

app = Flask(__name__)
CORS(app)

@method
def generate_images_base64(prompts: list, size: str = "512x512"):
    """
    バッチ画像生成。進捗はSSEで送る想定。
    JSON-RPCレスポンスとして最終結果を返す。
    """
    results = []
    for i, prompt in enumerate(prompts):
        # 画像生成
        response = openai.Image.create(prompt=prompt, n=1, size=size)
        image_url = response['data'][0]['url']

        # 画像ダウンロード
        img_response = requests.get(image_url)
        img_bytes = BytesIO(img_response.content)
        img_b64 = base64.b64encode(img_bytes.getvalue()).decode('utf-8')

        results.append({"prompt": prompt, "size": size, "image_base64": img_b64})
    return results

@app.route("/sse_generate", methods=["POST"])
def sse_generate():
    """
    SSEでリアルタイムに画像を送信するエンドポイント
    """
    data = request.get_json()
    prompts = data.get("prompts", [])
    size = data.get("size", "512x512")

    def event_stream():
        for prompt in prompts:
            # 画像生成
            response = openai.Image.create(prompt=prompt, n=1, size=size)
            image_url = response['data'][0]['url']

            img_response = requests.get(image_url)
            img_bytes = BytesIO(img_response.content)
            img_b64 = base64.b64encode(img_bytes.getvalue()).decode('utf-8')

            # SSE形式で送信
            yield f"data:{json.dumps({'prompt': prompt, 'image_base64': img_b64})}\n\n"
            time.sleep(0.5)  # デモ用に少し待機

    return Response(event_stream(), mimetype="text/event-stream")

@app.route("/", methods=["POST"])
def index():
    request_json = request.get_json()
    response = dispatch(request_json)
    return jsonify(response), 200

if __name__ == "__main__":
    print("JSON-RPC Batch Image AI Server (SSE対応) running on http://localhost:5000")
    app.run(host="0.0.0.0", port=5000)

'2. クライアント側(ブラウザ HTML + JS、SSE対応)

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>JSON-RPC バッチ画像生成デモ (リアルタイム進捗)</title>
<style>
  body { font-family: Arial, sans-serif; padding: 20px; }
  textarea, button { padding: 8px; margin: 5px 0; width: 100%; }
  img { max-width: 512px; margin: 10px 0; border: 1px solid #ccc; display:block; }
</style>
</head>
<body>
<h1>JSON-RPC バッチ画像生成デモ (リアルタイム進捗)</h1>

<textarea id="prompts" rows="5" placeholder="各行に1つのプロンプトを入力"></textarea>
<button id="generateBtn">生成</button>

<div id="imagesContainer"></div>

<script>
document.getElementById("generateBtn").addEventListener("click", () => {
    const promptsText = document.getElementById("prompts").value.trim();
    if (!promptsText) {
        alert("プロンプトを入力してください");
        return;
    }

    const prompts = promptsText.split("\n").map(p => p.trim()).filter(p => p);

    const imagesContainer = document.getElementById("imagesContainer");
    imagesContainer.innerHTML = "";

    // SSEで進捗取得
    const evtSource = new EventSourcePolyfill("http://localhost:5000/sse_generate", {
        method: "POST",
        body: JSON.stringify({ prompts: prompts, size: "512x512" }),
        headers: { "Content-Type": "application/json" }
    });

    evtSource.onmessage = function(event) {
        const data = JSON.parse(event.data);
        const img = document.createElement("img");
        img.src = "data:image/png;base64," + data.image_base64;
        img.alt = data.prompt;
        imagesContainer.appendChild(img);
    };

    evtSource.onerror = function(err) {
        console.error("SSEエラー", err);
        evtSource.close();
    };
});
</script>

<!-- EventSourcePolyfillはFetchメソッド対応のSSEポリフィル -->
<script src="https://unpkg.com/event-source-polyfill"></script>

</body>
</html>

'3. ポイント
Server-Sent Events (SSE)で進捗送信
各画像生成後にリアルタイムで送信
ブラウザで順次表示可能
非同期処理
大量生成でもユーザーが待機中の状況を把握可能
JSON-RPCと併用可能
バッチ生成の最終結果は従来のJSON-RPCで返すことも可能
この構成により、複数プロンプトの生成中もブラウザ上で 順次画像が表示されるリアルタイムUI が実現できます。
必要であれば、進捗バー付きで生成状況を可視化するUI も追加可能です。追加しますか?

はい。お願いします。

ChatGPT:

では、生成AIのバッチ画像生成で 進捗バー付きUI をブラウザに追加したサンプルを作ります。
リアルタイムに何枚生成済みか可視化できます。

  1. サーバー側(Flask + SSE)
    サーバーは前回とほぼ同じでOKです。進捗バーはクライアント側で管理するため、サーバー側はSSEで画像ごとに送信するだけです。
from flask import Flask, request, Response
import openai
import requests
import base64
from io import BytesIO
from flask_cors import CORS
import time
import json

openai.api_key = "YOUR_API_KEY"

app = Flask(__name__)
CORS(app)

@app.route("/sse_generate", methods=["POST"])
def sse_generate():
    data = request.get_json()
    prompts = data.get("prompts", [])
    size = data.get("size", "512x512")

    def event_stream():
        total = len(prompts)
        for i, prompt in enumerate(prompts, start=1):
            # 画像生成
            response = openai.Image.create(prompt=prompt, n=1, size=size)
            image_url = response['data'][0]['url']

            img_response = requests.get(image_url)
            img_bytes = BytesIO(img_response.content)
            img_b64 = base64.b64encode(img_bytes.getvalue()).decode('utf-8')

            # SSE形式で送信(画像 + 進捗情報)
            yield f"data:{json.dumps({'prompt': prompt, 'image_base64': img_b64, 'progress': i, 'total': total})}\n\n"
            time.sleep(0.5)  # デモ用

    return Response(event_stream(), mimetype="text/event-stream")

if __name__ == "__main__":
    print("JSON-RPC Batch Image AI Server (SSE + 進捗バー対応) running on http://localhost:5000")
    app.run(host="0.0.0.0", port=5000)

'2. クライアント側(HTML + JS + 進捗バー)

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>JSON-RPC バッチ画像生成デモ (進捗バー付き)</title>
<style>
  body { font-family: Arial, sans-serif; padding: 20px; }
  textarea, button { padding: 8px; margin: 5px 0; width: 100%; }
  img { max-width: 512px; margin: 10px 0; border: 1px solid #ccc; display:block; }
  #progressBarContainer { width: 100%; background: #eee; height: 20px; border-radius: 5px; margin-top: 10px; }
  #progressBar { height: 100%; width: 0%; background: #4caf50; border-radius: 5px; text-align:center; color:white; line-height:20px; }
</style>
</head>
<body>
<h1>JSON-RPC バッチ画像生成デモ (進捗バー付き)</h1>

<textarea id="prompts" rows="5" placeholder="各行に1つのプロンプトを入力"></textarea>
<button id="generateBtn">生成</button>

<div id="progressBarContainer">
  <div id="progressBar">0%</div>
</div>

<div id="imagesContainer"></div>

<script src="https://unpkg.com/event-source-polyfill"></script>
<script>
document.getElementById("generateBtn").addEventListener("click", () => {
    const promptsText = document.getElementById("prompts").value.trim();
    if (!promptsText) {
        alert("プロンプトを入力してください");
        return;
    }

    const prompts = promptsText.split("\n").map(p => p.trim()).filter(p => p.length > 0);
    const imagesContainer = document.getElementById("imagesContainer");
    const progressBar = document.getElementById("progressBar");

    imagesContainer.innerHTML = "";
    progressBar.style.width = "0%";
    progressBar.textContent = "0%";

    const evtSource = new EventSourcePolyfill("http://localhost:5000/sse_generate", {
        method: "POST",
        body: JSON.stringify({ prompts: prompts, size: "512x512" }),
        headers: { "Content-Type": "application/json" }
    });

    evtSource.onmessage = function(event) {
        const data = JSON.parse(event.data);

        // 画像表示
        const img = document.createElement("img");
        img.src = "data:image/png;base64," + data.image_base64;
        img.alt = data.prompt;
        imagesContainer.appendChild(img);

        // 進捗バー更新
        const percent = Math.round((data.progress / data.total) * 100);
        progressBar.style.width = percent + "%";
        progressBar.textContent = percent + "%";

        // すべて生成完了でSSE終了
        if (data.progress === data.total) {
            evtSource.close();
        }
    };

    evtSource.onerror = function(err) {
        console.error("SSEエラー", err);
        evtSource.close();
    };
});
</script>
</body>
</html>

'3. ポイント
進捗バー表示
生成済み画像数 / 総画像数 でバーの幅とテキストを更新
リアルタイム表示
画像が生成されるたびに 要素を追加
SSE + Fetch併用
EventSourcePolyfillを使い、POSTリクエストでもSSEを利用可能
この構成で、ユーザーはプロンプトを入力 → 画像が順次表示される → 進捗バーで何枚生成済みか一目で把握、という 直感的でリアルタイムなバッチ画像生成UI が完成します。
さらに改良すると、並列生成やキャンセル機能も追加できます。
追加しますか?

はい。お願いします。

ChatGPT:

では、ブラウザからバッチ画像生成を 並列化 し、さらに途中で キャンセル できる仕組みを追加したサンプルを作ります。

  1. サーバー側(Flask + SSE、並列化対応)
    サーバー側は以前のSSEとほぼ同じですが、生成処理を スレッドプール で並列化して高速化します。
from flask import Flask, request, Response
import openai
import requests
import base64
from io import BytesIO
from flask_cors import CORS
import json
from concurrent.futures import ThreadPoolExecutor

openai.api_key = "YOUR_API_KEY"

app = Flask(__name__)
CORS(app)

executor = ThreadPoolExecutor(max_workers=4)  # 並列生成数

@app.route("/sse_generate_parallel", methods=["POST"])
def sse_generate_parallel():
    data = request.get_json()
    prompts = data.get("prompts", [])
    size = data.get("size", "512x512")

    def generate_image(prompt):
        response = openai.Image.create(prompt=prompt, n=1, size=size)
        image_url = response['data'][0]['url']
        img_response = requests.get(image_url)
        img_bytes = BytesIO(img_response.content)
        img_b64 = base64.b64encode(img_bytes.getvalue()).decode('utf-8')
        return {'prompt': prompt, 'image_base64': img_b64}

    def event_stream():
        futures = {executor.submit(generate_image, p): p for p in prompts}
        total = len(prompts)
        completed = 0
        for future in futures:
            result = future.result()
            completed += 1
            # SSE形式で送信
            yield f"data:{json.dumps({**result, 'progress': completed, 'total': total})}\n\n"

    return Response(event_stream(), mimetype="text/event-stream")

if __name__ == "__main__":
    print("JSON-RPC Batch Image AI Server (並列 + SSE + キャンセル対応) running on http://localhost:5000")
    app.run(host="0.0.0.0", port=5000)

ポイント
ThreadPoolExecutor を使用して複数プロンプトを並列生成
SSEで生成結果を順次送信
キャンセルはクライアント側から EventSource を閉じることで対応可能
2. クライアント側(HTML + JS + 進捗バー + キャンセル)

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>JSON-RPC バッチ画像生成デモ (並列 + キャンセル)</title>
<style>
 body { font-family: Arial, sans-serif; padding: 20px; }
 textarea, button { padding: 8px; margin: 5px 0; width: 100%; }
 img { max-width: 512px; margin: 10px 0; border: 1px solid #ccc; display:block; }
 #progressBarContainer { width: 100%; background: #eee; height: 20px; border-radius: 5px; margin-top: 10px; }
 #progressBar { height: 100%; width: 0%; background: #4caf50; border-radius: 5px; text-align:center; color:white; line-height:20px; }
</style>
</head>
<body>
<h1>JSON-RPC バッチ画像生成デモ (並列 + キャンセル)</h1>

<textarea id="prompts" rows="5" placeholder="各行に1つのプロンプトを入力"></textarea>
<button id="generateBtn">生成</button>
<button id="cancelBtn">キャンセル</button>

<div id="progressBarContainer">
 <div id="progressBar">0%</div>
</div>

<div id="imagesContainer"></div>

<script src="https://unpkg.com/event-source-polyfill"></script>
<script>
let evtSource = null;

document.getElementById("generateBtn").addEventListener("click", () => {
   const promptsText = document.getElementById("prompts").value.trim();
   if (!promptsText) { alert("プロンプトを入力してください"); return; }

   const prompts = promptsText.split("\n").map(p => p.trim()).filter(p => p.length > 0);
   const imagesContainer = document.getElementById("imagesContainer");
   const progressBar = document.getElementById("progressBar");

   imagesContainer.innerHTML = "";
   progressBar.style.width = "0%";
   progressBar.textContent = "0%";

   // 既存のEventSourceがあれば閉じる
   if (evtSource) evtSource.close();

   evtSource = new EventSourcePolyfill("http://localhost:5000/sse_generate_parallel", {
       method: "POST",
       body: JSON.stringify({ prompts: prompts, size: "512x512" }),
       headers: { "Content-Type": "application/json" }
   });

   evtSource.onmessage = function(event) {
       const data = JSON.parse(event.data);

       const img = document.createElement("img");
       img.src = "data:image/png;base64," + data.image_base64;
       img.alt = data.prompt;
       imagesContainer.appendChild(img);

       const percent = Math.round((data.progress / data.total) * 100);
       progressBar.style.width = percent + "%";
       progressBar.textContent = percent + "%";

       if (data.progress === data.total) {
           evtSource.close();
           evtSource = null;
       }
   };

   evtSource.onerror = function(err) {
       console.error("SSEエラー", err);
       evtSource.close();
       evtSource = null;
   };
});

document.getElementById("cancelBtn").addEventListener("click", () => {
   if (evtSource) {
       evtSource.close();
       evtSource = null;
       alert("生成をキャンセルしました");
   }
});
</script>
</body>
</html>

'3. 特徴
並列生成
サーバー側で複数プロンプトを同時に生成
従来より高速
進捗バー付き
生成済み枚数 / 総枚数でバーを更新
キャンセル可能
「キャンセル」ボタンで EventSource を閉じ、生成を中止
リアルタイム表示
画像生成完了順に順次ブラウザに表示
この構成で、ユーザーは複数プロンプトを 高速並列生成 + 進捗表示 + キャンセル機能 の組み合わせで管理できます。
希望であれば、さらに 生成優先度を付けて重要なプロンプトから先に生成 する機能も追加可能です。
追加しますか?

参照

ChatGPT利用の技4つ with ChatGPT
https://qiita.com/kaizen_nagoya/items/4a178bd6a09a4a471a7f

ChatGPTによるQiita記事の改良と補足
https://qiita.com/kaizen_nagoya/items/20604d6dd0702ab95c2f

ChatGPTによるQiita記事の改良と補足(2)
https://qiita.com/kaizen_nagoya/items/996275307ffc8c1243f8

本から始める 面倒なことはChatGPTにやらせよう by からあげ
https://qiita.com/kaizen_nagoya/items/f5ce2a18db54b5610e4b

MCP入門 〜面倒なことはAIエージェントにやらせよう〜 by からあげ を聞きながら
https://qiita.com/kaizen_nagoya/items/54b648c838fae8d57e38

【松尾研LLMコミュニティ】面倒なことはLLMにやらせよう "Beginning LLM"2024年10月17日 AI(9)
https://qiita.com/kaizen_nagoya/items/efdc23fbe67cdae2126e

設計:ChatGPTで特異解か一般解を求める AI(1)
https://qiita.com/kaizen_nagoya/items/4dec580e16a7c84b0ec4

みんなの使い方から学ぶ
https://qiita.com/kaizen_nagoya/items/8e7de492d896df94a36e

AI・機械学習 昨日、今日、明日
https://qiita.com/kaizen_nagoya/items/adb184c8fc7a65ac9756

DNA LLM and genome for survey 2200 papers by name.
https://qiita.com/kaizen_nagoya/items/ce8a28d6072f340a9d59

ChatGPTから学ぶ 3倍褒めて3分の1貶す
https://qiita.com/kaizen_nagoya/items/91e70fd8caa25076718b

AI時代の相棒は、キミに決めた! 推しのAIエージェントをシェアしよう!企画参加まとめへの序章
https://qiita.com/kaizen_nagoya/items/e3fd7557bac97d1b88f2

記事投稿数、いいね数の目標設定して ChatGPTに聞いてみた。
https://qiita.com/kaizen_nagoya/items/019e2ad9c3e45e45854e

AI時代の相棒は、キミに決めた! ChatGPT推し ver.0
https://qiita.com/kaizen_nagoya/items/8068a884fb2e64cd3c4f

無料ChatGPTの処理限界
https://qiita.com/kaizen_nagoya/items/84683aee26d9f4a28af0

by ChatGPT, with ChatGPT and people opinions.
https://qiita.com/kaizen_nagoya/items/57f00f9b48b25bc231e6

ChatGPTの使い方の利点と課題 by ChatGPT
https://qiita.com/kaizen_nagoya/items/0f469e473a6ed0407daa

DataRobot 風 AI agent Robotをあなたに
https://qiita.com/kaizen_nagoya/items/1ca8ca1dedefaf739d16

ChatGPTの賢い使い方
https://qiita.com/kaizen_nagoya/items/3a7e4583553543eeeeb3

ChatGPTの弱みをあなたに
https://qiita.com/kaizen_nagoya/items/3c97c63a22939e203905

ChatGPTで裸の王様
https://qiita.com/kaizen_nagoya/items/8377be38d3a763e93811

設計 仕様 制約 AI利用開発の鍵 by ChatGPT
https://qiita.com/kaizen_nagoya/items/1b9cb2f9d26308d84791

PowerPoint 筋書き(outline), 見直し(review), 見栄え加工 by ChatGPT
https://qiita.com/kaizen_nagoya/items/37bb97fc250fca37295b

逃げ回るChatGPTを追い詰めるには
https://qiita.com/kaizen_nagoya/items/cd60426e626ba05e0377

三人寄れば文珠の知恵は直交する能力前提 by ChatGPT
https://qiita.com/kaizen_nagoya/items/512e5611615e2426bb42

プログラマ3年で社長事業(未成年編) 博士論文支援追加
https://qiita.com/kaizen_nagoya/items/326452b5bf29c144c307

自殺防止手引き原稿 補足 by ChatGPT
https://qiita.com/kaizen_nagoya/items/7e459fa7edf7205c2667

しつけ(discipline) の測定視点 by ChatGPT
https://qiita.com/kaizen_nagoya/items/6b5ce03c545f7bbd8723

技術者は英語を学ぶ必要はない。英単語の羅列でいい=プログラム。
https://qiita.com/kaizen_nagoya/items/4fc3963a21e0339fd1c9

猫中心設計から鳥中心設計へ part2
https://qiita.com/kaizen_nagoya/items/4d7a5a33c85e0b01dc5d

プログラマ必須科目 ChatGPTにも確認
https://qiita.com/kaizen_nagoya/items/7b30d9d119792130facd

なんで音楽とプログラムの関係がうまく書けないか。
https://qiita.com/kaizen_nagoya/items/489a68d360df4b26f87d

AI利用業務手引き
https://qiita.com/kaizen_nagoya/items/f201b292f37dba16e9ef

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?