PromptContract
Strict prompt-template input contracts with bounded JSON validation and deterministic one-pass rendering.
PromptContract
English · 0.1.0 · Python 3.10+ · ComfyUI V1 · MIT
在批量生产前校验提示词输入:漏填主体、字段拼错、多带了旧字段、类型不符或长度超限时,让工作流在严格渲染节点报错。合法输入才输出可连接到 CLIPTextEncode.text 的 STRING。
运行时只使用 Python 标准库,不加载模型,不计算 tokenizer 的 token 数,不读取文件或环境变量,也不联网、执行 Python 表达式或保存输出。作者 A ad钙,发布者 ye-zayne。
安装和连接
把本仓库放入 ComfyUI/custom_nodes/comfyui-promptcontract,重启 ComfyUI。没有额外 pip 依赖。
- 在
PromptContract分类添加 Strict Render。 - 填写
template、values_json、contract_json。 - 把输出
prompt接到CLIPTextEncode的text;把生成的 conditioning 接到采样器。 - 调试时添加 Inspect,或把
report_json接到原生 Preview as Text / PreviewAny。
严格渲染必须在采样器的数据依赖链上。独立放置 Inspect 只生成报告,不能阻止另一条采样分支。模型加载等其他依赖可能先执行;本包不会拦截队列中独立的任务。正、负提示词可各用一个 Strict Render,分别提供本提示词实际使用的合同和值。
节点
| 节点 / class type | 输入 | 输出 | 无效输入 |
| --- | --- | --- | --- |
| Inspect / PromptContractInspect | 三个 STRING:template、values_json、contract_json | BOOLEAN valid、STRING verdict、STRING report_json | 返回 false / invalid 和具体错误列表 |
| Strict Render / PromptContractRender | 同上 | STRING prompt、STRING report_json | 抛出简短错误,不输出提示词 |
Inspect 是输出节点,可独立排队;报告可在 API history 中读取。渲染报告包含格式版本、槽位名和出现次数、输入字节数、输出字节数及错误。报告和异常不重复打印输入值或整段模板。
示例
模板:
A {{subject}} in {{style}} style, {{count}} objects; enabled={{enabled}}.
values_json:
{"subject":"纸鹤", "style":"ink", "count":0, "enabled":false}
contract_json:
{
"subject": {"type":"string", "min_length":1, "max_length":120},
"style": {"type":"string", "choices":["ink","photo"]},
"count": {"type":"integer", "minimum":0, "maximum":10},
"enabled": {"type":"boolean"}
}
结果:A 纸鹤 in ink style, 0 objects; enabled=false.。0 和 false 是已填写的合法值,不能相互冒充类型。字符串原样插入,不自动去除首尾空白;只拒绝空字符串和全部由 Unicode 空白字符组成的字符串。
精确语法和转义
| 模板文字 | 含义 / 结果 |
| --- | --- |
| {{subject}} | 引用槽位 subject |
| {{subject}} / {{subject}} | 重复槽位合法,两处使用同一个值 |
| {{{{ | 字面量 {{ |
| }}}} | 字面量 }} |
| {{{{subject}}}} | 字面量 {{subject}},不会查询该槽位 |
| {ordinary braces} | 单花括号属于普通文字 |
按从左到右顺序扫描,四个花括号的转义优先于槽位识别。槽位名必须满足 [A-Za-z_][A-Za-z0-9_]{0,63};{{ subject }}、属性访问、索引、过滤器、默认值或表达式都无效。未闭合 {{、未转义的独立 }} 和空槽位 {{}} 报错。引号和反斜杠没有模板转义含义;JSON 字符串仍遵守 JSON 自身的转义规则。
只渲染一遍模板。如果值本身包含 {{other}}、$HOME 或通配符文字,这些内容会原样进入结果,不继续展开。因此合法输出可以包含刻意转义或值中自带的双花括号。三个输入的本节点文本控件都关闭了 ComfyUI dynamic prompts;其他上游节点如果已改写文字,本包不能还原。
最小合同
合同不是通用 JSON Schema。顶层是“槽位名 → 规则对象”;每个定义的槽位都必填、必须在模板使用,值的键必须与合同一致。未知值、未使用值、未使用合同槽位和未声明的模板槽位均报错。没有可选字段、默认值、类型转换或递归对象。
| 规则 | 支持范围 |
| --- | --- |
| type | 必填:string、integer、number、boolean |
| choices | 可选:1–64 个与声明类型匹配的值,区分大小写 |
| min_length / max_length | 仅字符串;非负整数,按 Unicode 码点计数,不是可见字符或 token 数 |
| minimum / maximum | 仅数值;包含边界,最小值不得大于最大值 |
integer 不接收 1.0 或布尔值;number 接收 JSON 整数和有限浮点数,浮点数采用 Python 的浮点解析。布尔值输出小写 true / false,数值输出 JSON 数值文字。null、数组和对象不能当作槽位值。未知规则(包括 required、enum、pattern)报错。重复 JSON 键、NaN、Infinity、非有限的指数值及无效 Unicode surrogate 都被拒绝。纯文字模板可使用两份 {},但最终提示词仍须非空。
限制
- 模板最多 65,536 UTF-8 字节;每份 JSON 同样最多 65,536 字节。
- 最多 64 个不同槽位、1,024 次占位符引用;一个 JSON 数值文字最多 128 个字符。
- 渲染结果最多 131,072 UTF-8 字节;报告最多列出 128 条错误,并提供省略数量。
- 字符串长度限制上限为 131,072 码点;输入和输出字节限制仍同时生效。
- 这些检查保证输入和模板合同一致,不评价提示词语义、最终画质或实际 CLIP token 截断。
API 示例
examples/inspect_api.json 是不依赖模型的完整 Inspect 请求。examples/render_api.json 是 Strict Render → 原生 PreviewAny 的完整请求,需安装版本包含原生 Preview as Text;提示词与报告分别在两个 Preview 输出中。
从仓库目录提交示例:
curl -H 'Content-Type: application/json' --data-binary @examples/render_api.json http://127.0.0.1:8188/prompt
使用响应的 prompt_id 读取 /history/{prompt_id}。把 values_json 的 subject 删除后,Strict Render 会产生执行错误,两个 Preview 不会收到结果。
examples/clip_wiring_fragment.json 只是 API 图片段:节点 11 的输出 0 接到 CLIPTextEncode 节点 12 的 text,其 clip 指向已有节点 1 的输出 1(例如 CheckpointLoaderSimple)。必须合入已有加载模型、采样器和输出节点的完整图才能提交。
已有节点和本包差异
已有提示词模板节点。ComfyUI-TemplateVars 已支持缺失变量报错,其 CLIP 模板节点也检查花括号;StringConstructor 明确提供递归格式化。PromptContract 集中提供小型类型合同、未知与未使用字段检查、严格 JSON、资源上限和一次性插值。它检查工作流输入;WorkflowCanary 检查输出是否相对基准发生变化,用途不同。
开发验证
python -m pip install pytest ruff
python -m pytest tests --rootdir=tests --confcutdir=tests -q
python -m ruff check . --select S102,S307,E702,F
测试覆盖 Unicode、转义、重复槽位、非递归值、重复 JSON 键、缺失与多余字段、类型/choices/长度/数值边界、0/false 和资源限制。CI 使用 Python 3.10 / 3.12。ComfyUI V1 注册和 API 示例也有本地测试。