garden-skills 中 GPT Image 2 的 ER 图 / 数据模型图模板:从结构化 JSON 提示词到工程感位图

原创2026-10-02 10:48:421,769 阅读
文章标签:人工智能AI 技能/插件提示工程

garden-skills 中 GPT Image 2 的 ER 图 / 数据模型图模板:从结构化 JSON 提示词到工程感位图

本篇技术指南围绕 garden-skills 仓库中 gpt-image-2 技能的 ER 图 / 数据模型图模板展开,讲解如何用一套高度结构化的 JSON 提示词,让 GPT Image 2 生成"工程感"的数据库 ER 图、领域模型图、API schema 图与微服务数据所有权图。读完你将对模板的字段语义、参数策略、crow's foot 关系线规范、三种变体以及实际出图链路(选模板 → 渲染 prompt → 调用 generate.js 落盘)有完整可复用的认识。

一、这个模板是什么:不是可编辑工程图,而是"文档级视觉呈现"

er-diagram.md 位于 skills/gpt-image-2/references/technical-diagrams/er-diagram.md,属于 gpt-image-2 技能 18 大类模板中的 Technical Diagrams(技术示意图)分类。它在文件开头就给出了最重要的边界声明:

⚠️ 本模板生成的是位图(PNG),不是 dbdiagram.io / draw.io 可编辑 ER 图。需要可编辑请用 dbdiagram.io / draw.io / DBeaver。

这意味着它面向的是视觉呈现而非工程编辑:适合放进数据库设计文档、API schema 文档、博客配图、PPT 或评审材料里,让读者一眼看清实体、字段与关系;但如果需要可对齐、可版本化、可二次编辑的工程图,应改用 dbdiagram.io、draw.io 或 DBeaver。这与同目录下其他模板(如 system-architecture.md)的定位完全一致——SKILL.md 中 Technical Diagrams 一节也统一注明:"本目录生成的是 PNG 位图,不是可编辑 SVG;需要可编辑请改用 mermaid / draw.io / excalidraw / Figma"。

该模板覆盖五类数据模型场景:

  • 数据库表结构图(PG / MySQL / SQLite)
  • 领域模型图(DDD 实体 + 关系)
  • 文档型数据库 schema(MongoDB / DynamoDB)
  • API 数据契约 schema 图
  • 微服务边界 + 数据所有权图

二、何时使用与何时不用

模板文档给出了精确的触发关键词:当用户提到 "ER 图 / Entity-Relationship / 数据模型 / 数据库设计 / schema 图 / 表结构",并且希望得到「实体 + 字段 + 关系」标准 ER 图样式、且接受位图时,就使用本模板。

同时它明确划出了三个"不要使用"的边界,避免模板误用:

用户实际诉求 应使用的模板
系统架构 technical-diagrams/system-architecture.md
类图 / UML 类图(含方法) 暂未做专门模板,可借用本模板加方法行
思维导图 technical-diagrams/mind-map-tech.md

这一"何时使用 / 不要使用"结构是 prompt-writing.md(skills/gpt-image-2/references/prompt-writing.md)规定的单模板文件标准结构的一部分,确保模板互不污染、精准命中。

三、缺失信息优先提问顺序

模板定义了 6 级提问优先级,Agent 在信息不足时应按此顺序向用户澄清:

  1. 数据库 / 领域名称(如 "e-commerce 数据模型 / SaaS 用户管理 schema")
  2. 实体列表(建议 4-12 个,超过考虑分子图)
  3. 每个实体的字段(字段名 + 类型 + PK/FK + 是否 nullable)
  4. 实体间关系(1:1 / 1:N / N:M,是否级联)
  5. 是否包含枚举 / 索引 / 约束
  6. 比例(默认 4:3 或 16:9)

这与技能的总询问规则一致:SKILL.md 强调"当模板缺少关键变量时,不要笼统地问'你想要什么风格',应当根据模板字段精确提问",本模板的提问顺序正是"围绕模板关键字段精准提问"的落地实现。

四、主模板:标准 ER 图(暗色工程风)JSON 全解

主模板是一份完整可复用的 JSON 提示词结构模板。注意:这是提示词结构模板,不是 API 请求体模板(SKILL.md「重要约束」一节明确说明,最终交给图像模型的是"渲染后的 prompt 字符串",可以是拍平的 JSON)。核心内容如下:

