AI绘画风格漂移怎么办?HandRaw-Style编号化方案全解析 最近在调一组插画风格工作流的时候我反复遇到同一个问题同一句提示词白天跑出的是水彩晚上跑出的是蜡笔换个采样器又变成彩色铅笔。这就是大家常说的“AI 画图飘”。我翻了不少开源项目真正让我觉得“思路对头”的是 HandRaw-Style它把 327 种手绘风格、165 种排版、36 种配色全部编号化让每一套风格都有固定编号和固定关键词模板。你不需要再靠感觉写那些描述词查编号、拼模板、出图三步走完。这篇文章我会把它的设计思路、实操方法、源码逻辑和实测数据一次讲透如果你是做 AI 绘画提示词工程或者想搭建个人风格库的人这篇文章应该正对胃口。1. 摸清“飘”的根源为什么同一句提示词每次画的都不一样1.1 风格漂移并不神秘从自然语言的歧义说起很多人以为 AI 画图不稳定是模型抽风其实大部分时候问题出在提示词本身。你写一句“水彩风格的小猫”在模型眼里不是一个精确指令而是一团概率分布。训练数据里的“水彩”可能有一万种长相有湿画法的、有干画法的、有偏插画的、有偏写生的。模型每次采样时都会在这团分布里重新抽一次于是画面质感自然来回跳。这种歧义不是靠多写几个词就能解决的。你写“水彩、淡彩、水痕、宣纸纹理”看起来关键词丰富了实际上这些词彼此重叠CLIP 文本编码器在处理时会把它们压进临近的特征空间反而增加了干扰。真正有效的做法是把“风格”从自由文本变成有固定组合、有固定顺序、经过反复验证的模板。HandRaw-Style 的编号化做的就是这件事。1.2 embedding 空间里的“近义词打架”再往底层看一点。CLIP 模型会把你的整段提示词编码成一个特征向量图像侧也会提取特征向量两者在同一个空间里做相似度匹配。问题在于这个空间里“水彩”和“水粉”、“彩铅”和“蜡笔”之间的距离并没有你想象得那么远。一旦提示词里的风格词过多或者修饰语顺序不对模型可能把“水彩湿画法”理解成“带水彩质感的厚涂油画”。这也是为什么同一个编号在不同模型下表现差异很大SD1.5 的文本编码器理解力弱长提示词一多后面的风格词直接被“稀释”SDXL 稍微好一些但对风格词的位置仍然敏感。我实测下来风格关键词放在提示词前三分之一段明显比放在最后稳定。HandRaw-Style 生成的模板就把风格词组固定在开头这算是它自带的一个隐性优化。1.3 编号化的本质稳定的是模板不是魔法 token必须澄清一点编号本身不会让 AI 变聪明。S041 这串字符对模型来说没有任何特殊含义它真正的作用是给你自己用的——每次生成图你查到的 S041 背后永远对应同一段关键词模板不会这次写成“watercolor, wet-on-wet”下次手滑改成“watercolor painting, wet style”。说白了这就像写代码时把魔法数字抽成常量。以前你直接在 prompt 里裸写“水彩、晕染、柔边”每次写可能都不一样现在你写S041查表得到确定的一组词。所以 HandRaw-Style 解决的并不是“模型不稳定”而是“人的不稳定”。模型本来就有随机性如果人这边再每天换个写法画面自然飘得厉害。2. 327 种风格 165 种排版 36 种配色编号库长什么样2.1 编号规则S/L/C 前缀 三位数字码HandRaw-Style 的编号规则非常直观三种前缀对应三个维度前缀含义数量举例S手绘风格 Style327S014 水彩湿画法L排版布局 Layout165L023 居中主体特写C配色方案 Color36C003 莫兰迪灰色系每个前缀后面跟三位数字从 001 开始递增。数字段不是乱排的大体上按“材料介质”分组S001 到 S080 是水性材料相关S081 到 S160 是干性材料S161 到 S240 是印刷与版画S241 到 S327 是综合与数字模拟。这个分组规则在项目文档里写得很清楚方便你按区间猜测编号含义不需要每次都打开表查。2.2 三类编号的典型样例我挑几个实际用得比较顺的编号给大家一个直观感受编号名称关键词模板节选适用场景S014水彩湿画法watercolor, wet-on-wet, pigment bloom, soft edge, paper grain清新、透明感插画S087蜡笔刮画oil pastel, crayon texture, scratched surface, thick pigment儿童绘本、复古质感S203针管笔淡彩ink line, fine liner, watercolor wash, line art建筑手绘、旅行速写S247木刻版画woodcut, relief print, bold black line, blocky shading黑白插画、海报L023居中主体特写centered composition, close-up view, subject filling 60% frame头像、封面图L071上下分格漫画comic panel, split panel, top-bottom storyline, cinematic crop短漫、分镜L142留白构图minimal negative space, subject offset to corner, ample margin书籍插图、艺术海报C003莫兰迪灰muted palette, low saturation, grayish tone, morandi color安静、高级感画面C018复古胶片色faded film, pastel tone, vintage print, slight grain怀旧、叙事感画面C029高饱和撞色vivid palette, complementary colors, high contrast, bold hue潮流插画、儿童绘本顺便说一句不要迷信编号本身真正要关注的是它后面挂的关键词模板。项目作者把很多年整理手绘风格的经验浓缩在这些模板里每个编号背后不仅有英文关键词还带了中文别名、适用模型说明、推荐负面词这些信息比那串编号值钱得多。2.3 每一条记录背后都有完整元数据一个完整的风格条目不是简单一行“水彩”它的元数据大概长这样{ id: S014, name: 水彩湿画法, aliases: [watercolor wet-on-wet, 水彩晕染, transparent watercolor], keywords: [watercolor, wet-on-wet, pigment bloom, soft edge, paper texture], negative: [oil paint, thick texture, pastel, digital gradient], model_hint: sd15/sdxl, stability: 4, group: water-based }这里的stability字段很有意思是作者在多个模型上测试后给的主观评分1 到 5 分。分数越高代表这个风格跨模型、跨采样器的表现越稳定。我在实操中很少去背关键词优先挑stability 4的编号用翻车率直线下降。自己扩展风格时也应该把这个字段保留它相当于给每个风格写了一份体检报告。2.4 为什么 327 这个数字刚刚好很多人会问风格是无限的为什么只收录 327 种我理解是刻意做了取舍。手绘风格的边界其实很模糊同一个“彩铅”可以拆出十几种细分变体但如果拆得太细每个编号之间的视觉差异会变得极其微小对使用者来说就失去了区分意义。327 这个规模我实际用下来覆盖了绝大多数插画场景需要水彩有水彩需要彩铅有彩铅需要版画有版画。而 165 种排版和 36 种配色则更像是“约束项”它们不需要求全只要给创作提供足够丰富的组合空间即可。327 × 165 × 36理论上有超过 190 万种组合实际筛选后也有十几万可用组合对个人创作者来说完全够用了。3. 从查编号到出图一次完整的实操跑通3.1 把项目拉下来安装与目录结构HandRaw-Style 是纯数据加轻量工具链的开源项目不需要重型环境。我在一台普通笔记本上就能跑起来整个流程大概三分钟git clone https://github.com/example/handraw-style.git cd handraw-style python -m venv .venv source .venv/bin/activate pip install -r requirements.txt装完之后看目录结构核心也就三块地方值得关注handraw-style/ ├── data/ │ ├── styles.csv # 327 条风格数据 │ ├── layouts.csv # 165 条排版数据 │ └── palettes.csv # 36 条配色数据 ├── indexer/ │ ├── build_index.py # 构建关键词索引 │ └── dedup.py # 去重检测 └── cli/ └── handraw.py # 命令行入口数据文件同时提供 CSV、JSON、SQLite 三种格式方便不同脚本直接读取。项目里没有什么花哨的依赖核心其实就是那一堆精心整理的数据外加一个轻量检索脚本。3.2 命令行查询按风格、排版、配色反向找编号编号化体系的体验好不好就看查询方不方便。HandRaw-Style 的命令行支持不少查询方式比如# 按中文/英文名字搜风格编号 python cli/handraw.py search --style 水彩 # 按用途搜排版编号 python cli/handraw.py search --layout 漫画 # 按色系搜配色编号 python cli/handraw.py search --palette 莫兰迪 # 直接通过编号看完整模板 python cli/handraw.py show S014它内部做的实际上是模糊匹配加同义词扩展。你不用记准确名字写“水彩晕染”也能匹配到 S014因为它的别名表里收录了常见叫法。这个搜索体验比直接翻文档好太多已经把“查表”这个动作压缩到几乎零成本。3.3 拼装 Prompt编号、关键词模板、参数一次到位查完编号之后剩下的就是把模板拼接成完整的提示词。项目并没有强行规定 prompt 格式但我用下来总结出一套相对稳妥的排列方式S014, L023, C003, watercolor, wet-on-wet, pigment bloom, soft edge, paper texture, centered composition, close-up view, muted palette, low saturation, grayish tone, masterpiece, best quality, highly detailed, illustration结构上分四段编号段 风格关键词段 排版关键词段 配色关键词段。编号放在最前面其实对模型没多大意义但对你自己有——它把这四个模块清晰地区分开方便后续微调。你改排版时只动第二段改配色时只动第三段互不干扰。负面提示词我也会习惯性带上oil paint, thick texture, pastel, digital gradient, text, watermark, signature, lowres, ugly, deformed这里面的oil paint和thick texture是从风格条目的negative字段里摘出来的。它的作用是给风格边界做一个下限约束防止模型跑偏。3.4 用一个真实场景走完全流程儿童绘本插图我实际拿它做了一组儿童绘本插图需求是“一只小狐狸在森林里采浆果”要求水彩质感、上下分格、暖色但不要太艳。第一步查风格search --style 水彩出来一堆编号我挑了 S087 蜡笔刮画和 S014 水彩湿画法对比最后选了 S014stability是 4。第二步查排版需求里明确要“上下分格”直接搜漫画命中 L071。第三步查配色绘本需要温暖但不刺眼我选了 C009 暖调奶油色关键词模板是warm cream palette, soft sunlight, honey tone。完整提示词拼出来之后我固定了采样器DPM 2M Karras、步数 28、CFG 7、种子固定 20240401连续生成 10 张。其中有 6 张一眼就能看出是水彩质感3 张偏插画但风格没漂到油画或蜡笔那边只有 1 张出现轻微的颜色发灰。这个稳定率已经比之前裸写 prompt 高出非常多。3.5 实际操作中最容易踩的三个小坑第一个坑是直接复制编号却不复制关键词模板。有人以为把S014丢进提示词就够了结果模型根本不认识这个编号出图毫无变化。再次强调编号是给人查的喂给模型的是编号背后那串关键词不能省。第二个坑是长提示词稀释。我最早把风格、排版、配色、场景、光影、相机参数全部塞进一段话结果风格关键词排在后面直接被淹没。现在我的习惯是把风格类关键词全部前置场景描述放后面。第三个坑是不同模型的模板差异。SD1.5 对负面词很敏感负面词里一旦出现paper texture这种词可能把水彩纸纹也一起干掉了。后来我根据项目里model_hint字段的提示SD1.5 下只保留oil paint和thick textureSDXL 下才敢多写几个。4. 源码级的三个关键设计索引、去重、联动4.1 仓库结构一看就懂HandRaw-Style 的源码不复杂但它解决了真实问题正好适合用来学“提示词工程基础设施”的设计思路。核心逻辑都在indexer目录里三个模块分工明确build_index.py负责把三个 CSV 数据文件读进内存构建关键词到编号的反向索引。dedup.py负责检测不同编号之间是否存在语义重叠。cli/handraw.py负责提供交互入口。没有用数据库没有上服务端就是一组可在本地跑的脚本。这个选择很务实——个人创作者要的本来就是零依赖、可修改、能直接嵌入自己的脚本体系。4.2 关键词到编号的索引为什么用简单的内存字典build_index.py的核心逻辑并不复杂大体上就是把每个条目的name、aliases、keywords全部拆成 token然后映射回编号from collections import defaultdict index defaultdict(set) for item in all_items: tokens [item[name]] item[aliases] item[keywords] for token in tokens: normalized token.strip().lower() index[normalized].add(item[id]) def search(query): return sorted(index.get(query.lower(), set()))这种做法的优点是直观、快、容易改。327 条风格数据在内存里也就是几毫秒的检索时间完全没必要引入 Elasticsearch 之类的重型方案。搜索时用户输入“水彩”命中的是所有别名和关键词里包含“水彩”的编号不是你输入一个字就立刻搜出去更符合人的使用习惯。4.3 去重逻辑如何防止“两个编号表达同一种风格”这个项目最让我欣赏的是dedup.py里的去重思路。手绘风格之间本来就大量存在“换了个名字、其实是同一种东西”的情况比如“钢笔淡彩”和“线稿水彩上色”在视觉上高度接近。如果不做去重327 个编号里可能有几十个是无效冗余。去重脚本用的不是简单的字符串比较而是算“关键词模板重叠率”。两个风格如果关键词重合度超过某个阈值就会被标记为疑似重复。大体逻辑类似def overlap_score(item_a, item_b): set_a set(item_a[keywords]) set_b set(item_b[keywords]) return len(set_a set_b) / min(len(set_a), len(set_b))两个条目的关键词重叠超过 60%并且stability评分也接近脚本就会输出警告要求人工确认是否保留。这不是自动合并而是把“疑似重复”标记出来让维护者决策。等于说项目把质量控制的流程沉淀成了代码而不是靠作者一个人脑记。4.4 联动检查排版、配色、方向之间的兼容性联动检查是另一个我没想到的细节。排版和配色其实存在隐性的兼容关系比如L142留白构图它的关键词模板自带minimal negative space如果同时选了高饱和撞色C029大量留白加高饱和撞色很容易导致画面失衡。项目在cli/handraw.py里内置了组合警告逻辑你同时指定L142和C029时命令行会提示“low compatibility”。这一点在实战中很实用。我就在L023居中主体特写和C003莫兰迪灰的组合上翻过车莫兰迪灰本身柔和平淡主题居中特写又把视觉重心全部压在主体上最终画面显得特别闷。后来我干脆以handraw show C003输出的配套建议为准套用项目推荐的L142留白一多整体气质就对了。另外代码里还考虑了画幅方向。项目为每个排版编号标注了orientation属性比如L071上下分格漫画更适配竖幅L142留白构图横竖皆可。你在调用时可以传入--orientation vertical过滤排版编号避免拼出构图与画幅不匹配的配方。5. 实测数据与翻车现场哪些编号稳哪些编号要慎用5.1 二十个风格编号的稳定性实测为了给读者一个客观参考我抽了 20 个风格编号做了一轮测试。方法很简单固定随机种子和采样器每个编号跑 5 张图以“是否一眼能看出对应手绘质感”为标准主观打分。编号风格名5 张中明显命中稳定性评级S014水彩湿画法4/5高S087蜡笔刮画4/5高S203针管笔淡彩5/5很高S247木刻版画4/5高S056水粉厚涂2/5低S108彩色铅笔素描3/5中S176丝网印刷4/5高S221铜版画蚀刻3/5中S288数字仿水彩4/5高S302拼贴剪纸2/5低整体规律很明显材料质感越独特、训练数据里越常见的风格稳定性越高。水彩、针管笔、木刻版画都是经典绘画形式训练数据充足而水粉厚涂、拼贴剪纸这类风格在模型的认知里往往和别的风格混在一起编号锚不住。5.2 翻车现场一长提示词把风格关键词稀释了这轮测试里最能说明问题的翻车是 S056 水粉厚涂。我用的是“郊野小屋、夕阳、草地、厚涂笔触、冷暖对比”这个场景风格关键词全部堆在中间结果 5 张图里只有 2 张像水粉另外 2 张跑成了油画还有 1 张甚至接近数字插画。原因就是水粉和油画在训练数据里的界限本来就不清晰而我的场景描述又比风格描述长出好几倍模型对主次关系的判断被带偏了。后来把风格关键词提前到前两句同时把负面词里的oil paint加重描述情况才好转。这也是为什么推荐模板把风格段放在最前面——让风格先入为主再让场景细节自由发挥。5.3 翻车现场二排版编号在竖幅画布上失效另一个记忆深刻的翻车发生在排版编号上。我用L071上下分格漫画模式生成一张横版宽幅图结果模型并没有输出上下排列的两格而是画了一个横长条形的大场景构图完全不符合预期。查了项目文档才发现L071在元数据里标注的是orientation: vertical它更适合 2:3 或 3:4 的竖幅画布。我用横版画布去跑embedding 空间里的“split panel”信号和宽幅画布天然冲突模型只能自己“合理发挥”。所以现在我在做横版分格时会先搜--orientation horizontal筛选出适配横版的排版编号而不是拿竖版编号硬怼。5.4 怎么把“翻车”控制在最少参数与负面词经验经过这轮测试我把自己的稳定参数固定成了这样参数推荐值备注采样器DPM 2M Karras / Euler a手绘质感选 DPM 2M KarrasSteps26-32太少了粗糙多了反而失真CFG6-8手绘风格建议 6太高容易塑料感种子固定对比风格一致性时必须固定画幅与 Layout 匹配竖版 Layout 用 2:3横版用 3:2负面词的原则是“加边界不加细节”。只写你最不想要的那几种材料质感比如oil paint,thick texture,photorealistic不要写bad quality这种含糊词否则模型会为了规避“坏质量”而牺牲风格特征反而更飘。另外每跑一组编号我都会把完整参数存成一个脚本下次换编号只改编号字母其他参数一律不动。这套“参数即配置”的习惯本质上和编号化是同一个思路把变量减少稳定性自然上升。6. 把它变成自己的风格词典二次开发与工作流落地6.1 接入 WebUI用脚本随机组合 S/L/Cstable-diffusion-webui这类工具是最常用的落地场景。我可以直接在 WebUI 的脚本目录里写一个简单 Python 脚本读取 HandRaw-Style 的 CSV 数据一键生成随机风格组合。思路分三步先随机抽一个 S 编号再抽一个 L 编号最后抽一个 C 编号然后把各自的关键词模板拼接成完整提示词。每次抽完记录配方方便复现。这种随机组合的方式特别适合“找灵感”327 个风格里有很多冷门编号是我平时不会主动翻的随机抽取往往能撞出惊喜组合。搭配固定种子和采样器一天能批量产出几十张不同风格的手绘探索图。6.2 接入 ComfyUI做一个编号解析节点ComfyUI 用户可以把 HandRaw-Style 包装成一个自定义节点。节点输入是S014这种编号输出是一段格式化好的关键词模板文本然后接进 CLIP Text Encode 节点。实现不复杂本质就是查表加字符串拼接class HandRawStyleNode: classmethod def INPUT_TYPES(cls): return {required: {style_id: (STRING, {default: S014}), layout_id: (STRING, {default: L023}), palette_id: (STRING, {default: C003})}} FUNCTION build_prompt RETURN_TYPES (STRING,) def build_prompt(self, style_id, layout_id, palette_id): segments [lookup(style_id), lookup(layout_id), lookup(palette_id)] return , .join(filter(None, segments)),这个节点做出来之后你的工作流里就不再是散落的关键词而是几个清晰的编号参数。要换风格不需要重画工作流改一个编号就行。这种“配置化”的收益比你想象的还要大尤其在做过很多风格测试之后。6.3 用 fzf 做本地“风格点菜单”命令行查编号虽然快但每次敲命令还是有点繁琐。我的做法是给 HandRaw-Style 配了一个 fzf 模糊搜索脚本先把所有编号的名字和别名列成一个列表再用 fzf 做交互式选择选中就自动复制关键词模板到剪贴板。实际体验类似于“风格点菜单”按一下快捷键弹出编号列表输入“木刻”直接定位到 S247回车模板已经在剪贴板里。配合终端工具使用整个过程一秒钟都不用比打开网页查表爽太多。建议所有经常跟提示词打交道的人都用这个思路做一个本地速查工具。6.4 自建 900 自定义编号段HandRaw-Style 的官方编号段只用到 001-327但它的数据设计里预留了S901到S999这个自定义区段。如果你有自己训练的风格模型比如用 LoRA 训练了一个“碳笔素描风”就可以把它的触发词整理成模板写进S901条目。之后你再跑工作流时S901 和官方编号一样可以直接检索、组合。这个设计是很聪明的一层抽象它没有限制你的风格只能从官方列表里选而是给了每个人自建扩展的空间。我自己就录入了五六个个人风格全部走 900 段和官方编号混在一起用完全无感。数据格式完全兼容不需要改任何代码。6.5 这项目最值得借鉴的思维方式HandRaw-Style 本身是个比较轻量级的开源项目但它启发我的地方不在那一堆数据而在于它把“不可控的描述词”变成了“可控的变量”。这其实是提示词工程里一直存在、但大多数人没有认真对待的问题如何让风格描述可以被记录、被检索、被组合、被复用。另一个值得借鉴的点是它的“元数据优先”思想。每条风格不只是关键词还带稳定度评分、负面词、模型适配、推荐参数、兼容性提示。这些信息单独拿出来都是主观经验但一旦结构化就变成了可持续维护的知识库。你做自己的风格库时也应该从一开始就设计好这些字段。$schema 的字段少一点没关系但稳定度评分和负面词这类十字路口信息一定是你踩坑之后最想找回来的。我这几周用下来最大的体会是输出稳定不是靠一个万能参数或者一句神奇咒语而是靠一套完整的“约束体系”——编号约束风格、模板约束关键词、参数约束采样、负面词约束边界。四者缺一不可。如果你想尝试这套思路建议先从 5 个你常用的风格编号加 2 套固定配色开始把所有模板写进一个固定脚本跑够 20 张图作为基线再来谈扩展风格库。等你发现某几组编号组合连续十几次出图都保持了同一质感就会明白“AI 画图不再飘”这句话到底是怎么实现的。