构建AI智能体:二十、妙笔生花:Gradio集成DashScope Qwen-Image模型实现文生图

一、循序渐进

今天按计划是想讲一些RAG的高阶属性的,但连着几天的烧脑模式,着实脑袋也有点疲惫,经常长篇大论的理论学说,看着可能也觉得枯燥了,今天计划结合前面的几篇文章,做个综合性的演示,温故而知新,同时也让大脑短暂的放松放松,事缓则圆,多几分从容!

考虑良久,决定搭建一个基于 Gradio 与 DashScope Qwen-Image 模型的文生图演示应用!此应用通过Gradio 直接生成简洁直观的 Web 界面,使用阿里云通义千问的Qwen-Image模型提供文生图能力。只需输入文字描述,选择风格与尺寸,即可快速生成高质量图像,顺便看看不同组合的prompt生成的图片有什么独特之处。

首先,看看整体界面:

二、文生图实践

1 整体概览

这是一个集成了阿里云 DashScope Qwen-Image 模型Gradio 框架构建的交互式文生图演示应用,考虑到便捷性,特意采用 Gradio 库构建用户界面。应用支持多种图像风格(3D卡通、动漫、油画、水彩等)和尺寸规格,提供负面提示词功能和示例模板,同时也能够输入,通过简单文本输入快速生成精美图像,并支持结果下载与分享。

代码主要功能包括:

  1. API 调用封装:通过 HTTP 请求直接调用 DashScope Qwen-Image API,支持异步任务处理和轮询机制

  2. 参数映射:将用户友好的中文参数名称映射到 API 实际支持的格式

  3. 用户界面:使用 Gradio 构建直观的 Web 界面,支持提示词输入、参数选择和图像展示

  4. 错误处理:完善的异常处理和错误信息反馈机制

  5. 辅助功能:提供示例提示词、图像下载和状态显示等功能

模型使用的是文生图V1版(wanx-v1),是最早期的版本,但它的丰富性足以够我们多场景、多风格、多尺寸的演示,可以根据实际需求切换更新的模型版本,下图是V1版的官网介绍:

相比其他版本文生图模型的介绍,按需选择合适的即可:

负向提示词(Negative Prompt)

负面提示词是AI图像生成中的一个重要概念,它在代码中的作用是指导模型避免生成某些特定内容、风格或元素。

负面提示词是指我们不希望出现在生成图像中的内容描述。与正面提示词(描述希望看到的内容)相反,负面提示词告诉模型应该避免生成什么。

负面提示词的作用:

  1. 排除不需要的元素,避免生成特定物体、人物或场景,如果生成自然风景,可以添加"人物、建筑物"作为负面提示词,确保画面纯净

  2. 改善图像质量,减少常见的图像缺陷,如使用"模糊、扭曲、畸形、低质量"等负面提示词可以提高图像清晰度

  3. 控制风格和氛围,避免不想要的风格倾向,如果希望生成写实风格,可以添加"卡通、漫画、水彩"作为负面提示词

  4. 符合内容政策,避免生成不当或敏感内容,如添加"暴力、血腥、裸露"等负面提示词确保生成内容符合规范

2. 代码结构