{
  "type": "工程感 ER 图 / 数据模型图",
  "goal": "生成一张工程感 ER 图作为数据库设计文档 / API schema / 领域模型 review 配图",
  "canvas": {
    "aspect_ratio": "{argument name=\"aspect_ratio\" default=\"4:3\"}",
    "background": "deep slate #0F172A with subtle 1px grid #1E293B at 32px spacing",
    "outer_padding": "60px"
  },
  "title_strip": {
    "title": "{argument name=\"title\" default=\"E-commerce Data Model\"}",
    "subtitle": "{argument name=\"subtitle\" default=\"core entities · v1.0\"}",
    "position": "top-left, JetBrains Mono / SF Mono, light gray"
  },
  "entities": {
    "count": "{argument name=\"entity_count\" default=\"6\"}",
    "items": [
      {
        "id": "E1",
        "name": "users",
        "category": "user",
        "fields": [
          { "name": "id", "type": "uuid", "marker": "PK" },
          { "name": "email", "type": "varchar(255)", "marker": "UQ" },
          { "name": "password_hash", "type": "varchar(255)", "marker": "" },
          { "name": "created_at", "type": "timestamp", "marker": "" },
          { "name": "updated_at", "type": "timestamp", "marker": "" }
        ]
      },
      {
        "id": "E2",
        "name": "orders",
        "category": "transaction",
        "fields": [
          { "name": "id", "type": "uuid", "marker": "PK" },
          { "name": "user_id", "type": "uuid", "marker": "FK→users.id" },
          { "name": "status", "type": "enum", "marker": "" },
          { "name": "total_cents", "type": "bigint", "marker": "" },
          { "name": "created_at", "type": "timestamp", "marker": "" }
        ]
      },
      {
        "id": "E3",
        "name": "order_items",
        "category": "transaction",
        "fields": [
          { "name": "id", "type": "uuid", "marker": "PK" },
          { "name": "order_id", "type": "uuid", "marker": "FK→orders.id" },
          { "name": "product_id", "type": "uuid", "marker": "FK→products.id" },
          { "name": "quantity", "type": "int", "marker": "" },
          { "name": "unit_price_cents", "type": "bigint", "marker": "" }
        ]
      },
      {
        "id": "E4",
        "name": "products",
        "category": "catalog",
        "fields": [
          { "name": "id", "type": "uuid", "marker": "PK" },
          { "name": "sku", "type": "varchar(64)", "marker": "UQ" },
          { "name": "name", "type": "varchar(255)", "marker": "" },
          { "name": "price_cents", "type": "bigint", "marker": "" },
          { "name": "stock", "type": "int", "marker": "" }
        ]
      },
      {
        "id": "E5",
        "name": "categories",
        "category": "catalog",
        "fields": [
          { "name": "id", "type": "uuid", "marker": "PK" },
          { "name": "name", "type": "varchar(128)", "marker": "" },
          { "name": "parent_id", "type": "uuid", "marker": "FK→categories.id (self)" }
        ]
      },
      {
        "id": "E6",
        "name": "product_categories",
        "category": "join",
        "fields": [
          { "name": "product_id", "type": "uuid", "marker": "PK,FK→products.id" },
          { "name": "category_id", "type": "uuid", "marker": "PK,FK→categories.id" }
        ]
      }
    ]
  },
  "entity_style": {
    "shape": "rounded rectangle, corner radius 6px",
    "fill": "category color × 10% opacity",
    "border": "1.5px solid in category color",
    "header_strip": "topmost ~28px height: filled with category color × 25% opacity, contains table name in bold mono 12pt + small icon glyph",
    "field_row_style": "below header: each field row = 'field_name : type [marker]' in mono 10pt, alternating row tint for readability",
    "marker_color": "PK = amber bold, FK = blue, UQ = violet, NN = subtle gray"
  },
  "category_color_map": {
    "user": "cyan #22D3EE",
    "transaction": "emerald #34D399",
    "catalog": "violet #A78BFA",
    "join": "slate #94A3B8",
    "system": "amber #FBBF24",
    "external": "rose #FB7185"
  },
  "relationships": {
    "items": [
      { "from": "E1", "to": "E2", "cardinality": "1:N", "label": "places" },
      { "from": "E2", "to": "E3", "cardinality": "1:N", "label": "contains" },
      { "from": "E4", "to": "E3", "cardinality": "1:N", "label": "appears_in" },
      { "from": "E4", "to": "E6", "cardinality": "1:N", "label": "" },
      { "from": "E5", "to": "E6", "cardinality": "1:N", "label": "" },
      { "from": "E5", "to": "E5", "cardinality": "0..1:N", "label": "parent_of (self)" }
    ],
    "line_style": {
      "default": "solid line 1.5px slate #94A3B8",
      "endpoint_notation": "use crow's foot notation: '1' = single perpendicular tick, 'N' = three-pronged 'crow's foot', '0..1' = open circle + tick, '0..N' = open circle + crow's foot",
      "label_format": "relationship verb in mono 9pt placed near the middle of the line, e.g. 'places' / 'contains'"
    },
    "rule_routing": "lines avoid crossing entities; orthogonal routing preferred; self-relations curve to the side"
  },
  "extras": {
    "indices_section": {
      "enabled": "{argument name=\"indices_enabled\" default=\"false\"}",
      "rule": "if true, below each entity add a small 'Indices' section listing index names (e.g. 'idx_users_email')"
    },
    "color_legend": {
      "enabled": true,
      "position": "bottom-right",
      "content": "category color → role mapping + marker meaning (PK / FK / UQ / NN) + cardinality notation"
    }
  },
  "constraints": {
    "must_keep": [
      "实体框形状统一(圆角矩形 + header strip)",
      "字段行用等宽字体,类型靠右或冒号分隔",
      "PK / FK / UQ 标记清晰(颜色 + 文字)",
      "关系线用 crow's foot 或 UML 多重性表达 1:1 / 1:N / N:M",
      "FK 字段在表内必须标 FK→target_table.field",
      "暗色 grid 背景 + 等宽字体",
      "legend 必画"
    ],
    "avoid": [
      "用菱形当实体(语义错误)",
      "字段行使用比例字体(破坏对齐)",
      "FK 没标 target → 关系丢失上下文",
      "关系线没有 cardinality endpoint",
      "实体 > 12 个(拥挤;按子领域拆分)",
      "join 表与普通表用同色(应该用 'join' 灰色区分)",
      "用 emoji 当字段标记",
      "声称这是可编辑 SVG"
    ]
  }
}

