File size: 5,888 Bytes
06b8797
 
ebcfb0d
06b8797
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d09190e
06b8797
63d6796
d09190e
06b8797
 
 
 
 
ebcfb0d
 
06b8797
 
 
d09190e
ebcfb0d
06b8797
 
ebcfb0d
06b8797
 
 
 
 
 
 
 
 
 
 
 
 
 
31684d8
8f60829
06b8797
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13841ca
 
 
 
06b8797
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# 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=4,
            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)