python 复制代码
"""
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              # 启用调试模式
    )
  • 使用说明
  1. 首先,您需要在阿里云DashScope平台注册账号并获取API Key

  2. 将代码中的DASHSCOPE_API_KEY变量替换为实际的API Key

  3. 运行代码,Gradio界面将在本地启动

  4. 在浏览器中打开http://localhost:7860访问界面

  5. 输入提示词,选择参数,点击"生成图像"按钮

3. 流程解析

  • 主要步骤:
  1. 用户通过Gradio界面输入提示词和参数

  2. 调用生成图像函数(使用HTTP请求)

  3. 如果是异步任务,则轮询任务状态直到完成

  4. 从返回的结果中获取图像URL并下载图像

  5. 将图像显示在Gradio界面上

  6. 用户可以选择下载图像或清除结果

  • 流程图:
  • 流程概述
  1. 初始化阶段:应用启动时完成库导入、API密钥设置、参数映射定义和核心函数定义

  2. 界面构建:创建Gradio用户界面,包括输入控件、输出区域和功能按钮

  3. 用户交互:

  • 用户输入提示词和参数后点击生成按钮

  • 应用调用DashScope API生成图像

  • 处理API响应(同步或异步)

  • 下载并显示生成的图像

  • 用户可选择下载图像或清除显示内容

4. 执行过程

4.1 初始化阶段

  1. 导入必要的库:加载Gradio、DashScope、requests等依赖库

  2. 设置API密钥:配置DashScope API访问凭证

  3. 定义参数映射:创建用户友好名称与API参数之间的映射关系

  4. 定义核心函数

    • 生成图像函数:构建并发送API请求

    • 轮询任务函数:检查异步任务状态

    • 下载图像函数:获取并保存生成的图像

4.2 用户交互阶段

  1. 构建用户界面:使用Gradio创建包含输入控件和输出区域的Web界面

  2. 定义事件处理:设置按钮点击事件的处理逻辑

  3. 启动应用:运行Gradio服务器,提供Web访问接口

4.3 API调用阶段

  1. 发送生成请求:将用户输入转换为API请求格式并发送

  2. 处理异步任务:如果是异步任务,定期轮询直到任务完成

  3. 下载生成结果:从返回的URL下载生成的图像

  4. 错误处理:捕获并显示各种可能的错误信息

4.4 结果返回阶段

  1. 显示生成状态:实时反馈生成进度和状态

  2. 展示生成结果:在界面中显示生成的图像

  3. 提供操作选项:允许用户下载图像或清除当前结果

5. 代码分解

5.1 导入和初始化

python 复制代码
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 参数定义

python 复制代码
# 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 函数
python 复制代码
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 函数
python 复制代码
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 函数
python 复制代码
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 事件处理函数
python 复制代码
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 界面构建

python 复制代码
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 其他功能

python 复制代码
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 应用启动

python 复制代码
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分辨率。

大图预览:

  1. 提示词:中国桂林漓江,春雨后,雾气缭绕如薄纱,江面如镜,倒映着喀斯特地貌的翠绿山峰。一叶扁舟点缀江心,远处山峦层层叠叠,意境如水墨画般诗意朦胧。柔和散射光,宁静氛围。

大图预览:

  1. 提示词:江南古典园林的夏夜,一轮明月倒映在荷花盛开的池塘中,九曲回廊和亭台在水面形成对称倒影。荷花与荷叶上有晶莹的露珠,远处有薄雾和萤火虫微光,氛围宁静梦幻。蓝金色调,工笔细腻。

大图预览:

  1. 提示词:险峻的悬崖绝壁上,一座古老的寺庙腾空而起,四周是深谷和缭绕的云雾。红墙灰瓦,古松斜出,夕阳的金光恰好打在寺庙的屋檐上,神圣而危险。中国山水画意境,细节惊人。

大图预览:

  1. 提示词:一位绝美的古风少女,面容精致无瑕,鹅蛋脸,柳叶细眉,眼眸清澈如秋水含情,眼神略带疏离感。肌肤白皙透亮如雪,吹弹可破。背景虚化,焦点完全集中在完美的脸庞上。柔光照明,肤色均匀,超级细节。

大图预览:

五、总结

经过今天的部署,我们能构建了一个功能完整、用户友好的Web应用程序,通过Gradio界面连接Qwen-Image模型实现了从文本描述生成高质量图像的功能。使用前务必将 DASHSCOPE_API_KEY 替换为阿里云平台获取的真实密钥。

使用时过程中要注意,从提供的示例提示词开始,逐步修改以探索模型能力;善用负面提示词来排除不想要的元素,能极大提升出图质量;仔细观察生成结果和后台打印的日志,根据错误信息调整参数。

相关推荐
siliconstorm.ai7 小时前
OpenAI重组受阻:微软“锁链”与生态博弈
人工智能
Fabarta技术团队8 小时前
Fabarta个人专属智能体赋能媒体:从过载信息到深度可控的创作体系
人工智能·智能体
电气铺二表姐1377441661510 小时前
【WIFI电表】物联网无线通讯光伏储能三相单相智能电表
运维·人工智能·能源
胶带码农10 小时前
机器学习-时序预测2
人工智能·机器学习
心动啊12110 小时前
神经网络2——使用Keras实现MLP
人工智能·深度学习·神经网络
stjiejieto11 小时前
教育 AI 的下半场:个性化学习路径生成背后,技术如何平衡效率与教育本质?
大数据·人工智能·学习
武子康11 小时前
AI-调查研究-65-机器人 机械臂控制技术的前世今生:从PLC到MPC
人工智能·ai·职场和发展·机器人·职场发展·个人开发·gp
vvilkim11 小时前
PyTorch自动微分(Autograd)原理与实践:让深度学习训练更高效
人工智能·pytorch·深度学习
BFT白芙堂11 小时前
松灵斯坦福Mobile ALOHA同款 | 通过低成本全身远程操作实现双手机器人移动操控学习
人工智能·学习·机器人·移动机器人·论文解读·开源双臂遥操作系统·松灵cobotmagic