Overview
Connect nodes
֍
Learn how to connect nodes using futures

Substrate requires connecting nodes before running them. When we connect two nodes, we use a future reference from the first node as an input to the second node.

Operators from the sb submodule are used to transform future values. Common transforms are included, and most other transforms can be expressed using jq (opens in a new tab), a powerful language for manipulating JSON data.

See also

  • Use Box to combine outputs into a single node
  • Use If to return one of two options based on a condition
  • Use RunPython to transform outputs with custom code

Joining strings

Use sb.concat to join future and static strings.

Python
TypeScript

story = ComputeText(prompt="tell me a short story")
summary = ComputeText(prompt=sb.concat("summarize: ", story.future.text))

To join strings using a template, use sb.jinja in Python, or sb.interpolate in TypeScript.

Python
TypeScript

story = ComputeText(prompt="tell me a short story")
summary = ComputeText(
prompt=sb.jinja("summarize: {{story.future.text}}", {"story": story}),
)

Future dictionary values

  • In Python, simply use brackets as usual.
  • In TypeScript, use .get() to reference untyped future object values.
Python
TypeScript

author = ComputeJSON(
prompt="Who wrote Don Quixote?",
json_schema={
"type": "object",
"properties": {
"author": {
"type": "string",
"description": "The name of the author.",
},
},
},
)
summary = ComputeText(
prompt=sb.concat(
"Write a haiku describing ",
author.future.json_object["author"]),
),
)

Future array items

  • In Python, simply use brackets as usual.
  • In TypeScript, use .at() to index future arrays.
Python
TypeScript

story = MultiComputeText(prompt="tell me a short story", num_choices=2)
summary = ComputeText(
prompt=sb.concat("summarize: ", story.future.choices[0].text),
)

Parsing strings

Use sb.jq to parse strings before passing them to other nodes.

Python
TypeScript

name = ComputeText(
prompt="Give me a unique startup name inside <name></name> tags. Example: <name>Hyphae</name><description>A startup that ... </description>",
)
haiku = ComputeText(
prompt=sb.concat(
"Write a haiku describing a startup named: ",
sb.jq(
name.future.text,
'ascii_downcase | split("<name>") | .[1] | split("</name>") | .[0]',
),
),
)

Learn more

The jq pipeline above is an example of what's possible using the jq language (opens in a new tab).

  • jq takes any JSON value as input and produces a JSON value as output. JSON values include dictionaries, arrays, strings, numbers, and booleans.
  • The . dot syntax can be used to filter by a data path: .[0].text
  • The | pipe operator is used to chain together jq expressions.

In this jq example, we're downcasing (opens in a new tab) the string, splitting (opens in a new tab) by the opening <name> tag, indexing (opens in a new tab) the second item in the resulting array, splitting by the closing </name> tag, and finally returning the first value in the resulting array:

  • ascii_downcase | split("<name>") | .[1] | split("</name>") | .[0]

Alternatively, you can use jq's capture (opens in a new tab) function with a regular expression:

  • capture("<name>(?<content>.*?)</name>") | .content