一、循序漸進
今天按計劃是想講一些RAG的高階屬性的,但連着幾天的燒腦模式,着實腦袋也有點疲憊,經常長篇大論的理論學説,看着可能也覺得枯燥了,今天計劃結合前面的幾篇文章,做個綜合性的演示,温故而知新,同時也讓大腦短暫的放鬆放鬆,事緩則圓,多幾分從容!
考慮良久,決定搭建一個基於 Gradio 與 DashScope Qwen-Image 模型的文生圖演示應用!此應用通過Gradio 直接生成簡潔直觀的 Web 界面,使用阿里雲通義千問的Qwen-Image模型提供文生圖能力。只需輸入文字描述,選擇風格與尺寸,即可快速生成高質量圖像,順便看看不同組合的prompt生成的圖片有什麼獨特之處。
首先,看看整體界面:
二、文生圖實踐
1 整體概覽
這是一個集成了阿里雲 DashScope Qwen-Image 模型Gradio 框架構建的交互式文生圖演示應用,考慮到便捷性,特意採用 Gradio 庫構建用户界面。應用支持多種圖像風格(3D卡通、動漫、油畫、水彩等)和尺寸規格,提供負面提示詞功能和示例模板,同時也能夠輸入,通過簡單文本輸入快速生成精美圖像,並支持結果下載與分享。
代碼主要功能包括:
- API 調用封裝:通過 HTTP 請求直接調用 DashScope Qwen-Image API,支持異步任務處理和輪詢機制
- 參數映射:將用户友好的中文參數名稱映射到 API 實際支持的格式
- 用户界面:使用 Gradio 構建直觀的 Web 界面,支持提示詞輸入、參數選擇和圖像展示
- 錯誤處理:完善的異常處理和錯誤信息反饋機制
- 輔助功能:提供示例提示詞、圖像下載和狀態顯示等功能
模型使用的是文生圖V1版(wanx-v1),是最早期的版本,但它的豐富性足以夠我們多場景、多風格、多尺寸的演示,可以根據實際需求切換更新的模型版本,下圖是V1版的官網介紹:
相比其他版本文生圖模型的介紹,按需選擇合適的即可:
負向提示詞(Negative Prompt)
負面提示詞是AI圖像生成中的一個重要概念,它在代碼中的作用是指導模型避免生成某些特定內容、風格或元素。
負面提示詞是指我們不希望出現在生成圖像中的內容描述。與正面提示詞(描述希望看到的內容)相反,負面提示詞告訴模型應該避免生成什麼。
負面提示詞的作用:
1. 排除不需要的元素,避免生成特定物體、人物或場景,如果生成自然風景,可以添加"人物、建築物"作為負面提示詞,確保畫面純淨
2. 改善圖像質量,減少常見的圖像缺陷,如使用"模糊、扭曲、畸形、低質量"等負面提示詞可以提高圖像清晰度
3. 控制風格和氛圍,避免不想要的風格傾向,如果希望生成寫實風格,可以添加"卡通、漫畫、水彩"作為負面提示詞
4. 符合內容政策,避免生成不當或敏感內容,如添加"暴力、血腥、裸露"等負面提示詞確保生成內容符合規範
2. 代碼結構
"""
Qwen-Image 文生圖演示應用
基於阿里雲 DashScope API 和 Gradio 框架構建的文本到圖像生成演示界面
功能特點:
- 支持多種圖像風格選擇 (3D卡通、動漫、油畫、水彩等)
- 提供多種圖像尺寸選項 (正方形、橫屏、豎屏)
- 支持負面提示詞輸入,排除不希望出現在圖像中的內容
- 提供示例提示詞,一鍵嘗試不同風格
- 實時狀態反饋和圖像下載功能
使用方法:
1. 替換 DASHSCOPE_API_KEY 為您的實際API密鑰
2. 運行腳本啓動Gradio Web界面
3. 在瀏覽器中訪問 http://localhost:7860 使用應用
注意: 使用前需在阿里雲DashScope平台申請API密鑰
"""
import gradio as gr
import dashscope
from dashscope import ImageSynthesis
import requests
import tempfile
import os
import time
from PIL import Image
import io
import base64
import json
# 設置您的 DashScope API Key
# 注意: 此處需要替換為實際的API密鑰,可從阿里雲DashScope控制枱獲取
DASHSCOPE_API_KEY = os.environ.get("DASHSCOPE_API_KEY", "") # 請替換為您的實際API Key
# 初始化 DashScope
dashscope.api_key = DASHSCOPE_API_KEY
# DashScope Qwen-Image 支持的風格參數
# 映射用户友好的中文名稱到API實際支持的參數格式
SUPPORTED_STYLES = {
"自動": "auto",
"3D卡通": "<3d cartoon>",
"動漫": "<anime>",
"油畫": "<oil painting>",
"水彩": "<watercolor>",
"素描": "<sketch>",
"中國畫": "<chinese painting>",
"扁平插畫": "<flat illustration>",
"攝影": "<photography>",
"肖像": "<portrait>"
}
# DashScope Qwen-Image 支持的尺寸參數
# 使用星號(*)作為分隔符,這是API要求的格式
SUPPORTED_SIZES = {
"正方形 (1024x1024)": "1024*1024",
"橫屏 (1280x720)": "1280*720",
"豎屏 (720x1280)": "720*1280"
}
def generate_image_direct(prompt, size, style=None, negative_prompt=None):
"""
直接使用HTTP請求調用DashScope API,避免dashscope庫的問題
參數:
prompt: 圖像描述文本
size: 圖像尺寸 (API格式,如"1024*1024")
style: 圖像風格 (可選)
negative_prompt: 負面提示詞 (可選)
返回:
成功: 圖像文件路徑
失敗: 錯誤信息字符串
"""
# DashScope API端點
url = "https://dashscope.aliyuncs.com/api/v1/services/aigc/text2image/image-synthesis"
# 設置請求頭
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {DASHSCOPE_API_KEY}",
"X-DashScope-Async": "enable" # 啓用異步調用
}
# 構建請求體
payload = {
"model": "wanx-v1", # 使用wanx-v1模型
"input": {
"prompt": prompt
},
"parameters": {
"size": size,
"n": 1 # 生成1張圖像
}
}
# 添加風格參數(如果提供且不是"自動")
if style and style != "自動":
# 將中文風格名稱轉換為API支持的格式
style_code = SUPPORTED_STYLES.get(style, "auto")
payload["parameters"]["style"] = style_code
# 添加負面提示(如果提供)
if negative_prompt and negative_prompt.strip():
payload["parameters"]["negative_prompt"] = negative_prompt
try:
# 打印請求詳情便於調試
print(f"發送請求到DashScope API: {json.dumps(payload, ensure_ascii=False)}")
# 發送POST請求到DashScope API
response = requests.post(url, headers=headers, json=payload)
response_data = response.json()
# 打印API響應便於調試
print(f"API響應: {json.dumps(response_data, ensure_ascii=False, indent=2)}")
# 檢查響應狀態碼
if response.status_code == 200:
# 檢查是否為異步任務
if "output" in response_data and "task_status" in response_data["output"]:
task_id = response_data["output"]["task_id"]
print(f"異步任務已創建,任務ID: {task_id}")
# 輪詢任務狀態
return poll_task_result(task_id)
elif "output" in response_data and "results" in response_data["output"]:
# 同步響應,直接獲取結果
if len(response_data["output"]["results"]) > 0:
image_url = response_data["output"]["results"][0]["url"]
return download_and_save_image(image_url)
else:
return "API響應中未包含有效結果"
else:
return "API響應格式不正確"
else:
# 處理API錯誤響應
error_msg = f"API調用失敗,狀態碼: {response.status_code}"
if "message" in response_data:
error_msg += f", 錯誤信息: {response_data['message']}"
return error_msg
except Exception as e:
# 處理異常情況
error_msg = f"發生異常: {str(e)}"
print(error_msg)
import traceback
traceback.print_exc() # 打印完整堆棧跟蹤便於調試
return error_msg
def poll_task_result(task_id, max_attempts=30, delay=2):
"""
輪詢異步任務結果
參數:
task_id: 異步任務ID
max_attempts: 最大輪詢次數
delay: 每次輪詢間隔(秒)
返回:
成功: 圖像文件路徑
失敗: 錯誤信息字符串
"""
# 構建任務狀態查詢URL
url = f"https://dashscope.aliyuncs.com/api/v1/tasks/{task_id}"
headers = {
"Authorization": f"Bearer {DASHSCOPE_API_KEY}"
}
attempt = 0
# 輪詢任務狀態
while attempt < max_attempts:
try:
print(f"輪詢任務狀態,嘗試 {attempt + 1}/{max_attempts}")
# 發送GET請求獲取任務狀態
response = requests.get(url, headers=headers)
response_data = response.json()
# 打印任務狀態響應便於調試
print(f"任務狀態響應: {json.dumps(response_data, ensure_ascii=False, indent=2)}")
if response.status_code == 200:
task_status = response_data["output"]["task_status"]
if task_status == "SUCCEEDED":
# 任務成功,提取圖像URL
if ("output" in response_data and
"results" in response_data["output"] and
len(response_data["output"]["results"]) > 0):
image_url = response_data["output"]["results"][0]["url"]
return download_and_save_image(image_url)
else:
return "任務成功但未包含有效結果"
elif task_status in ["FAILED", "CANCELED"]:
# 任務失敗,提取錯誤信息
error_msg = f"任務失敗,狀態: {task_status}"
if "message" in response_data["output"]:
error_msg += f", 錯誤信息: {response_data['output']['message']}"
return error_msg
else:
# 任務仍在處理中,等待後再次嘗試
time.sleep(delay)
attempt += 1
else:
return f"獲取任務狀態失敗,狀態碼: {response.status_code}"
except Exception as e:
# 處理輪詢過程中的異常
error_msg = f"輪詢任務時發生異常: {str(e)}"
print(error_msg)
time.sleep(delay)
attempt += 1
return "任務處理超時"
def download_and_save_image(image_url):
"""
下載圖像並保存到臨時文件
參數:
image_url: 圖像下載URL
返回:
成功: 圖像文件路徑
失敗: 錯誤信息字符串
"""
try:
# 下載圖像
img_response = requests.get(image_url)
if img_response.status_code == 200:
# 創建臨時文件保存圖像
with tempfile.NamedTemporaryFile(delete=False, suffix='.png') as f:
f.write(img_response.content)
image_path = f.name
print("圖像下載成功!")
return image_path
else:
return f"下載圖像失敗,狀態碼: {img_response.status_code}"
except Exception as e:
return f"下載圖像時發生異常: {str(e)}"
# 創建 Gradio 界面
with gr.Blocks(title="Qwen-Image 文生圖演示", theme=gr.themes.Soft()) as demo:
gr.Markdown("# 🎨 Qwen-Image 文生圖演示")
gr.Markdown("使用阿里雲 DashScope 的 Qwen-Image 模型根據文本描述生成圖像")
# 使用行佈局分割輸入和輸出區域
with gr.Row():
# 左側輸入區域
with gr.Column(scale=1):
# 提示詞輸入框
prompt = gr.Textbox(
label="提示詞",
placeholder="請輸入詳細的圖像描述,例如:一隻戴着禮帽、拿着手杖的卡通貓,背景是城市夜景",
lines=3
)
# 負面提示詞輸入框
negative_prompt = gr.Textbox(
label="負面提示詞 (可選)",
placeholder="請輸入不希望出現在圖像中的內容",
lines=1
)
# 圖像尺寸選擇下拉菜單
size = gr.Dropdown(
choices=list(SUPPORTED_SIZES.keys()),
value="正方形 (1024x1024)",
label="圖像尺寸"
)
# 圖像風格選擇下拉菜單
style = gr.Dropdown(
choices=list(SUPPORTED_STYLES.keys()),
value="自動",
label="圖像風格"
)
# 生成圖像按鈕
generate_btn = gr.Button("生成圖像", variant="primary")
# 使用説明
gr.Markdown("### 使用説明")
gr.Markdown("""
1. 在提示詞框中輸入您想要生成的圖像描述
2. 可選:在負面提示詞框中輸入不希望出現在圖像中的內容
3. 選擇圖像尺寸和風格,點擊"生成圖像"按鈕
4. 等待幾秒鐘,生成的圖像將顯示在右側
**注意**: 首次使用需要設置您的 DashScope API Key
**支持的尺寸**: 1024x1024, 1280x720, 720x1280
**支持的風格**: 3D卡通, 動漫, 油畫, 水彩, 素描, 中國畫, 扁平插畫, 攝影, 肖像
""")
# 右側輸出區域
with gr.Column(scale=1):
# 生成的圖像顯示區域
output_image = gr.Image(
label="生成的圖像",
interactive=False
)
# 狀態信息顯示文本框
status_text = gr.Textbox(
label="狀態信息",
interactive=False,
lines=3
)
# 操作按鈕行
with gr.Row():
download_btn = gr.Button("下載圖像")
clear_btn = gr.Button("清除")
# 示例提示詞區域
examples = gr.Examples(
examples=[
["一隻戴着禮帽、拿着手杖的卡通貓,背景是城市夜景", "正方形 (1024x1024)", "3D卡通", "模糊"],
["寧靜的湖邊日落,天空中有粉紅色的雲彩,水面有倒影", "橫屏 (1280x720)", "中國畫", "人物"],
["未來科技城市,飛行汽車穿梭在高樓大廈之間,霓虹燈光", "正方形 (1024x1024)", "自動", "傳統建築"],
["一隻可愛的熊貓在竹林裏吃竹子,陽光透過竹葉灑下", "豎屏 (720x1280)", "自動", "人工建築物"]
],
inputs=[prompt, size, style, negative_prompt],
label="示例提示詞 (點擊嘗試)"
)
# 處理生成按鈕點擊事件
def on_generate_click(prompt, size, style, negative_prompt):
# 驗證提示詞是否為空
if not prompt.strip():
return None, "請輸入提示詞"
# 驗證API密鑰是否已設置
if not DASHSCOPE_API_KEY or DASHSCOPE_API_KEY == "您的API_KEY":
return None, "請先設置您的 DashScope API Key"
# 將用户友好的尺寸名稱轉換為API格式
api_size = SUPPORTED_SIZES.get(size, "1024*1024")
# 調用API生成圖像
result = generate_image_direct(prompt, api_size, style, negative_prompt)
# 檢查結果是圖像路徑還是錯誤信息
if isinstance(result, str) and result.endswith('.png') and os.path.exists(result):
return result, "圖像生成成功!"
else:
return None, f"生成失敗: {result}"
# 綁定生成按鈕點擊事件
generate_btn.click(
fn=on_generate_click,
inputs=[prompt, size, style, negative_prompt],
outputs=[output_image, status_text]
)
# 處理下載按鈕點擊事件
def on_download_click(image):
# 檢查是否有圖像可下載
if image is None:
return "沒有可下載的圖像"
# 生成基於時間戳的文件名
timestamp = int(time.time())
filename = f"qwen_image_{timestamp}.png"
try:
# 如果圖像是文件路徑,複製到當前目錄
if isinstance(image, str) and os.path.exists(image):
import shutil
shutil.copy2(image, filename)
return f"圖像已保存為 {filename}"
else:
return "無法保存圖像:無效的圖像路徑"
except Exception as e:
return f"保存圖像時發生錯誤: {str(e)}"
# 綁定下載按鈕點擊事件
download_btn.click(
fn=on_download_click,
inputs=output_image,
outputs=status_text
)
# 處理清除按鈕點擊事件
def on_clear_click():
return None, "已清除圖像"
# 綁定清除按鈕點擊事件
clear_btn.click(
fn=on_clear_click,
inputs=None,
outputs=[output_image, status_text]
)
# 應用啓動入口
if __name__ == "__main__":
# 檢查API密鑰是否已設置
if not DASHSCOPE_API_KEY or DASHSCOPE_API_KEY == "您的API_KEY":
print("警告: 請先設置您的 DashScope API Key")
print("您可以在代碼中設置 DASHSCOPE_API_KEY 變量")
# 啓動 Gradio 界面
demo.launch(
server_name="0.0.0.0", # 允許外部訪問
server_port=7860, # 設置端口
share=False, # 不創建公開鏈接
debug=True # 啓用調試模式
)
- 使用説明
- 首先,您需要在阿里雲DashScope平台註冊賬號並獲取API Key
- 將代碼中的DASHSCOPE_API_KEY變量替換為實際的API Key
- 運行代碼,Gradio界面將在本地啓動
- 在瀏覽器中打開http://localhost:7860訪問界面
- 輸入提示詞,選擇參數,點擊"生成圖像"按鈕
3. 流程解析
- 主要步驟:
1. 用户通過Gradio界面輸入提示詞和參數
2. 調用生成圖像函數(使用HTTP請求)
3. 如果是異步任務,則輪詢任務狀態直到完成
4. 從返回的結果中獲取圖像URL並下載圖像
5. 將圖像顯示在Gradio界面上
6. 用户可以選擇下載圖像或清除結果
- 流程圖:
- 流程概述
1. 初始化階段:應用啓動時完成庫導入、API密鑰設置、參數映射定義和核心函數定義
2. 界面構建:創建Gradio用户界面,包括輸入控件、輸出區域和功能按鈕
3. 用户交互:
- 用户輸入提示詞和參數後點擊生成按鈕
- 應用調用DashScope API生成圖像
- 處理API響應(同步或異步)
- 下載並顯示生成的圖像
- 用户可選擇下載圖像或清除顯示內容
4. 執行過程
4.1 初始化階段
- 導入必要的庫:加載Gradio、DashScope、requests等依賴庫
- 設置API密鑰:配置DashScope API訪問憑證
- 定義參數映射:創建用户友好名稱與API參數之間的映射關係
- 定義核心函數:
- 生成圖像函數:構建併發送API請求
- 輪詢任務函數:檢查異步任務狀態
- 下載圖像函數:獲取並保存生成的圖像
4.2 用户交互階段
- 構建用户界面:使用Gradio創建包含輸入控件和輸出區域的Web界面
- 定義事件處理:設置按鈕點擊事件的處理邏輯
- 啓動應用:運行Gradio服務器,提供Web訪問接口
4.3 API調用階段
- 發送生成請求:將用户輸入轉換為API請求格式併發送
- 處理異步任務:如果是異步任務,定期輪詢直到任務完成
- 下載生成結果:從返回的URL下載生成的圖像
- 錯誤處理:捕獲並顯示各種可能的錯誤信息
4.4 結果返回階段
- 顯示生成狀態:實時反饋生成進度和狀態
- 展示生成結果:在界面中顯示生成的圖像
- 提供操作選項:允許用户下載圖像或清除當前結果
5. 代碼分解
5.1 導入和初始化
import gradio as gr
import dashscope
from dashscope import ImageSynthesis
import requests
import tempfile
import os
import time
from PIL import Image
import io
import base64
import json
# 設置您的 DashScope API Key
DASHSCOPE_API_KEY = os.environ.get("DASHSCOPE_API_KEY", "") # 請替換為您的實際API Key
# 初始化 DashScope
dashscope.api_key = DASHSCOPE_API_KEY
導入必要的庫:
- gradio: 用於構建Web界面
- dashscope: 阿里雲的DashScope SDK
- requests: 用於HTTP請求
- tempfile, os: 用於文件操作
- time: 用於時間相關操作
- PIL, io, base64: 用於圖像處理
- json: 用於JSON數據處理
API密鑰設置:從環境變量中獲取名為DASHSCOPE_API_KEY的API key。
5.2 參數定義
# DashScope Qwen-Image 支持的風格參數
SUPPORTED_STYLES = {
"自動": "auto",
"3D卡通": "<3d cartoon>",
"動漫": "<anime>",
"油畫": "<oil painting>",
"水彩": "<watercolor>",
"素描": "<sketch>",
"中國畫": "<chinese painting>",
"扁平插畫": "<flat illustration>",
"攝影": "<photography>",
"肖像": "<portrait>"
}
# DashScope Qwen-Image 支持的尺寸參數
SUPPORTED_SIZES = {
"正方形 (1024x1024)": "1024*1024",
"橫屏 (1280x720)": "1280*720",
"豎屏 (720x1280)": "720*1280"
}
- 參數映射:創建了兩個字典,將用户友好的參數名稱映射到DashScope API實際支持的參數格式。
- 解決兼容性問題:通過這種方式,用户界面可以使用友好的中文名稱,而API調用使用正確的格式。
5.3 主要功能函數
5.3.1 generate_image_direct 函數
def generate_image_direct(prompt, size, style=None, negative_prompt=None):
# 構建請求頭和請求體
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {DASHSCOPE_API_KEY}",
"X-DashScope-Async": "enable" # 啓用異步調用
}
payload = {
"model": "wanx-v1",
"input": {
"prompt": prompt
},
"parameters": {
"size": size,
"n": 1
}
}
# 處理可選參數
if style and style != "自動":
style_code = SUPPORTED_STYLES.get(style, "auto")
payload["parameters"]["style"] = style_code
if negative_prompt and negative_prompt.strip():
payload["parameters"]["negative_prompt"] = negative_prompt
# 發送請求並處理響應
response = requests.post(url, headers=headers, json=payload)
response_data = response.json()
# 處理同步和異步響應
if response.status_code == 200:
if "output" in response_data and "task_status" in response_data["output"]:
task_id = response_data["output"]["task_id"]
return poll_task_result(task_id) # 異步任務,需要輪詢
elif "output" in response_data and "results" in response_data["output"]:
# 同步響應,直接獲取結果
if len(response_data["output"]["results"]) > 0:
image_url = response_data["output"]["results"][0]["url"]
return download_and_save_image(image_url)
- 直接HTTP請求:使用requests庫直接調用DashScope API。
- 異步處理:通過設置X-DashScope-Async: enable頭,啓用異步處理模式。
- 參數處理:正確處理風格和負面提示詞等可選參數。
- 錯誤處理:檢查HTTP狀態碼和響應結構,確保正確處理各種情況。
5.3.2 poll_task_result 函數
def poll_task_result(task_id, max_attempts=30, delay=2):
url = f"https://dashscope.aliyuncs.com/api/v1/tasks/{task_id}"
headers = {"Authorization": f"Bearer {DASHSCOPE_API_KEY}"}
attempt = 0
while attempt < max_attempts:
response = requests.get(url, headers=headers)
response_data = response.json()
if response.status_code == 200:
task_status = response_data["output"]["task_status"]
if task_status == "SUCCEEDED":
if ("output" in response_data and
"results" in response_data["output"] and
len(response_data["output"]["results"]) > 0):
image_url = response_data["output"]["results"][0]["url"]
return download_and_save_image(image_url)
elif task_status in ["FAILED", "CANCELED"]:
error_msg = f"任務失敗,狀態: {task_status}"
if "message" in response_data["output"]:
error_msg += f", 錯誤信息: {response_data['output']['message']}"
return error_msg
else:
time.sleep(delay)
attempt += 1
- 輪詢機制:定期檢查異步任務的狀態,直到任務完成或超時。
- 超時控制:通過max_attempts和delay參數控制輪詢頻率和最大嘗試次數。
- 狀態處理:正確處理任務的各種狀態(成功、失敗、取消、處理中)。
- 錯誤信息提取:從API響應中提取詳細的錯誤信息,便於調試和用户反饋。
5.3.3 download_and_save_image 函數
def download_and_save_image(image_url):
try:
img_response = requests.get(image_url)
if img_response.status_code == 200:
with tempfile.NamedTemporaryFile(delete=False, suffix='.png') as f:
f.write(img_response.content)
image_path = f.name
return image_path
else:
return f"下載圖像失敗,狀態碼: {img_response.status_code}"
except Exception as e:
return f"下載圖像時發生異常: {str(e)}"
- 圖像下載:從生成的URL下載圖像內容。
- 臨時文件:使用tempfile創建臨時文件保存圖像,避免永久存儲。
- 錯誤處理:捕獲下載過程中可能出現的異常。
5.3.4 on_generate_click 事件處理函數
def on_generate_click(prompt, size, style, negative_prompt):
if not prompt.strip():
return None, "請輸入提示詞"
if not DASHSCOPE_API_KEY or DASHSCOPE_API_KEY == "您的API_KEY":
return None, "請先設置您的 DashScope API Key"
# 將用户友好的尺寸名稱轉換為API格式
api_size = SUPPORTED_SIZES.get(size, "1024*1024")
# 調用API
result = generate_image_direct(prompt, api_size, style, negative_prompt)
# 檢查結果是圖像路徑還是錯誤信息
if isinstance(result, str) and result.endswith('.png') and os.path.exists(result):
return result, "圖像生成成功!"
else:
return None, f"生成失敗: {result}"
generate_btn.click(
fn=on_generate_click,
inputs=[prompt, size, style, negative_prompt],
outputs=[output_image, status_text]
)
- 參數驗證:檢查提示詞是否為空和API密鑰是否已設置。
- 參數轉換:將用户友好的參數名稱轉換為API支持的格式。
- 結果處理:根據返回結果判斷是圖像路徑還是錯誤信息,並更新相應的輸出控件。
5.4 Gradio 界面構建
with gr.Blocks(title="Qwen-Image 文生圖演示", theme=gr.themes.Soft()) as demo:
gr.Markdown("# 🎨 Qwen-Image 文生圖演示")
with gr.Row():
with gr.Column(scale=1):
# 輸入控件
prompt = gr.Textbox(label="提示詞", lines=3)
negative_prompt = gr.Textbox(label="負面提示詞 (可選)", lines=2)
size = gr.Dropdown(choices=list(SUPPORTED_SIZES.keys()), value="正方形 (1024x1024)", label="圖像尺寸")
style = gr.Dropdown(choices=list(SUPPORTED_STYLES.keys()), value="自動", label="圖像風格")
generate_btn = gr.Button("生成圖像", variant="primary")
with gr.Column(scale=1):
# 輸出控件
output_image = gr.Image(label="生成的圖像", interactive=False)
status_text = gr.Textbox(label="狀態信息", interactive=False, lines=3)
with gr.Row():
download_btn = gr.Button("下載圖像")
clear_btn = gr.Button("清除")
# 示例提示詞
examples = gr.Examples(
examples=[
["一隻戴着禮帽、拿着手杖的卡通貓,背景是城市夜景", "正方形 (1024x1024)", "3D卡通", "模糊"],
# 更多示例...
],
inputs=[prompt, size, style, negative_prompt],
label="示例提示詞 (點擊嘗試)"
)
- 界面佈局:使用gr.Row()和gr.Column()創建響應式佈局。
- 輸入控件:
gr.Textbox: 用於提示詞和負面提示詞輸入
gr.Dropdown: 用於選擇尺寸和風格
gr.Button: 生成圖像按鈕
- 輸出控件:
gr.Image: 顯示生成的圖像
gr.Textbox: 顯示狀態信息
- 示例功能:使用gr.Examples提供預設的示例,用户可以一鍵嘗試。
5.5 其他功能
def on_download_click(image):
if image is None:
return "沒有可下載的圖像"
timestamp = int(time.time())
filename = f"qwen_image_{timestamp}.png"
try:
if isinstance(image, str) and os.path.exists(image):
import shutil
shutil.copy2(image, filename)
return f"圖像已保存為 {filename}"
else:
return "無法保存圖像:無效的圖像路徑"
except Exception as e:
return f"保存圖像時發生錯誤: {str(e)}"
download_btn.click(
fn=on_download_click,
inputs=output_image,
outputs=status_text
)
def on_clear_click():
return None, "已清除圖像"
clear_btn.click(
fn=on_clear_click,
inputs=None,
outputs=[output_image, status_text]
)
- 下載功能:將生成的圖像保存到本地文件。
- 清除功能:清除顯示的圖像和狀態信息。
- 錯誤處理:捕獲可能出現的異常並提供友好的錯誤信息。
5.6 應用啓動
if __name__ == "__main__":
# 檢查API密鑰是否已設置
if not DASHSCOPE_API_KEY or DASHSCOPE_API_KEY == "您的API_KEY":
print("警告: 請先設置您的 DashScope API Key")
print("您可以在代碼中設置 DASHSCOPE_API_KEY 變量")
# 啓動 Gradio 界面
demo.launch(
server_name="0.0.0.0", # 允許外部訪問
server_port=7860, # 設置端口
share=False, # 不創建公開鏈接
debug=True # 啓用調試模式
)
- API密鑰檢查:啓動前檢查API密鑰是否已正確設置。
- 服務器配置:配置服務器監聽地址、端口和調試模式。
三、示例畫作賞析
1.示例提示詞:寧靜的湖邊日落,天空中有粉紅色的雲彩,水面有倒影
大圖預覽:
2.示例提示詞:未來科技城市,飛行汽車穿梭在高樓大廈之間,霓虹燈光
大圖預覽:
3.示例提示詞:一隻可愛的熊貓在竹林裏吃竹子,陽光透過竹葉灑下
大圖預覽:
四、妙筆生花,美圖賞析
1. 提示詞:一位絕美的仙俠古風女子,面容精緻無瑕,肌膚勝雪,淡妝容,眼眸如秋水含情。身着飄逸的雪紗漢服,衣袂飄飄,上有淡淡的青蓮暗紋,髮絲邊緣閃爍着柔光,站在雲霧繚繞的仙境山巔。大師級攝影,膠片質感,超高細節,8K分辨率。
大圖預覽:
2. 提示詞:中國桂林灕江,春雨後,霧氣繚繞如薄紗,江面如鏡,倒映着喀斯特地貌的翠綠山峯。一葉扁舟點綴江心,遠處山巒層層疊疊,意境如水墨畫般詩意朦朧。柔和散射光,寧靜氛圍。
大圖預覽:
3. 提示詞:江南古典園林的夏夜,一輪明月倒映在荷花盛開的池塘中,九曲迴廊和亭台在水面形成對稱倒影。荷花與荷葉上有晶瑩的露珠,遠處有薄霧和螢火蟲微光,氛圍寧靜夢幻。藍金色調,工筆細膩。
大圖預覽:
4. 提示詞:險峻的懸崖絕壁上,一座古老的寺廟騰空而起,四周是深谷和繚繞的雲霧。紅牆灰瓦,古鬆斜出,夕陽的金光恰好打在寺廟的屋檐上,神聖而危險。中國山水畫意境,細節驚人。
大圖預覽:
5. 提示詞:一位絕美的古風少女,面容精緻無瑕,鵝蛋臉,柳葉細眉,眼眸清澈如秋水含情,眼神略帶疏離感。肌膚白皙透亮如雪,吹彈可破。背景虛化,焦點完全集中在完美的臉龐上。柔光照明,膚色均勻,超級細節。
大圖預覽:
五、總結
經過今天的部署,我們能構建了一個功能完整、用户友好的Web應用程序,通過Gradio界面連接Qwen-Image模型實現了從文本描述生成高質量圖像的功能。使用前務必將 DASHSCOPE_API_KEY 替換為阿里雲平台獲取的真實密鑰。
使用時過程中要注意,從提供的示例提示詞開始,逐步修改以探索模型能力;善用負面提示詞來排除不想要的元素,能極大提升出圖質量;仔細觀察生成結果和後台打印的日誌,根據錯誤信息調整參數。