五、关键字段语义与源码佐证

1. canvas 与 title_strip:视觉系统的统一基调

canvas 固定了"暗色 grid + 等宽字体"的视觉系统:背景为 deep slate #0F172A,叠加 #1E293B 的 1px 细网格、32px 间距,外留白 60px;title_strip 位于左上角,使用 JetBrains Mono / SF Mono 等宽字体。这与同目录所有 technical-diagrams 模板(如 state-machine.md、system-architecture.md)保持一致——SKILL.md 第 18 类技术图统一为"暗色 grid 背景 + 等宽字体 + 角色编码配色,每个模板都附 light 变体"。

2. entities:实体框 = 圆角矩形,上下两区

实体框是整张图的信息主体,分上下两区:

  • 上区 header strip:约 28px 高,以分类色 25% 不透明度填充,内含加粗等宽 12pt 表名 + 小图标 glyph;
  • 下区字段列表:每行格式为 field_name : type [marker],等宽 10pt,隔行交替浅色 tint 提升可读性。

字段的 marker 是 ER 语义的关键载体,模板定义了四种标记及对应颜色:PK = amber 加粗、FK = blue、UQ = violet、NN = subtle gray(非空)。其中 FK 标记必须写出目标,格式固定为 FK→target_table.field(例如 FK→users.id),否则"关系丢失上下文"。

3. category_color_map:颜色按"角色"而非"表名"编码

模板内置六类语义色,其中四类在主模板直接使用:

category 含义 颜色
user 用户域 cyan #22D3EE
transaction 交易域 emerald #34D399
catalog 商品目录域 violet #A78BFA
join 关联/连接表 slate #94A3B8
system 系统域 amber #FBBF24
external 外部域 rose #FB7185

值得强调的是 join 表必须用灰色 slate 与普通表区分——主模板的 product_categories 就是复合主键(PK,FK)的 join 表范例,constraints.avoid 中明确禁止"join 表与普通表用同色"。

4. relationships:crow's foot 关系线的精确语义

