尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Codex生成PSD实战:提示词工程与脚本落地全流程

Codex生成PSD实战:提示词工程与脚本落地全流程 1. 先搞清楚一件事Codex 到底能不能直接吐出一个 PSD先把结论摆在最前面能但别指望它像 Photoshop 那样给你一个双击就能打开、图层命名规整、蒙版齐全的成品文件。它真正能做的是生成一份“PSD 结构描述”再由脚本把它翻译成真正的.psd二进制文件。这个区别非常关键很多人第一次尝试就翻车就是因为把“生成 PSD”理解成了“生成 Photoshop 工程”。我最早接触这个玩法是想让模型帮我批量做电商主图的分层模板。当时我的想法很朴素给一段提示词让它输出一个 PSD我拿去改文字就行。结果第一次拿到的是一堆 Markdown 表格写着“背景层、产品层、文字层”我当时就笑了——这玩意儿我自己也能写。后来才想明白模型本身不产出二进制文件它产出的是结构化的图层指令真正落地靠的是psd-tools、pytoshop或者 Adobe 的脚本接口。所以这篇东西适合谁看三类人一是想用 AI 批量生成分层设计稿的电商/运营同学二是想把手里的重复性 PSD 制作流程自动化的设计师三是纯粹好奇“提示词工程能玩到什么程度”的技术玩家。不管你是哪一类只要你能接受“提示词 脚本”这套组合拳后面这些内容你都能直接抄作业。核心关键词我先埋进来Codex、PSD、提示词。这三个词串起来就是一条完整的链路——Codex 负责理解意图并输出结构PSD 是最终产物格式提示词是中间那根指挥棒。指挥棒挥得好不好直接决定最后拿到的是能用的分层文件还是一坨没法看的垃圾。2. 为什么“直接生成 PSD”这件事没那么简单2.1 模型输出的是文本PSD 是二进制这是最根本的矛盾。大语言模型的输出本质是 token 序列也就是文本。而 PSD 是 Adobe 的私有二进制格式里面有图层、通道、蒙版、智能对象、颜色配置文件等一大堆结构化数据。模型不可能凭空“吐”出二进制字节流它只能吐出描述这些结构的文本。那怎么办答案是中间层。让模型输出一份 JSON 或者 YAML描述每个图层的名称、位置、尺寸、透明度、混合模式、文字内容然后写一个 Python 脚本读取这份描述调用psd-tools或pytoshop把它写成真正的 PSD。这个中间层就是提示词要约束的核心对象。我试过让模型直接输出 Python 代码来构建 PSD效果也能用但稳定性差。因为代码里一旦有个缩进错误或者 API 调用顺序不对整个脚本就崩了。相比之下让模型输出 JSON 描述、脚本固定不变容错率高得多。这也是我后来一直坚持的方案。2.2 提示词的核心不是“描述画面”而是“描述结构”很多人写提示词的习惯是描述画面“一个蓝色背景中间有个产品上面有标题文字”。这种提示词给文生图模型用没问题但给 Codex 用来生成 PSD 就太模糊了。它不知道蓝色是哪个色值不知道产品放在哪个坐标不知道标题文字用什么字体、多大字号。正确的思路是把提示词写成一份规格说明书。你要告诉它画布多大、有几个图层、每个图层的类型是什么、位置和尺寸是多少、文字层的内容和样式是什么。这听起来很啰嗦但一旦你把模板固定下来后面就是填空游戏。我个人的经验是提示词里必须包含这几个硬性字段画布尺寸、图层列表、每个图层的类型背景/形状/文字/图片占位、位置坐标、尺寸、以及文字层的字体和字号。缺一个生成出来的 PSD 就会缺胳膊少腿。2.3 为什么选 JSON 而不是自然语言自然语言描述结构模型理解起来会有歧义。比如“标题放在上面”上面是哪里顶部居中还是左上角而 JSON 是强结构的{type: text, x: 100, y: 50, width: 800, height: 120}这种写法没有歧义。更重要的是JSON 可以被脚本稳定解析。你不需要写复杂的正则去提取信息直接json.loads就行。我在实际项目里踩过的坑就是早期用自然语言描述模型有时候输出“标题在顶部”有时候输出“顶部放置标题”脚本根本没法统一处理。换成 JSON 之后这个问题彻底消失。提示如果你用的是 Codex 这类代码模型可以在提示词里明确要求“只输出 JSON不要输出任何解释性文字”。否则它很可能会在 JSON 前后加一段“好的以下是根据您的要求生成的...”这种废话导致解析失败。3. 提示词模板拆解一份能直接用的结构描述3.1 基础模板长什么样下面这份模板是我迭代了七八个版本之后固定下来的你可以直接拿去改。它的核心思路是用 JSON Schema 约束输出格式用示例锁定字段含义。{ canvas: { width: 1080, height: 1080, background: #FFFFFF }, layers: [ { name: 背景层, type: solid, color: #F5F5F5, x: 0, y: 0, width: 1080, height: 1080, opacity: 100, blend_mode: normal }, { name: 产品图占位, type: placeholder, x: 240, y: 200, width: 600, height: 600, opacity: 100, blend_mode: normal }, { name: 主标题, type: text, content: 限时特惠, x: 100, y: 850, width: 880, height: 120, font_family: SourceHanSans-Bold, font_size: 72, color: #333333, align: center, opacity: 100, blend_mode: normal } ] }这份模板里canvas定义画布layers是一个数组每个元素是一个图层。图层类型我定义了三种solid纯色填充、placeholder图片占位、text文字。这三种覆盖了绝大多数模板类 PSD 的需求。3.2 每个字段为什么这么设计canvas.width和canvas.height用像素值不用厘米或英寸因为 PSD 内部就是以像素为单位的。background是画布底色虽然 PSD 本身可以透明但大多数设计稿都有底色所以单独拎出来。图层的x和y是相对于画布左上角的坐标不是相对于父图层。这样设计是为了简化脚本逻辑不需要处理嵌套坐标系。width和height是图层尺寸对于文字层来说这个尺寸是文本框的尺寸不是文字实际渲染的尺寸。opacity用 0 到 100 的整数和 Photoshop 界面上的百分比一致。blend_mode用字符串比如normal、multiply、screen脚本里做一个映射表转成 PSD 内部的枚举值。文字层的font_family我建议用英文名比如SourceHanSans-Bold因为 PSD 内部存储的字体名通常是英文。如果你写“思源黑体”脚本可能找不到对应字体。align控制文字对齐方式center、left、right三选一。3.3 提示词里怎么让 Codex 稳定输出这个结构光给模板不够你还要在提示词里明确告诉它“照着这个结构输出”。我的做法是给一个完整的示例然后说“请严格按照上述 JSON 结构为以下需求生成图层描述”。提示词示例你是一个 PSD 结构生成器。请根据用户需求输出一个 JSON 对象描述 PSD 文件的画布和图层结构。 输出格式必须严格遵循以下 JSON Schema { canvas: {width: int, height: int, background: string}, layers: [ { name: string, type: solid | placeholder | text, x: int, y: int, width: int, height: int, opacity: int, blend_mode: string, color: string (仅 solid 和 text 需要), content: string (仅 text 需要), font_family: string (仅 text 需要), font_size: int (仅 text 需要), align: string (仅 text 需要) } ] } 不要输出任何解释性文字只输出 JSON。 用户需求制作一个 1080x1080 的电商主图模板浅灰色背景中间放产品图占位底部放主标题“限时特惠”字体用思源黑体粗体字号 72颜色深灰。这段提示词的关键在于Schema 明确、示例完整、禁止废话。我实测下来这样写之后 Codex 的输出稳定率能到九成以上偶尔出问题也是因为需求描述本身有歧义。4. 从 JSON 到 PSD脚本落地全流程4.1 环境准备与依赖安装脚本我用 Python 写核心依赖是psd-tools。安装很简单pip install psd-tools pillowpsd-tools负责读写 PSD 文件pillow负责处理图片占位符的生成。如果你需要更精细的控制比如创建智能对象那psd-tools可能不够得考虑pytoshop或者直接调用 Adobe 的 ExtendScript。但对于模板类 PSDpsd-tools完全够用。注意psd-tools在写入 PSD 时对某些高级特性支持有限比如图层样式、蒙版、智能对象。如果你需要这些建议先用 Photoshop 做一个空白模板然后用脚本只替换文字和图片内容。这是另一种思路后面会讲。4.2 核心脚本逐段解析先看整体结构import json from psd_tools import PSDImage from psd_tools.api.layers import PixelLayer, TypeLayer from PIL import Image, ImageDraw, ImageFont def load_spec(path): with open(path, r, encodingutf-8) as f: return json.load(f) def create_canvas(spec): canvas spec[canvas] img Image.new(RGB, (canvas[width], canvas[height]), canvas[background]) return img def render_layers(img, layers): for layer in layers: if layer[type] solid: draw ImageDraw.Draw(img) draw.rectangle( [layer[x], layer[y], layer[x] layer[width], layer[y] layer[height]], filllayer[color] ) elif layer[type] placeholder: draw ImageDraw.Draw(img) draw.rectangle( [layer[x], layer[y], layer[x] layer[width], layer[y] layer[height]], outline#CCCCCC, width2 ) elif layer[type] text: draw ImageDraw.Draw(img) font ImageFont.truetype(layer[font_family] .otf, layer[font_size]) draw.text( (layer[x], layer[y]), layer[content], filllayer[color], fontfont, alignlayer[align] ) return img def save_psd(img, path): psd PSDImage.frompil(img) psd.save(path) if __name__ __main__: spec load_spec(spec.json) img create_canvas(spec) img render_layers(img, spec[layers]) save_psd(img, output.psd)这段代码的逻辑很直白读 JSON、建画布、逐层绘制、保存 PSD。但这里有个问题——PSDImage.frompil会把所有内容合并成一个图层丢失分层信息。这显然不是我们想要的。4.3 保留图层信息的正确做法要保留分层得用psd-tools的底层 API 手动构建图层。下面是我实际用的版本from psd_tools import PSDImage from psd_tools.api.layers import PixelLayer from psd_tools.api.numpy_io import numpy_to_psd import numpy as np from PIL import Image, ImageDraw, ImageFont def create_layer_image(layer, canvas_size): img Image.new(RGBA, canvas_size, (0, 0, 0, 0)) draw ImageDraw.Draw(img) if layer[type] solid: draw.rectangle( [layer[x], layer[y], layer[x] layer[width], layer[y] layer[height]], filllayer[color] ) elif layer[type] placeholder: draw.rectangle( [layer[x], layer[y], layer[x] layer[width], layer[y] layer[height]], outline#CCCCCC, width2 ) elif layer[type] text: font ImageFont.truetype(layer[font_family] .otf, layer[font_size]) draw.text( (layer[x], layer[y]), layer[content], filllayer[color], fontfont, alignlayer[align] ) return img def build_psd(spec, output_path): canvas spec[canvas] canvas_size (canvas[width], canvas[height]) psd PSDImage.new(RGB, canvas_size, canvas[background]) for layer_spec in spec[layers]: layer_img create_layer_image(layer_spec, canvas_size) layer PixelLayer.frompil(layer_img, psd, layer_spec[name]) psd.append(layer) psd.save(output_path)这个版本里每个图层单独渲染成一张 RGBA 图片然后作为PixelLayer追加到 PSD 里。这样保存出来的 PSD 在 Photoshop 里打开每个图层都是独立的可以单独编辑。实操心得PixelLayer.frompil的第二个参数是父级 PSD 对象第三个参数是图层名。图层名的中文支持没问题但建议不要用特殊字符比如/、\、:这些在 PSD 内部可能会出问题。4.4 文字层的特殊处理上面的方案有个硬伤文字层被栅格化成了像素图层在 Photoshop 里没法再编辑文字内容。如果你需要文字可编辑得用TypeLayer。但psd-tools对TypeLayer的创建支持比较弱我试过几次都不太稳定。折中方案是用 Photoshop 做一个空白模板文字层留好然后用脚本替换文字内容。这需要用到 Photoshop 的脚本接口或者用psd-tools修改现有文字层。后者我试过能改内容但字体和样式容易丢。所以我的建议是如果文字不需要后期编辑直接用像素层简单可靠如果需要编辑老老实实用 Photoshop 模板 脚本替换的方案别硬刚psd-tools的文字层创建。5. 提示词工程的关键技巧与避坑指南5.1 怎么让 Codex 理解“分层”这个概念模型对“分层”的理解容易跑偏。你让它生成分层 PSD它可能给你生成一个“图层列表”的文本描述而不是结构化的 JSON。解决办法是在提示词里用示例锁定行为。我通常会在提示词里放一个完整的输入输出示例输入制作一个 800x600 的横幅蓝色背景中间白色文字“欢迎光临”。 输出 { canvas: {width: 800, height: 600, background: #0000FF}, layers: [ {name: 背景, type: solid, color: #0000FF, x: 0, y: 0, width: 800, height: 600, opacity: 100, blend_mode: normal}, {name: 文字, type: text, content: 欢迎光临, x: 200, y: 250, width: 400, height: 100, font_family: SourceHanSans-Bold, font_size: 48, color: #FFFFFF, align: center, opacity: 100, blend_mode: normal} ] }有了这个示例模型就知道你要的是 JSON不是文字描述。我实测下来加了示例之后输出格式的正确率从六成提升到九成以上。5.2 坐标和尺寸的常见错误模型在计算坐标时经常犯两类错误一是把坐标当成相对于父图层二是尺寸和位置不匹配。比如画布 1080x1080它给文字层设置x: 100, y: 850, width: 880, height: 120这没问题。但它有时候会给x: 100, y: 850, width: 1200宽度超出画布了。解决办法是在提示词里加一条约束“所有图层的 x width 不得超过画布宽度y height 不得超过画布高度。” 这条约束加上之后越界问题基本消失。另一个技巧是让模型先算再写。比如提示词里说“请先计算每个图层的边界确保不超出画布然后再输出 JSON。” 这样模型会在内部做一次校验输出质量更高。5.3 字体问题的处理字体是 PSD 生成里最容易翻车的地方。模型不知道你系统里装了什么字体它可能输出一个你根本没有的字体名。解决办法有两个一是在提示词里限定字体列表比如“只能使用 SourceHanSans、Arial、Times New Roman 这三种字体”二是在脚本里做字体回退找不到指定字体就用默认字体。我通常两个都做。提示词里限定字体脚本里再加一层回退。这样即使模型抽风输出了奇怪字体名脚本也不会崩。注意ImageFont.truetype加载字体时如果字体文件不存在会直接抛异常。建议用try-except包起来回退到ImageFont.load_default()。5.4 颜色格式的统一颜色格式不统一也是常见问题。模型可能输出#FFF、#FFFFFF、rgb(255,255,255)、white各种格式。脚本里得做归一化处理。我的做法是在提示词里明确要求“颜色一律使用 6 位十六进制格式如 #FFFFFF”然后在脚本里再加一层转换兼容 3 位十六进制和颜色名。def normalize_color(color): if color.startswith(#): if len(color) 4: return # color[1] * 2 color[2] * 2 color[3] * 2 return color color_map {white: #FFFFFF, black: #000000, red: #FF0000} return color_map.get(color.lower(), #000000)这段代码能处理大部分情况。如果模型输出了rgb()格式那就得再加一层解析不过我在提示词里限制了之后基本没遇到过。6. 常见问题排查速查表6.1 脚本报错与解决方案问题现象可能原因解决方案JSONDecodeError模型输出包含解释性文字提示词里强调“只输出 JSON”脚本里用正则提取第一个{到最后一个}KeyError: canvas模型漏掉了某个字段提示词里给完整示例脚本里加默认值图层位置偏移坐标计算错误提示词里加约束“xwidth 不超画布”脚本里做边界裁剪字体加载失败字体文件不存在脚本里做字体回退提示词里限定字体列表PSD 打开后图层合并用了frompil整体转换改用PixelLayer.frompil逐层添加文字显示为方块字体不支持中文换用支持中文的字体如 SourceHanSans6.2 提示词层面的排查如果脚本没问题但生成的 PSD 不符合预期那多半是提示词的问题。我总结了一个排查顺序先看模型输出的是不是纯 JSON。如果夹杂了文字说明提示词约束不够强。再看 JSON 结构是否完整有没有缺字段。然后看数值是否合理坐标有没有越界颜色格式对不对。最后看图层顺序背景层是不是在最下面。这个顺序能覆盖九成以上的问题。我遇到过的奇葩情况是模型把图层顺序搞反了背景层跑到最上面把其他图层全遮住了。解决办法是在提示词里明确“layers 数组的第一个元素是背景层后续图层按从下到上的顺序排列”。6.3 性能与批量生成单次生成一个 PSD 大概需要几秒钟主要时间花在模型推理上。如果要批量生成建议把提示词模板固定只替换需求描述部分。这样模型不需要每次重新理解格式输出更稳定速度也更快。我做过一个批量生成 100 个电商主图的测试用固定模板 变量替换的方式整体耗时大概十几分钟平均每个不到十秒。如果每次都重新写完整提示词耗时会翻倍。实操心得批量生成时建议把模型输出先存成 JSON 文件再用脚本统一转换。这样即使中间某个生成失败也不影响已经成功的部分。而且 JSON 文件可以人工检查发现问题及时调整提示词。7. 进阶玩法从模板到自动化流水线7.1 结合现有 PSD 模板做替换纯从零生成 PSD 适合简单模板复杂设计还是得靠 Photoshop 模板。我的做法是用 Photoshop 做一个标准模板图层命名规范化然后用脚本读取模板、替换文字和图片、导出新 PSD。psd-tools可以读取现有 PSD 并修改图层内容。比如替换文字层的内容from psd_tools import PSDImage psd PSDImage.open(template.psd) for layer in psd: if layer.name 主标题: layer.text 新的标题内容 psd.save(output.psd)这段代码看起来简单但实际用的时候坑很多。psd-tools修改文字层时字体和样式可能会丢需要手动重新设置。而且不是所有 PSD 都能被正确解析有些复杂模板会报错。所以我的建议是模板尽量简单图层命名规范避免使用太复杂的图层样式。这样脚本处理起来稳定得多。7.2 与设计系统结合如果你在做团队协作可以把提示词模板和脚本封装成一个内部工具。设计师在界面上填表单后台调用模型生成 JSON再转成 PSD。这样非技术同学也能用。我帮一个电商团队做过类似的工具前端用简单的 HTML 表单后端用 Flask 调模型和脚本。设计师选模板类型、填文字内容、上传产品图点生成就能拿到 PSD。整个流程从原来的半小时缩短到两分钟。这个工具的核心其实不是技术而是提示词的标准化。我们把常用的几种模板类型主图、详情页头图、活动横幅的提示词都固定下来设计师只需要填变量。这样模型输出稳定脚本处理也稳定。7.3 局限性与边界这套方案不是万能的。它适合结构清晰、图层简单的模板类 PSD。如果你要做复杂的设计稿比如带蒙版、智能对象、图层样式的这套方案基本搞不定。那些还是得靠设计师手动做。另外模型对空间关系的理解有限。你让它“把文字放在产品图下方 20 像素”它可能算不准。所以提示词里最好用绝对坐标别用相对位置描述。我个人的判断是这套方案能覆盖大概六成的模板类 PSD 需求剩下的四成还是得人工介入。但就这六成已经能省下大量重复劳动了。8. 我踩过的几个坑和最后的建议第一个坑是过度依赖模型输出。早期我完全信任模型生成的 JSON结果经常出现坐标越界、颜色格式错误。后来我在脚本里加了一层校验和修正问题少了很多。所以别偷懒脚本里的容错逻辑该写还得写。第二个坑是字体问题。我一开始没在意字体结果生成的 PSD 在 Photoshop 里打开全是乱码。后来我把常用字体打包到项目里脚本里指定字体文件路径才彻底解决。如果你要批量生成字体文件一定要随项目走别依赖系统字体。第三个坑是图层顺序。模型有时候会把背景层放在数组最后导致生成的 PSD 背景盖住所有内容。解决办法是在脚本里强制把type为solid且尺寸等于画布的图层放到最前面。这个逻辑我写死在脚本里不依赖模型输出。最后一个建议先手动做一个 PSD再用脚本复现它。这样你能清楚地知道每个图层应该是什么样提示词和脚本的目标也更明确。我每次做新模板都是这个流程先手动做一遍再让模型和脚本复现。这样成功率最高也最容易排查问题。这套玩法说到底就是“提示词定结构脚本做落地”。Codex 负责理解你的意图并输出结构化描述脚本负责把描述翻译成 PSD。两者配合好了批量生成分层设计稿这件事就变得非常轻松。提示词确实不复杂复杂的是中间那层脚本的容错和边界处理。把这两块都打磨好你就能真正体会到“让 Codex 直接生成 PSD”的爽感了。
返回列表