← All ivy-nodes
IVYXSTUDIO · IVY NODE
T
Template Render
ivy.node.template-render · v0.1.0
ivyx✓
Fills {{ name }} placeholders in a text template from a mapping, and reports which names were missing. Substitution is textual, never evaluated, so a template that arrives from a model or a file cannot run code. Generalises the hand-written prompt-creator nodes; pure compute with no network or file access.
#template#prompt#text
Inputs
| Field | Type | Description |
|---|---|---|
| templaterequired | string | Text with {{ name }} placeholders. Dotted names read nested values. |
| values | object | The mapping the placeholders are filled from. |
| on_missing | string | What a missing name does: error, empty or keep. |
Outputs
| Field | Type | Description |
|---|---|---|
| textrequired | string | The filled template. |
| missingrequired | array | Placeholder names that had no value, sorted and deduplicated. |
Source
python
# Input preparation
inp = __ivy_ctx__["nodes"][__ivy_node_id__]["input"]
template = inp["template"]
values = inp.get("values") or {}
on_missing = inp.get("on_missing", "error")
# Compute
import re
PLACEHOLDER = re.compile(r"\{\{\s*([A-Za-z_][A-Za-z0-9_.]*)\s*\}\}")
def resolve(values, dotted):
"""Walk a dotted name through nested dicts. Absent yields None, False."""
node = values
for part in dotted.split("."):
if not isinstance(node, dict) or part not in node:
return None, False
node = node[part]
return node, True
def render(template, values, on_missing="error"):
"""
Fill {{ name }} placeholders from a mapping.
Deliberately not `str.format` and not an f-string: both execute parts of
the template, so a template that arrives from a model or a file becomes a
way to run code. This substitutes text and nothing else.
`on_missing` is the whole of the policy about a name that is not there —
`error` refuses, `empty` writes nothing, `keep` leaves the placeholder
visible so the gap is obvious downstream. There is no silent default,
because a half-filled prompt that looks finished is the failure this node
exists to prevent.
"""
if not isinstance(template, str):
raise ValueError("template must be a string")
if on_missing not in ("error", "empty", "keep"):
raise ValueError("on_missing must be one of error, empty, keep")
missing = []
def substitute(match):
name = match.group(1)
value, found = resolve(values, name)
if found:
return "" if value is None else str(value)
missing.append(name)
if on_missing == "keep":
return match.group(0)
return ""
text = PLACEHOLDER.sub(substitute, template)
if missing and on_missing == "error":
raise ValueError("missing value for: " + ", ".join(sorted(set(missing))))
return text, sorted(set(missing))
rendered, missing_names = render(template, values, on_missing)
# Output collection (runner reads __ivy_ctx__)
out = __ivy_ctx__["nodes"][__ivy_node_id__]["output"]
out["text"] = rendered
out["missing"] = missing_namesTests
Requires: python:3.9
- fills-and-nests
A flat name and a dotted name are both filled from the mapping.
- keeps-the-gap-visible
With on_missing keep, an unfilled placeholder stays in the text and is reported.
- no-code-execution
Braces that look like format syntax are left alone: the template is not evaluated.
- missing-is-an-error-by-default
By default a missing name refuses rather than producing a half-filled prompt.