Spaces:
Running
Running
# app.py | |
import gradio as gr | |
import together | |
import os | |
import base64 | |
from PIL import Image | |
from io import BytesIO | |
# --- 1. 設定: APIキーの読み込み --- | |
# 環境変数 `TOGETHER_API_KEY` からAPIキーを読み込みます。 | |
# 事前に `export TOGETHER_API_KEY="あなたのAPIキー"` のように設定してください。 | |
api_key = os.environ.get("TOGETHER_API_KEY") | |
# APIキーがあればTogetherAIクライアントを初期化 | |
if api_key: | |
together_client = together.Together(api_key=api_key) | |
else: | |
together_client = None | |
# 使用する画像生成モデル | |
IMAGE_MODEL = "black-forest-labs/FLUX.1-schnell-Free" | |
# --- 2. 中核機能: 画像生成関数 --- | |
def generate_image_from_prompt(prompt: str, history: list): | |
""" | |
TogetherAI APIを使用して画像を生成し、履歴リストの先頭に追加します。 | |
Args: | |
prompt (str): 画像生成のためのテキストプロンプト。 | |
history (list): これまでの生成結果を格納したリスト。 | |
各要素は (PIL.Image, "プロンプト") のタプルです。 | |
Returns: | |
tuple: 更新された履歴リスト (Gallery表示用) と、 | |
更新された履歴リスト (State保持用) のタプル。 | |
""" | |
# APIクライアントが設定されていない場合はエラーを返す | |
if not together_client: | |
raise gr.Error("TogetherAIのAPIクライアントが設定されていません。環境変数 TOGETHER_API_KEY を確認してください。") | |
# プロンプトが空の場合はエラーを返す | |
if not prompt or not prompt.strip(): | |
raise gr.Error("画像を生成するには、プロンプトを入力してください。") | |
print(f"プロンプトを元に画像を生成中: '{prompt}'") | |
try: | |
# TogetherAI APIを呼び出し | |
response = together_client.images.generate( | |
prompt=prompt, | |
model=IMAGE_MODEL, | |
steps=10, | |
n=4, | |
height=1024, | |
width=1024 | |
) | |
# レスポンスにはbase64形式で画像データが含まれている | |
image_b64 = response.data[0].b64_json | |
image_data = base64.b64decode(image_b64) | |
# バイトデータからPILイメージオブジェクトを作成 | |
image = Image.open(BytesIO(image_data)) | |
# 新しい画像とプロンプトを履歴リストの先頭に追加 | |
# Galleryコンポーネントは (image, caption) のタプルのリストを期待します | |
new_history = [(image, prompt)] + history | |
print("画像の生成が完了しました。") | |
return new_history, new_history | |
except Exception as e: | |
print(f"エラーが発生しました: {e}") | |
raise gr.Error(f"画像の生成に失敗しました。エラー詳細: {e}") | |
# --- 3. Gradio UIの構築 --- | |
with gr.Blocks(theme=gr.themes.Soft(), css=".gradio-container {max-width: 800px; margin: auto;}") as app: | |
gr.Markdown( | |
""" | |
# 🖼️ TogetherAI 画像生成アプリ (Gradio版) | |
プロンプトを入力して、TogetherAIのAPIで画像を生成します。 | |
最新の画像がギャラリーの先頭に表示されます。 | |
""" | |
) | |
gr.Markdown("---") | |
# 生成された画像の履歴を保持するためのState | |
# 履歴は [(PIL.Image, "プロンプト1"), (PIL.Image, "プロンプト2"), ...] のリスト | |
history_state = gr.State([]) | |
with gr.Column(): | |
# 入力コンポーネント | |
prompt_input = gr.Textbox( | |
label="画像生成プロンプト", | |
placeholder="例: 月面にいる、写真のようにリアルな猫の宇宙飛行士", | |
lines=4, | |
interactive=True, | |
) | |
# APIキーが設定されていない場合に警告を表示 | |
if not together_client: | |
gr.Warning("環境変数 `TOGETHER_API_KEY` が見つかりません。画像生成機能を利用するにはAPIキーを設定してください。") | |
generate_btn = gr.Button( | |
"画像生成 ✨", | |
variant="primary", | |
# APIクライアントがなければボタンを無効化 | |
interactive=(together_client is not None) | |
) | |
gr.Markdown("---") | |
# ▼▼▼ 修正箇所 ▼▼▼ | |
# gr.subheader を gr.Markdown("## ...") に変更 | |
gr.Markdown("## 生成された画像") | |
# 出力コンポーネント | |
# Galleryは、キャプション付きの画像リストを表示するのに最適です | |
image_gallery = gr.Gallery( | |
label="生成結果", | |
show_label=False, | |
columns=2, | |
height="auto", | |
object_fit="contain", | |
value=None, | |
preview=True | |
) | |
# ボタンのクリックイベントと生成関数を接続 | |
generate_btn.click( | |
fn=generate_image_from_prompt, | |
inputs=[prompt_input, history_state], | |
outputs=[image_gallery, history_state], | |
# API呼び出し中にプログレスインジケーターを表示 | |
show_progress="full" | |
) | |
# ユーザーのための入力例 | |
gr.Examples( | |
examples=[ | |
"A high-resolution photo of a futuristic city with flying cars", | |
"An oil painting of a serene landscape with a river and mountains", | |
"A cute, fluffy alien creature exploring a vibrant, magical forest", | |
"Logo for a coffee shop named 'The Daily Grind', minimalist, modern" | |
], | |
inputs=prompt_input | |
) | |
# `app.launch()` はGradioアプリを起動します | |
# ローカルサーバーが立ち上がり、ブラウザでアクセスできるURLがターミナルに表示されます | |
if __name__ == "__main__": | |
app.launch(mcp_server=True) |