从 DALL-E 到 gpt-image-1:generative-ai-for-beginners 第 09 课「构建图像生成应用」完整实战
本文基于开源课程仓库 generative-ai-for-beginners 的第 09 课 构建图像生成应用(阿拉伯语译本,对应 英文版课程文档)展开:先讲清楚 DALL-E 与 Midjourney 这类文生图模型是什么、如何工作,再给出从零搭建一个可运行的 Python 图像生成应用的全部步骤(依赖、.env 配置、完整 app.py 代码、参数逐项解析),并深入讲解图像编辑(带掩码)、图像变体、温度参数与「元提示词」边界控制,最后结合仓库中真实的 aoai-app.py、aoai-app-variation.py 等源码文件印证每一处 API 调用的实际写法。读完后,你可以独立复现课程中的图像生成、编辑、变体与元提示词四大实战能力。
为什么需要图像生成应用
大语言模型(LLM)的能力不止于文本生成——同样可以从文本描述生成图像。图像作为一种输出模态,在医疗科技(MedTech)、建筑、旅游、游戏开发等诸多领域都有很高的实用价值。课程把这一定位归纳为两点:
- 图像编辑与合成。可以为各种用途生成图像,例如对图像进行编辑(在局部区域加入新元素)或图像合成。
- 跨行业应用。可以为医疗科技、旅游、游戏开发等多种行业生成素材图像。
课程的落点是一个贯穿始终的实战场景——初创公司 Edu4All:学生为自己的课堂评测(assessment)创建图像。具体画什么由学生自己决定,可以是自创童话的插画、故事里的新角色,或是帮助自己可视化想法与概念。例如,学生正在课堂上学习「纪念碑」这一主题时,用如下提示词即可生成配图:
“Dog next to Eiffel Tower in early morning sunlight”(清晨阳光中,一只狗站在埃菲尔铁塔旁)
本节的学习目标(对应原文档 Learning Goals):
- 构建一个图像生成应用;
- 使用「元提示词(meta prompts)」为应用设定内容边界;
- 掌握与 DALL-E 和 Midjourney 这类模型协同工作。
DALL-E 与 Midjourney 是什么
DALL-E 与 Midjourney 是当下最流行的两个图像生成模型,都允许你用文本提示词(prompt)来生成图像。
DALL-E:CLIP + 扩散注意力的组合
DALL-E 是一个从文本描述生成图像的生成式 AI 模型。从模型构成看,它是两个模型的组合:
- CLIP:一个能把图像和文本都映射为「嵌入(embeddings)」——即数据的数值化表示——的模型;
- 扩散注意力(diffused attention):一个能从这些嵌入反向生成图像的模型。
DALL-E 在「图像 + 文本」的成对数据集上训练,因此可以接受文本描述并输出图像,比如「戴帽子的猫」或「留莫霍克发型的狗」。
Midjourney
Midjourney 的工作方式与 DALL-E 类似:从文本提示词生成图像,同样支持 “a cat in a hat”“dog with a mohawk” 这类描述性提示词。
底层机制:自回归 Transformer
课程对 DALL-E 工作原理的解释是:DALL-E 基于 Transformer 架构,并采用自回归 Transformer(autoregressive transformer)。自回归 Transformer 定义了模型如何从文本描述逐像素地生成图像——每次生成一个像素,再用已生成的像素去生成下一个像素,信号反复穿过神经网络的多个层,直到整幅图像完成。通过这一过程,DALL-E 能够控制生成图像中的属性、物体、特征等要素;而 DALL-E 2 和 DALL-E 3 对生成结果的掌控力更强。
项目依赖与环境准备
要构建一个图像生成应用,仓库中 09-building-image-applications/requirements.txt 列出了四个必需依赖(与课程文档完全一致):
python-dotenv
openai
pillow
requests
各库的职责(继承自课程文档的说明):
| 库 | 作用 |
|---|---|
| python-dotenv | 强烈建议使用,把密钥保存在 _.env_ 文件中,与代码隔离 |
| openai | 用于与 OpenAI / Azure OpenAI API 交互的官方 SDK |
| pillow | 在 Python 中处理、打开、展示图像 |
| requests | 执行 HTTP 请求(用于下载生成结果的图片 URL) |
创建并部署 Azure OpenAI 图像模型
按照课程文档的前置条件:若尚未完成,需先在 Azure 侧创建 Azure OpenAI 资源并部署图像模型,模型选择以仓库当前版本为准——英文版课程文档已更新为选择 gpt-image-1(当前一代 Azure OpenAI 图像模型;DALL-E 3 属于旧代,不再对新部署开放)。这一点与仓库源码完全吻合:python 目录下的示例脚本 统一使用 api_version = "2024-10-21" 且模型名来自环境变量,不再写死 dall-e-3。
创建第一个图像生成应用
第 1 步:创建 .env 文件
按课程文档创建 _.env_(注意:阿拉伯语译本中示例部署名仍为旧代 dall-e-3,与仓库当前源码一致的写法是 gpt-image-1,见下文源码印证):
AZURE_OPENAI_ENDPOINT=<your endpoint>
AZURE_OPENAI_API_KEY=<your key>
AZURE_OPENAI_DEPLOYMENT="gpt-image-1"
这些信息可以在 Azure OpenAI Foundry 门户中你的资源「Deployments(部署)」部分找到。
第 2 步:创建虚拟环境并安装依赖
macOS / Linux:
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
Windows:
python3 -m venv venv
venv\Scripts\activate.bat
第 3 步:完整 app.py 代码
按课程文档,创建 app.py(以下为课程文档中的完整代码):
import openai
import os
import requests
from PIL import Image
import dotenv
from openai import OpenAI, AzureOpenAI
# import dotenv
dotenv.load_dotenv()
# configure Azure OpenAI service client
client = AzureOpenAI(
azure_endpoint = os.environ["AZURE_OPENAI_ENDPOINT"],
api_key=os.environ['AZURE_OPENAI_API_KEY'],
api_version = "2024-02-01"
)
try:
# Create an image by using the image generation API
generation_response = client.images.generate(
prompt='Bunny on horse, holding a lollipop, on a foggy meadow where it grows daffodils',
size='1024x1024', n=1,
model=os.environ['AZURE_OPENAI_DEPLOYMENT']
)
# Set the directory for the stored image
image_dir = os.path.join(os.curdir, 'images')
# If the directory doesn't exist, create it
if not os.path.isdir(image_dir):
os.mkdir(image_dir)
# Initialize the image path (note the filetype should be png)
image_path = os.path.join(image_dir, 'generated-image.png')
# Retrieve the generated image
image_url = generation_response.data[0].url # extract image URL from response
generated_image = requests.get(image_url).content # download the image
with open(image_path, "wb") as image_file:
image_file.write(generated_image)
# Display the image in the default image viewer
image = Image.open(image_path)
image.show()
# catch exceptions
except openai.InvalidRequestError as err:
print(err)
代码逐段解析(对应课程文档讲解)
-
导入依赖:引入 OpenAI SDK、dotenv、requests 与 Pillow:
import openai import os import requests from PIL import Image import dotenv -
加载环境变量:从
_.env_读入端点与密钥:dotenv.load_dotenv() -
配置 Azure OpenAI 客户端:
client = AzureOpenAI( azure_endpoint = os.environ["AZURE_OPENAI_ENDPOINT"], api_key=os.environ['AZURE_OPENAI_API_KEY'], api_version = "2024-02-01" ) -
调用图像生成 API:
generation_response = client.images.generate( prompt='Bunny on horse, holding a lollipop, on a foggy meadow where it grows daffodils', size='1024x1024', n=1, model=os.environ['AZURE_OPENAI_DEPLOYMENT'] )API 会以 JSON 对象响应,其中包含生成图像的 URL;用该 URL 下载图像并落盘。
-
展示图像:用 Pillow 打开并调用系统默认看图程序:
image = Image.open(image_path) image.show()
生成参数的逐项说明
课程文档对 client.images.generate(...) 的四个关键参数给出了明确定义,这里完整保留并标注适用前提:
- prompt:用于生成图像的文本提示词。示例中是 “Bunny on horse, holding a lollipop, on a foggy meadow where it grows daffodils”(雾霭弥漫、长满水仙花的草地上,一匹马上坐着一只抱着棒棒糖的兔子)。
- size:生成图像的尺寸。示例为
1024x1024像素。 - n:生成的图像数量。示例代码传
n=1(文档正文描述为“生成两张”,实际以代码传入值为准)。 - temperature:控制生成式 AI 模型输出随机性的参数。取值在 0~1 之间:0 表示输出确定性(可复现倾向),1 表示输出随机;默认值为 0.7。该参数在下一节「温度」中单独实验验证。
仓库源码印证:当前 API 版本与模型参数的实际写法
课程文档中的 app.py 是教学基线版本;仓库中真正维护的 aoai-app.py 体现了该课在迁移到新一代模型后的三处演进,值得对照理解:
client = AzureOpenAI(
api_key=os.environ['AZURE_OPENAI_API_KEY'], # this is also the default, it can be omitted
api_version = "2024-10-21",
azure_endpoint=os.environ['AZURE_OPENAI_ENDPOINT']
)
model = os.environ['AZURE_OPENAI_DEPLOYMENT']
result = client.images.generate(
model=model,
prompt='Bunny on horse, holding a lollipop, on a foggy meadow where it grows daffodils. It says "hello"',
size='1024x1024',
n=1
)
generation_response = json.loads(result.model_dump_json())
- API 版本升级为
2024-10-21:教学基线使用2024-02-01,当前部署gpt-image-1需要新版 API,注释中也提示应查阅 Microsoft Foundry 文档确认模型所需的 API 版本; - 模型名显式外置:
model不再内联在调用参数中,而是先读入变量再传入,便于按部署切换; - 响应解析方式:新版 SDK 返回的是 Pydantic 风格对象,仓库用
result.model_dump_json()转 JSON 后再取data[0].url,这与教学版直接访问generation_response.data[0].url的效果等价。
此外,oai-app.py 展示了直连 OpenAI(非 Azure)的对照写法:client = OpenAI(api_key=api_key) 加 model="dall-e-3",并在启动前校验 OPENAI_API_KEY 是否存在、下载图片时加 timeout=30 与 raise_for_status()、异常捕获改为 OpenAIError——这些是教学版代码没有覆盖的工程化细节,可作为落地生产时的参考。
图像生成的进阶能力:编辑与变体
课程文档指出,除了「几行代码生成一张图」,图像 API 还支持两类进阶操作。
1. 图像编辑(Edit):图 + 掩码 + 提示词
给出一张已有图像、一个掩码(mask,标识要修改的区域)和一段文本提示词,就能修改图像的局部——例如给「兔子图」的兔子上加一顶帽子。注意:编辑能力在 DALL-E 3 中不受支持。课程文档给出基于 GPT Image 的示例:
response = client.images.edit(
model="gpt-image-1",
image=open("sunlit_lounge.png", "rb"),
mask=open("mask.png", "rb"),
prompt="A sunlit indoor lounge area with a pool containing a flamingo"
)
image_url = response.data[0].url
基础图只包含阳光下的室内水吧,而最终图像会在掩码指定的泳池区域出现一只火烈鸟。三张素材与结果如下:
2. 创建变体(Variation)
思路是:取一张已有图像,请求模型基于它创建变体。做法是提供图像加提示参数:
response = client.images.create_variation(
image=open("bunny-lollipop.png", "rb"),
n=1,
size="1024x1024"
)
image_url = response.data[0].url
注意(继承原文档说明):变体能力在模型层面有限制——课程文档说明该能力仅适用于 OpenAI 的 DALL-E 2 模型,不适用于 gpt-image-1。
仓库中对应的可运行脚本是 aoai-app-variation.py:它先打开上一节生成的 images/generated-image.png 并展示,随后调用 client.images.create_variation(image=open(image_path, "rb"), n=1, size="1024x1024"),把结果下载保存为 generated_variation.png 再展示。oai-app-variation.py 则是直连 OpenAI 的对照版本,二者逻辑一致,差异仅在客户端类型(AzureOpenAI vs OpenAI)。
温度(Temperature):控制输出的随机性
温度是控制生成式 AI 模型输出随机性的参数:取值 0~1,0 表示输出确定性、1 表示输出随机,默认 0.7。课程用一个重复实验直观演示了温度的作用。
实验 1:同一提示词跑两次
Prompt : "Bunny on horse, holding a lollipop, on a foggy meadow where it grows daffodils"
两次运行得到相似但并不相同的图像(第一次出现兔子,第二次画面以马为主)——说明即使不显式设置温度,输出也带有随机性。
实验 2:显式设置更低随机性
先把生成调用写成低随机倾向形式(课程文档示例):
generation_response = client.images.create(
prompt='Bunny on horse, holding a lollipop, on a foggy meadow where it grows daffodils', # Enter your prompt text here
size='1024x1024',
n=2
)
再把温度显式设为 0:
generation_response = client.images.create(
prompt='Bunny on horse, holding a lollipop, on a foggy meadow where it grows daffodils', # Enter your prompt text here
size='1024x1024',
n=2,
temperature=0
)
运行后得到的两张图像明显彼此更相似——温度越接近 0,同一提示词下的输出越趋于一致;越接近 1,风格与构图差异越大。这个结论可以直接指导产品决策:教学评测配图这类需要稳定观感的场景,应压低温度;而需要创意多样性(如为故事生成多版角色形象)时则应调高。
用元提示词(Meta Prompts)为应用设定边界
演示已经能生成图像,但面向客户(尤其 Edu4All 这样的教育产品)必须设定内容边界:不生成不适合工作场合(not safe for work)的图像,不生成不适合儿童的图像。课程给出的手段是元提示词(metaprompts):
- 元提示词是用于控制生成式 AI 模型输出的文本提示词;
- 它置于用户文本提示词之前,与用户输入一起封装成单个完整提示词,随请求嵌入模型调用中,从而在应用层面对模型输出形成约束。
一个典型的元提示词(原文保留英文,因为提示词需传给模型):
You are an assistant designer that creates images for children.
The image needs to be safe for work and appropriate for children.
The image needs to be in color.
The image needs to be in landscape orientation.
The image needs to be in a 16:9 aspect ratio.
Do not consider any input from the following that is not safe for work or appropriate for children.
(Input)
在演示代码中,它被写成「黑名单变量 + 多行 f-string + 拼接用户输入」的结构:
disallow_list = "swords, violence, blood, gore, nudity, sexual content, adult content, adult themes, adult language, adult humor, adult jokes, adult situations, adult"
meta_prompt =f"""You are an assistant designer that creates images for children.
The image needs to be safe for work and appropriate for children.
The image needs to be in color.
The image needs to be in landscape orientation.
The image needs to be in a 16:9 aspect ratio.
Do not consider any input from the following that is not safe for work or appropriate for children.
{disallow_list}
"""
prompt = f"{meta_prompt}
Create an image of a bunny on a horse, holding a lollipop"
# TODO add request to generate image
从上可以看出:最终发送的 prompt 是「元提示词 + 用户输入」的拼接体,所有生成的图像都会同时受元提示词约束(儿童安全、彩色、横向、16:9、排除黑名单内容)。仓库中 aoai-solution.py 的 disallow_list 与 meta_prompt 与本节代码逐字一致,印证了这是课程的标准落地写法。
课程任务与参考解法
课程作业(Assignment):回到 Edu4All 场景,让学生能为评测生成图像——学生创作包含纪念碑(monuments)的图像,具体选哪个纪念碑、放在什么情境里,由学生发挥创意。
课程文档给出的一份参考解法(完整代码):
import openai
import os
import requests
from PIL import Image
import dotenv
from openai import AzureOpenAI
# import dotenv
dotenv.load_dotenv()
# Get endpoint and key from environment variables
client = AzureOpenAI(
azure_endpoint = os.environ["AZURE_OPENAI_ENDPOINT"],
api_key=os.environ['AZURE_OPENAI_API_KEY'],
api_version = "2024-10-21"
)
disallow_list = "swords, violence, blood, gore, nudity, sexual content, adult content, adult themes, adult language, adult humor, adult jokes, adult situations, adult"
meta_prompt = f"""You are an assistant designer that creates images for children.
The image needs to be safe for work and appropriate for children.
The image needs to be in color.
The image needs to be in landscape orientation.
The image needs to be in a 16:9 aspect ratio.
Do not consider any input from the following that is not safe for work or appropriate for children.
{disallow_list}
"""
prompt = f"""{meta_prompt}
Generate monument of the Arc of Triumph in Paris, France, in the evening light with a small child holding a Teddy looks on.
"""
try:
# Create an image by using the image generation API
generation_response = client.images.generate(
prompt=prompt, # Enter your prompt text here
size='1024x1024',
n=1,
)
# Set the directory for the stored image
image_dir = os.path.join(os.curdir, 'images')
# If the directory doesn't exist, create it
if not os.path.isdir(image_dir):
os.mkdir(image_dir)
# Initialize the image path (note the filetype should be png)
image_path = os.path.join(image_dir, 'generated-image.png')
# Retrieve the generated image
image_url = generation_response.data[0].url # extract image URL from response
generated_image = requests.get(image_url).content # download the image
with open(image_path, "wb") as image_file:
image_file.write(generated_image)
# Display the image in the default image viewer
image = Image.open(image_path)
image.show()
# catch exceptions
except openai.BadRequestError as err:
print(err)
该解法同时串联了本课程的三个知识点:元提示词边界控制(meta_prompt + disallow_list)、完整生成流程(生成 → 取 URL → 下载 → 保存 → 展示)、以及异常处理(BadRequestError)。仓库中维护版 aoai-solution.py 与之同构,差异仅为输出文件名(ch9-sol-generated-image.png)与用 result.model_dump_json() 解析新版响应。
延伸:同一课程的 TypeScript 实现
除 Python 外,仓库还为第 09 课提供了 TypeScript 对照实现 typescript/image-generation-app,入口为 src/main.ts。从 package.json 可以看到其依赖为 openai(^4.77.0)、dotenv 与构建工具 typescript/nodemon/ts-node,脚本通过 npm start(nodemon 监听 src 并以 ts-node 执行 ./src/main.ts)运行。对于前端/全栈开发者,可直接参考该目录把本课程的图像生成流程移植到 Node 环境。
小结
- 本课的核心链路是:提示词(可含元提示词边界)→
client.images.generate→ 从响应取图像 URL →requests下载 → Pillow 保存并展示; - 进阶能力包括带掩码的
images.edit(DALL-E 3 不支持)、仅 OpenAI DALL-E 2 支持的images.create_variation; - 温度 0~1(默认 0.7)控制输出随机性,需要稳定观感时取 0;
- 元提示词是应用层控制内容安全与画面规格(彩色、横向、16:9、儿童友好 + 黑名单)的实用手段;
- 仓库源码(python 目录与 typescript 目录)展示了课程代码从 DALL-E 3 迁移到 gpt-image-1(API 版本 2024-10-21)后的实际写法,可作为对照。
课程第 10 课将转向低代码方式构建 AI 应用,可继续参考 10-building-low-code-ai-applications。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00



