substrate-illustratedprimer.web.val.run
Readme

Generates a streaming illustrated primer on a subject. Enter a subject, click on titles to "delve".

🪩 To fork, sign up for Substrate to get your own API key and $50 free credits

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import wrapper from "https://esm.town/v/substrate/substrateBadgeMiddleware";
import { ComputeJSON, ComputeText, GenerateImage, sb, Substrate } from "npm:substrate";
import { z } from "npm:zod";
import { zodToJsonSchema } from "npm:zod-to-json-schema";
async function handler(req: Request): Promise<Response> {
const searchParams = new URL(req.url).searchParams;
const { prompt = "modernism" } = Object.fromEntries(searchParams);
// Substrate graph
const substrate = new Substrate({ apiKey: Deno.env.get("SUBSTRATE_API_KEY") });
const Topic = z
.object({
concepts: z.array(z.string()).min(2).max(2).describe(
"List of deeper concepts or ideas. Keep them short, less than 5 words.",
),
})
.describe("Deeper concepts or ideas related to a topic.");
const c1 = new ComputeJSON({
prompt: `List deeper concepts or ideas related to: ${prompt}`,
json_schema: zodToJsonSchema(Topic),
});
const prompt1 = new ComputeText({
prompt: sb.interpolate`generate a description of an image of ${
c1.future.json_object.get("concepts").at(0)
}. Be concise and terse. Include details on the background, angle & framing, and style.`,
});
const prompt2 = new ComputeText({
prompt: sb.interpolate`generate a description of an image of ${
c1.future.json_object.get("concepts").at(1)
}. Be concise and terse. Include details on the background, angle & framing, and style.`,
});
const caption1 = new ComputeText({
prompt: sb.interpolate`write a short paragraph relating ${
c1.future.json_object.get("concepts").at(0)
} to ${prompt}`,
});
const caption2 = new ComputeText({
prompt: sb.interpolate`write a short paragraph relating ${
c1.future.json_object.get("concepts").at(1)
} to ${prompt}. It should be meaningfully different from the following content:
${caption1.future.text}`,
}, { cache_age: 800 });
const image1 = new GenerateImage({ prompt: prompt1.future.text });
const image2 = new GenerateImage({ prompt: prompt2.future.text });
const c2 = new ComputeJSON({
prompt: sb.interpolate`List deeper concepts or ideas related to: ${c1.future.json_object.get("concepts").at(0)}
The items must NOT be in this list:[${c1.future.json_object.get("concepts").at(0)}, ${
c1.future.json_object.get("concepts").at(1)
}]`,
json_schema: zodToJsonSchema(Topic),
});
const prompt3 = new ComputeText({
prompt: sb.interpolate`generate a description of an image of ${
c2.future.json_object.get("concepts").at(0)
}. Be creative depicting abstract topics with extra detail. Include details on the background, angle & framing, and style.`,
});
const prompt4 = new ComputeText({
prompt: sb.interpolate`generate a description of an image of ${
c2.future.json_object.get("concepts").at(1)
}. Be creative depicting abstract topics with extra detail. Include details on the background, angle & framing, and style.`,
});
const caption3 = new ComputeText({
prompt: sb.interpolate`write a short paragraph relating ${
c2.future.json_object.get("concepts").at(0)
} to ${prompt}. It should be meaningfully different from the following content:
${caption1.future.text}
${caption2.future.text}`,
});
const caption4 = new ComputeText({
prompt: sb.interpolate`write a short paragraph relating ${
c2.future.json_object.get("concepts").at(1)
} to ${prompt}. It should be meaninfully different from the following content:
${caption1.future.text}
${caption2.future.text}
${caption3.future.text}`,
});
const image3 = new GenerateImage({ prompt: prompt3.future.text });
const image4 = new GenerateImage({ prompt: prompt4.future.text });
const nodes = [image1, caption1, image2, caption2, image3, caption3, image4, caption4];
const stream = await substrate.stream(...nodes);
// UI
const capitalize = s => s.replace(/^\w/, c => c.toUpperCase());
return new Response(
new ReadableStream({
async start(controller) {
const pairs = [
{ image: null, caption: null, title: null },
{ image: null, caption: null, title: null },
{ image: null, caption: null, title: null },
{ image: null, caption: null, title: null },
];
const outputPair = (pair, index) => {
if (pair.image && pair.caption) {
controller.enqueue(new TextEncoder().encode(
`<div style="display:flex;justify-content:center;align-items:center;margin-bottom:20px;">
<div style="margin:0 10px;">${pair.image}</div>
Only the latest version can be previewed
Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
Comments
Nobody has commented on this val yet: be the first!
v41
July 13, 2024