关系线是 ER 图区别于其他示意图的核心。模板对端点记号给出了精确规范:

  • 1 = 单条垂直 tick(垂直线段)
  • N = 三叉的 crow's foot(乌鸦脚)
  • 0..1 = 空心圆 + tick
  • 0..N = 空心圆 + crow's foot

关系动词标签用等宽 9pt 放在线的中间位置,如 places / contains。布线规则要求:线尽量正交、避免穿过实体,自引用关系(如 categories 的 parent_of (self),基数 0..1:N)向侧面弯曲。主模板示例覆盖了 1:N 与 0..1:N(自引用)两类典型关系。

5. extras:索引区与图例

  • indices_section.enabled 默认 false,开启后会在每个实体下方追加一个小型 "Indices" 区,列出索引名(如 idx_users_email);
  • color_legend.enabled 默认 true、位于右下角,内容为"分类色 → 角色映射 + 标记含义(PK / FK / UQ / NN)+ 基数记号"。must_keep 明确要求 legend 必画——图例是读者正确解码整张图的前提。

六、参数策略:必问 / 可默认 / 可随机

模板遵循 prompt-writing.md 的三类参数划分:

  • 必问:title、实体列表(含字段 + PK/FK 标记)、关系列表(含 cardinality)——这三类缺失会显著影响结果,必须向用户澄清;
  • 可默认:background(暗色 grid)、category_color_map、indices_enabled(false)——缺失时用默认值即可正常工作;
  • 可随机:实体摆放位置(基于实体间关系自动布局,目标是让边交叉最少)。

prompt-writing.md 第 6.1/6.2/6.3 节正是这一划分的通用规范:核心参数优先提问、可默认参数直接落默认值、可随机参数在风格范围内合理生成。

七、自动补全策略

模板给出了四条可直接执行的自动补全规则:

  1. 用户给 "e-commerce schema" 但没给细节 → 使用默认 6 实体版;
  2. 用户没指定 cardinality → 反问(关系语义不能瞎猜);
  3. 用户没给分类 category → 自动按表名归类:users → user、orders → transaction、products → catalog、*_join → join;
  4. 用户说要 light 模式 → 使用变体 1;用户说"含索引" → 启用 indices_enabled。

其中"cardinality 不能瞎猜"是一条重要原则——关系语义属于业务规则,Agent 无权虚构,必须回到用户那里确认。

八、三个变体:Light、DDD、微服务数据所有权

变体 1:浅色 Light ER 图

面向白底文档站 / 印刷场景,通过 modify 块在主模板基础上调整少量字段:

{
  "modify": {
    "background": "warm off-white #F8FAFC + faint grid #E2E8F0",
    "entity_fill": "category color × 8% opacity",
    "entity_border": "1.5px solid (deeper shade for white bg)",
    "label_color": "deep slate #0F172A",
    "vibe": "白底文档站友好"
  }
}

变体 2:DDD 领域模型图(含方法 / 行为)

在实体框上叠加 DDD 战术设计语义,适用于 DDD 战术设计 review、领域建模 workshop、UML 类图、业务建模:

{
  "modify": {
    "entity_label_format": "<<entity / value object / aggregate root>> 在表名上方加 stereotype 标签",
    "field_section_split": "实体内部分两部分:上面字段,下面方法(用 '——' 分隔线分开),方法格式 'methodName(args): returnType'",
    "category_color_map_extra": "aggregate root = amber, entity = emerald, value object = violet, domain service = cyan",
    "use_case": "DDD 战术设计 review、领域建模 workshop"
  }
}

变体 3:微服务数据所有权图(bounded context)

用于微服务拆分、bounded context 设计、康威定律对齐、数据所有权 review:

{
  "modify": {
    "extras": "用大虚线框(bounded context)包围属于同一服务的实体,框上标 'User Service' / 'Order Service' 等",
    "cross_service_relations": "跨服务的关系用红色虚线(暗示 anti-pattern 或显式服务边界跨越)",
    "use_case": "微服务拆分、bounded context 设计、康威定律对齐"
  }
}

三个变体全部遵循"变体不应完全脱离主模板,而应在主模板结构上调整少量字段"的规范(prompt-writing.md 第 10 节),通过 modify 增量覆盖而非另起炉灶。

九、实战链路:从模板到落盘 PNG

