Overview
Using futures
֍
Learn how to connect nodes using futures

When we connect two nodes using Substrate, we use a future reference from the first node as an input to the second node. Often, we'll need to transform these future references – for example, to use the output of a node as part of a subsequent prompt. For most transformations, you can use Substrate's built-in sb functions.

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 a list of future and static strings.

Python
TypeScript

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

In TypeScript, you can use sb.interpolate:

TypeScript

const story = new ComputeText({ prompt: "tell me a short story" });
const summary = new ComputeText({
prompt: sb.interpolate`summarize: ${story.future.text}`,
});

In Python, you can use sb.format, or sb.jinja. Jinja is a powerful tool for building prompt templates, with support for filters (opens in a new tab), conditionals (opens in a new tab), and comments (opens in a new tab).

sb.format
sb.jinja

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

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