{ "id": "cdb7a54f-3f88-4d2f-aa34-9034f3cb6b91", "revision": 0, "last_node_id": 9, "last_link_id": 12, "nodes": [ { "id": 1, "type": "Note", "pos": [ 40, 20 ], "size": [ 1620, 200 ], "flags": {}, "order": 0, "mode": 0, "inputs": [], "outputs": [], "properties": {}, "widgets_values": [ "HASH VAULT (image-only API) \u2014 caching the Gemini Style Transfer node\n\nStyle Transfer takes (image, style, intensity, ...) and emits a styled image \u2014 no prompt STRING anywhere. v1.2.0 of API-Optimizer made Hash Vault's payload_string optional and added any_input_2/3/4, so we can hash purely on image + widget values.\n\nWIRING\nLoadImage routes to BOTH Style Transfer.image AND Hash Vault.any_input.\nThe Style Transfer Settings node owns the style + intensity dropdowns and emits each as a STRING. Its outputs fan out to BOTH the matching Style Transfer inputs (widgets converted to inputs) AND Hash Vault.any_input_2 / any_input_3.\n\nWhy a Settings node instead of StringConstantMultiline: the Settings node keeps the native ComfyUI dropdown UX \u2014 typeahead, validation, no typos. Typing 'Saul Leiter / Intimate' as free text into a StringConstantMultiline silently breaks the cache the moment you mistype.\n\nResult: same image + same style + same intensity \u2192 cache hit \u2192 no API call. Change any of the three \u2192 new hash \u2192 API runs once, then cached.\n\nNOT CACHED: the Style Transfer node still has its own model / seed / aspect_ratio / resolution / direction widgets that DON'T factor into the hash here. If you change those and want a fresh render, clear the matching .pt file in output/hash_vault/ first. Or wire those through additional any_input slots if you have them free.\n\nREQUIRES\nComfyUI-API-Optimizer v1.2.0+, ComfyUI-Gemini-Direct (Settings node shipped in the release that includes GeminiStyleTransferSettings)." ] }, { "id": 2, "type": "LoadImage", "pos": [ 40, 240 ], "size": [ 320, 320 ], "flags": {}, "order": 1, "mode": 0, "inputs": [ { "localized_name": "image", "name": "image", "type": "COMBO", "widget": { "name": "image" }, "link": null }, { "localized_name": "upload", "name": "upload", "type": "IMAGEUPLOAD", "widget": { "name": "upload" }, "link": null } ], "outputs": [ { "localized_name": "IMAGE", "name": "IMAGE", "type": "IMAGE", "links": [ 1, 2 ], "slot_index": 0 }, { "localized_name": "MASK", "name": "MASK", "type": "MASK", "links": [], "slot_index": 1 } ], "properties": { "cnr_id": "comfy-core", "ver": "0.18.1", "Node name for S&R": "LoadImage" }, "widgets_values": [ "example.png", "image" ] }, { "id": 3, "type": "GeminiStyleTransferSettings", "pos": [ 40, 600 ], "size": [ 320, 120 ], "flags": {}, "order": 2, "mode": 0, "inputs": [ { "localized_name": "style", "name": "style", "type": "COMBO", "widget": { "name": "style" }, "link": null }, { "localized_name": "intensity", "name": "intensity", "type": "COMBO", "widget": { "name": "intensity" }, "link": null } ], "outputs": [ { "localized_name": "style", "name": "style", "type": "STRING", "links": [ 3, 4 ], "slot_index": 0 }, { "localized_name": "intensity", "name": "intensity", "type": "STRING", "links": [ 5, 6 ], "slot_index": 1 } ], "properties": { "cnr_id": "comfyui-gemini-direct", "ver": "1.1.0", "Node name for S&R": "GeminiStyleTransferSettings", "aux_id": "jeremieLouvaert/ComfyUI-Gemini-Direct" }, "widgets_values": [ "Saul Leiter / Intimate", "full" ] }, { "id": 5, "type": "DeterministicHashVault", "pos": [ 420, 240 ], "size": [ 340, 220 ], "flags": {}, "order": 3, "mode": 0, "inputs": [ { "localized_name": "payload_string", "name": "payload_string", "type": "STRING", "shape": 7, "link": null }, { "localized_name": "any_input", "name": "any_input", "type": "*", "shape": 7, "link": 1 }, { "localized_name": "any_input_2", "name": "any_input_2", "type": "*", "shape": 7, "link": 3 }, { "localized_name": "any_input_3", "name": "any_input_3", "type": "*", "shape": 7, "link": 5 }, { "localized_name": "any_input_4", "name": "any_input_4", "type": "*", "shape": 7, "link": null }, { "localized_name": "cache_ttl_hours", "name": "cache_ttl_hours", "type": "FLOAT", "widget": { "name": "cache_ttl_hours" }, "shape": 7, "link": null } ], "outputs": [ { "localized_name": "cached_data", "name": "cached_data", "type": "*", "links": [ 8 ], "slot_index": 0 }, { "localized_name": "is_cached", "name": "is_cached", "type": "INT", "links": [ 7 ], "slot_index": 1 }, { "localized_name": "hash_key", "name": "hash_key", "type": "STRING", "links": [ 9 ], "slot_index": 2 } ], "properties": { "cnr_id": "comfyui-api-optimizer", "ver": "1.2.2", "Node name for S&R": "DeterministicHashVault", "aux_id": "jeremieLouvaert/ComfyUI-API-Optimizer" }, "widgets_values": [ 0.0 ] }, { "id": 6, "type": "GeminiStyleTransfer", "pos": [ 420, 500 ], "size": [ 380, 380 ], "flags": {}, "order": 4, "mode": 0, "inputs": [ { "localized_name": "image", "name": "image", "type": "IMAGE", "link": 2 }, { "localized_name": "style", "name": "style", "type": "COMBO", "widget": { "name": "style" }, "link": 4 }, { "localized_name": "intensity", "name": "intensity", "type": "COMBO", "widget": { "name": "intensity" }, "link": 6 }, { "localized_name": "model", "name": "model", "type": "COMBO", "widget": { "name": "model" }, "link": null }, { "localized_name": "seed", "name": "seed", "type": "INT", "widget": { "name": "seed" }, "link": null }, { "localized_name": "aspect_ratio", "name": "aspect_ratio", "type": "COMBO", "widget": { "name": "aspect_ratio" }, "link": null }, { "localized_name": "resolution", "name": "resolution", "type": "COMBO", "widget": { "name": "resolution" }, "link": null }, { "localized_name": "direction", "name": "direction", "type": "STRING", "widget": { "name": "direction" }, "shape": 7, "link": null }, { "localized_name": "api_key", "name": "api_key", "type": "STRING", "widget": { "name": "api_key" }, "shape": 7, "link": null } ], "outputs": [ { "localized_name": "image", "name": "image", "type": "IMAGE", "links": [ 10 ], "slot_index": 0 }, { "localized_name": "cost_info", "name": "cost_info", "type": "STRING", "links": [], "slot_index": 1 }, { "localized_name": "cache_key", "name": "cache_key", "type": "STRING", "links": [], "slot_index": 2 } ], "properties": { "cnr_id": "comfyui-gemini-direct", "ver": "1.1.0", "Node name for S&R": "GeminiStyleTransfer", "aux_id": "jeremieLouvaert/ComfyUI-Gemini-Direct" }, "widgets_values": [ "Saul Leiter / Intimate", "full", "gemini-3-pro-image-preview", 0, "auto", "2K", "", "" ] }, { "id": 7, "type": "HashVaultSave", "pos": [ 840, 500 ], "size": [ 300, 80 ], "flags": {}, "order": 5, "mode": 0, "inputs": [ { "localized_name": "hash_key", "name": "hash_key", "type": "STRING", "link": 9 }, { "localized_name": "api_output", "name": "api_output", "type": "*", "link": 10 } ], "outputs": [ { "localized_name": "api_output", "name": "api_output", "type": "*", "links": [ 11 ], "slot_index": 0 } ], "properties": { "cnr_id": "comfyui-api-optimizer", "ver": "1.2.2", "Node name for S&R": "HashVaultSave", "aux_id": "jeremieLouvaert/ComfyUI-API-Optimizer" }, "widgets_values": [] }, { "id": 8, "type": "LazyAPISwitch", "pos": [ 1180, 240 ], "size": [ 300, 120 ], "flags": {}, "order": 6, "mode": 0, "inputs": [ { "localized_name": "is_cached", "name": "is_cached", "type": "INT", "link": 7 }, { "localized_name": "cached_data", "name": "cached_data", "type": "*", "shape": 7, "link": 8 }, { "localized_name": "api_data", "name": "api_data", "type": "*", "shape": 7, "link": 11 } ], "outputs": [ { "localized_name": "final_output", "name": "final_output", "type": "*", "links": [ 12 ], "slot_index": 0 } ], "properties": { "cnr_id": "comfyui-api-optimizer", "ver": "1.2.2", "Node name for S&R": "LazyAPISwitch", "aux_id": "jeremieLouvaert/ComfyUI-API-Optimizer" }, "widgets_values": [] }, { "id": 9, "type": "PreviewImage", "pos": [ 1520, 240 ], "size": [ 420, 500 ], "flags": {}, "order": 7, "mode": 0, "inputs": [ { "localized_name": "images", "name": "images", "type": "IMAGE", "link": 12 } ], "outputs": [], "properties": { "cnr_id": "comfy-core", "ver": "0.18.1", "Node name for S&R": "PreviewImage" }, "widgets_values": [] } ], "links": [ [ 1, 2, 0, 5, 1, "IMAGE" ], [ 2, 2, 0, 6, 0, "IMAGE" ], [ 3, 3, 0, 5, 2, "STRING" ], [ 4, 3, 0, 6, 1, "STRING" ], [ 5, 3, 1, 5, 3, "STRING" ], [ 6, 3, 1, 6, 2, "STRING" ], [ 7, 5, 1, 8, 0, "INT" ], [ 8, 5, 0, 8, 1, "*" ], [ 9, 5, 2, 7, 0, "STRING" ], [ 10, 6, 0, 7, 1, "IMAGE" ], [ 11, 7, 0, 8, 2, "*" ], [ 12, 8, 0, 9, 0, "IMAGE" ] ], "groups": [], "config": {}, "extra": {}, "version": 0.4 }