2025年6月26日 星期四

OpenAI API 學習筆記 : 呼叫 Image API 生圖 (二)

在前一篇測試中已對 OpenAI Image API 做過初步測試, 本篇要使用 Gradio 做為呼叫 Image API 生圖的使用者介面. 

本系列全部測試筆記參考 :


關於 Gradio 套件用法參考 : 


下面範例以直觀的作法處理模型與尺寸選擇器 : 


測試 1 : 模型與尺寸選擇器不連動的生圖介面 [看原始碼]

# gradio-openai-image-api-test-1.py
import gradio as gr
from openai import OpenAI

def generate_images(prompt, api_key, **kwargs):
    client=OpenAI(api_key=api_key)
    replies=client.images.generate(prompt=prompt, **kwargs)
    urls=[item.url for item in replies.data]
    return urls

def handler(api_key, prompt, model_sel, size_sel, image_count):
    if not api_key.strip():  # 處理使用者未輸入金鑰問題
        return [], '請輸入 OpenAI API Key'
    elif not prompt.strip():  # 處理使用者未輸入提示詞問題
        return [], '請輸入提示詞 (prompt)'
    if model_sel == 'dall-e-2':  
        n=image_count  # dall-e-2 允許生 1~10 張圖
        if size_sel == 'dall-e-2:256x256|dall-e-3:1024x1024':
            size='256x256'
        elif size_sel == 'dall-e-2:512x512|dall-e-3:1024x1792':
            size='512x512'
        else:
            size='1024x1024'
    else:  # model_sel='dall-e-3'
        n=1  # dall-e-3 只允許生 1 張圖
        if size_sel == 'dall-e-2:256x256|dall-e-3:1024x1024':
            size='1024x1024'
        elif size_sel == 'dall-e-2:512x512|dall-e-3:1024x1792':
            size='1024x1792'
        else:
            size='1792x1024'
    urls=generate_images(prompt, api_key, model=model_sel, n=n, size=size)
    msg=f'model:{model_sel}\nsize:{size}\nn:{n}'  # 輸出設定值
    return urls, msg  # 傳回生圖之網址給 Gallery, 設定值給狀態訊息

api_key=gr.Textbox(label='請輸入金鑰 (API key)', type='password')
prompt=gr.TextArea(label='請輸入提示詞 (Prompt)', max_lines=10)
model_sel=gr.Radio(
    label='選擇模型',
    choices=['dall-e-2', 'dall-e-3'],
    value='dall-e-3'
    )
size_sel=gr.Radio(
    label='選擇圖片尺寸',
    choices=[
        'dall-e-2:256x256|dall-e-3:1024x1024',
        'dall-e-2:512x512|dall-e-3:1024x1792',
        'dall-e-2:1024x1024|dall-e-3:1792x1024'
        ],
    value='dall-e-2:256x256|dall-e-3:1024x1024'
    )
image_count=gr.Slider(
    label='圖片張數',
    minimum=1,
    maximum=10,
    step=1,
    value=1
    )
iface=gr.Interface(
    fn=handler,
    inputs=[api_key, prompt, model_sel, size_sel, image_count],  
    outputs=[
        gr.Gallery(label='生成的圖片'),
        gr.Textbox(label='狀態訊息', interactive=False)
        ],
    title='OpenAI Image API 測試',
    flagging_mode='never'
    )
iface.launch()

此例使用兩個 Radio 單選圓鈕來選擇生圖模型與圖片尺寸, 因為 dall-e-2 與 dall-e-3 分別有三種不同尺寸, 故使用 if else 判斷 model_sel 與 size_sel 來決定 size 之值. 為了避免使用者未輸入金鑰或提示詞, 在 handler() 中一開始便檢查這兩個欄位是否為空字串, 是的話就終止生圖並於狀態資訊欄顯示原因. 

輸入前一篇測試使用的描繪亞洲女性臉孔的提示詞 (使用中文版) :

美麗的亞洲女性,優雅且高貴,柔和的自然光,細緻的五官,富有表情的雙眼配上自然的睫毛,光滑如瓷的肌膚,精緻的骨骼結構,自然的妝容,黑色亮麗的頭髮帶有柔和的波浪,神情寧靜,寫實風格,高解析度,專業人像攝影,淺景深,溫暖的色調,電影感燈光,傑作級品質,極致細緻。

使用 dall-e-3 模型繪製 1024x1024 一張結果如下 :




使用 dall-e-2 模型繪製 256x256| 兩張結果如下 :




使用 dall-e-2 模型繪製 512x512| 四張結果如下 :