在 gpt-image-2 技能中,渲染好的 ER 图提示词通过三条链路出图,取决于运行模式(详见 skills/gpt-image-2/SKILL.md):

  • Mode A(Garden 本地生图):ENABLE_GARDEN_IMAGEGEN=1 且有 OPENAI_API_KEY 时,调用 scripts/generate.js 端到端出图并落盘,例如:
node skills/gpt-image-2/scripts/generate.js \
  --promptfile garden-gpt-image-2/prompt/er-diagram-20260424-153045.md \
  --size 1536x1024
  • Mode B(Host-Native 委托宿主):不调用脚本,直接把渲染好的 prompt 传给宿主自带的图像工具;
  • Mode C(Advisor 顾问):只产出高质量 prompt 保存到 garden-gpt-image-2/prompt/<task-slug>-<timestamp>.md,交给用户自行执行。

generate.js 的内部实现(见 scripts/shared.js)展示了渲染 prompt 之后发生了什么:readPromptInput 读取 prompt(--prompt 或 --promptfile),savePrompt 先把 prompt 落盘到 garden-gpt-image-2/prompt/,postJson 携带 Bearer API Key POST 到 ${OPENAI_BASE_URL || 'https://api.openai.com/v1'}/images/generations,extractGeneratedBytes 优先解析 data[0].b64_json、兼容 data[0].url,最后 saveImage 将图片写入默认目录 garden-gpt-image-2/image/,文件名遵循 <task-slug>-<timestamp>.png 规则(如 er-diagram-20260424-153045.png)。

仓库还提供了真实的案例工程文件可直接对照:website/gpt-image2-website/public/case/technical-diagrams/er-diagram/1.json 是一份 9 实体电商 PostgreSQL 逻辑模型提示词(users / addresses / products / skus / orders / order_items / payments / coupons / coupon_redemptions),它在主模板基础上演示了多个进阶用法:

  • 字段类型使用真实 PG 类型:citext、timestamptz、jsonb、numeric(12,2)、bigint;
  • 关系覆盖三种基数:1:N(places / contains / variants)、1:0..1(orders → payments 的 pays)、0..1:N(addresses → orders 的 ships_to);
  • indices_section.enabled 置为 true,并给出 idx_users_email (email)、idx_orders_user_placed (user_id, placed_at DESC) 等真实索引示例;
  • join 表 coupon_redemptions 用复合主键 PK,FK 且分类为 join 灰色。

十、避免事项:ER 语义的十条红线

模板最后总结了本类图最容易失败的地方,可视为一份"生成质量检查清单":

  1. 字段行用比例字体 → 类型 / 标记不对齐;
  2. FK 不标 target → 关系上下文丢失;
  3. 关系线没 cardinality → 完全失去 ER 语义;
  4. 实体 > 12 个 → 视觉爆炸,必须拆分(或按子领域分子图);
  5. 用菱形当 entity → 语义错误(菱形属于 ER 图的关系符号,不是实体);
  6. 用 emoji 当字段标记;
  7. join 表与普通表混色;
  8. 声称这是可编辑 SVG;
  9. 把"系统架构"塞进 ER 图(应改用 system-architecture 模板);
  10. 把字段类型省略 → 失去工程价值。

其中第 9 条呼应了模板开头的模板边界——ER 图与系统架构图、状态机图、流程图各自语义独立,混用会造成概念混淆(SKILL.md 模板索引第 18 类明确将 er-diagram 与 flowchart-decision、sequence-diagram、state-machine、mind-map-tech、network-topology 并列,各司其职)。

十一、小结

er-diagram.md 是一个"开箱即用"的结构化提示词模板:它把 ER 图的全部工程语义——实体框结构、字段行格式、PK/FK/UQ/NN 标记、crow's foot 基数记号、角色配色、索引区、图例——编码成可复用的 JSON 结构,配合必问/默认/随机的参数策略与三个变体,可以让 GPT Image 2 稳定产出数据库文档、DDD 领域模型、API schema 与微服务数据所有权评审所需的工程感位图。使用时的关键纪律是:关系基数与业务规则不可虚构、FK 必须标明目标、图例必画、超过 12 个实体必须拆分,并把最终 prompt 通过 generate.js(Mode A)或宿主图像工具(Mode B)执行,prompt 归档到 garden-gpt-image-2/prompt/ 便于复用与调试。

登录后查看全文
garden-skills