此 web app 已發布於 Hugging Face Spaces :



上面範例中的模型選單與尺寸選單是獨立不連動的, 我們是利用 if else 依據模型選單值來決定尺寸選單要用哪個選項值, 這種做法簡單但介面不太友善, 使用者看到尺寸選單時會有點困惑. 比較友善的做法是要讓這兩個選單連動, 讓尺寸選單依據模型選單的值顯示 dall-e-2 或 dall-e-3 尺寸.

因為 gr.Interface 不支援元件間連動, 必須使用 gr.Blocks() 結構才能動態更新元件 (例如此處的 gr.Radio) 內容, 將上面範例改寫為如下 gr.Blocks() 架構的版本 : 


測試 2 : 模型與尺寸選擇器連動的生圖介面 [看原始碼]

# gradio-openai-image-api-test-2.py
import gradio as gr
from openai import OpenAI

# 圖片尺寸選項
size_options={
    'dall-e-2': ['256x256', '512x512', '1024x1024'],
    'dall-e-3': ['1024x1024', '1024x1792', '1792x1024']
    }

# 呼叫 OpenAI API 生圖
def generate_images(prompt, api_key, **kwargs):
    client=OpenAI(api_key=api_key)
    replies=client.images.generate(prompt=prompt, **kwargs)
    urls=[item.url for item in replies.data]
    return urls  # Gallery 只能接收串列

# 執行按鈕時處理函式
def handler(api_key, prompt, model_sel, size_sel, image_count):
    if not api_key.strip():   # 處理使用者未輸入金鑰問題
        return [], '請輸入 OpenAI API Key'
    if not prompt.strip():   # 處理使用者未輸入提示詞問題
        return [], '請輸入提示詞 (prompt)'
    if model_sel == 'dall-e-2':
        size=size_sel
        n=image_count   # dall-e-2 允許生 1~10 張圖
    else:
        size=size_sel
        n=1   # dall-e-3 只允許生 1 張圖
    urls=generate_images(prompt, api_key, model=model_sel, n=n, size=size)
    msg=f'模型: {model_sel}\n尺寸: {size}\n張數: {n}'   # 輸出設定值
    return urls, msg  # 傳回生圖之網址串列給 Gallery, 設定值給狀態訊息

# 模型選單連動圖片尺寸選單 : 動態更新圖片尺寸選單
def update_size_options(selected_model):
    return gr.update(
        choices=size_options[selected_model],
        value=size_options[selected_model][0]
        )

# 使用 Blocks 語法 (才有元件連動功能)
with gr.Blocks(title='OpenAI Image API 測試') as blocks:
    gr.Markdown('## 🎨 使用 DALL·E 2 / 3 生圖')
    api_key=gr.Textbox(label='請輸入金鑰 (API key)', type='password')
    prompt=gr.TextArea(label='請輸入提示詞 (Prompt)', max_lines=10)
    model_sel=gr.Radio(
        label='選擇模型',
        choices=['dall-e-2', 'dall-e-3'],
        value='dall-e-3'
        )
    size_sel=gr.Radio(
        label='選擇圖片尺寸',
        choices=size_options['dall-e-3'],
        value=size_options['dall-e-3'][0]
        )
    image_count=gr.Slider(
        label='圖片張數 (DALL·E 2 專用)',
        minimum=1,
        maximum=10,
        step=1,
        value=1
        )
    submit_btn=gr.Button('開始生成')
    gallery=gr.Gallery(label='生成的圖片')
    status=gr.Textbox(label='狀態訊息', interactive=False) # 僅輸出
    # 連動更新圖片尺寸選單
    model_sel.change(
        fn=update_size_options,  # 呼叫自訂函式更新尺寸選單內容
        inputs=model_sel,  # 模型選單值
        outputs=size_sel   # 尺寸選單值
        )
    # 點擊按鈕觸發 handler
    submit_btn.click(
        fn=handler,
        inputs=[api_key, prompt, model_sel, size_sel, image_count],
        outputs=[gallery, status]
        )
blocks.launch()

執行後模型與尺寸選單就會連動了, 預設是 dall-e-3 選單 : 




模型改選 dall-e-2 時尺寸選單會更新選項 :




再次生成亞洲女性臉孔 (使用英文提示詞) : 




選擇 dall-e-3 模型生成一張 1024x1024 圖片 :




選擇 dall-e-2 模型生成兩張 1024x1024 圖片 :





此 Gradio 應用程式我已發佈到 Hugging Face Spaces 平台 :


沒有留言 :