1import wrapper from "https://esm.town/v/substrate/substrateBadgeMiddleware";
2import { ComputeJSON, ComputeText, GenerateImage, sb, Substrate } from "npm:substrate";
3import { z } from "npm:zod";
4import { zodToJsonSchema } from "npm:zod-to-json-schema";
23 });
24 const prompt1 = new ComputeText({
25 prompt: sb.interpolate`generate a description of an image of ${
26 c1.future.json_object.get("concepts").at(0)
27 }. Be concise and terse. Include details on the background, angle & framing, and style.`,
28 });
29 const prompt2 = new ComputeText({
30 prompt: sb.interpolate`generate a description of an image of ${
31 c1.future.json_object.get("concepts").at(1)
32 }. Be concise and terse. Include details on the background, angle & framing, and style.`,
43 ${caption1.future.text}`,
44 }, { cache_age: 800 });
45 const image1 = new GenerateImage({ prompt: prompt1.future.text });
46 const image2 = new GenerateImage({ prompt: prompt2.future.text });
47 const c2 = new ComputeJSON({
48 prompt: sb.interpolate`List deeper concepts or ideas related to: ${c1.future.json_object.get("concepts").at(0)}
53 });
54 const prompt3 = new ComputeText({
55 prompt: sb.interpolate`generate a description of an image of ${
56 c2.future.json_object.get("concepts").at(0)
57 }. Be creative depicting abstract topics with extra detail. Include details on the background, angle & framing, and style.`,
58 });
59 const prompt4 = new ComputeText({
60 prompt: sb.interpolate`generate a description of an image of ${
61 c2.future.json_object.get("concepts").at(1)
62 }. Be creative depicting abstract topics with extra detail. Include details on the background, angle & framing, and style.`,
77 ${caption3.future.text}`,
78 });
79 const image3 = new GenerateImage({ prompt: prompt3.future.text });
80 const image4 = new GenerateImage({ prompt: prompt4.future.text });
81 const nodes = [image1, caption1, image2, caption2, image3, caption3, image4, caption4];
82 const stream = await substrate.stream(...nodes);
83
88 async start(controller) {
89 const pairs = [
90 { image: null, caption: null, title: null },
91 { image: null, caption: null, title: null },
92 { image: null, caption: null, title: null },
93 { image: null, caption: null, title: null },
94 ];
95
96 const outputPair = (pair, index) => {
97 if (pair.image && pair.caption) {
98 controller.enqueue(new TextEncoder().encode(
99 `<div style="display:flex;justify-content:center;align-items:center;margin-bottom:20px;">
100 <div style="margin:0 10px;">${pair.image}</div>
101 <div style="margin:0 10px;font-size:1.2rem;">
102 <a href="/?subject=${pair.title}"><b>${capitalize(pair.title)}</b></a><br/>${pair.caption}</div>
103</div>`,
104 ));
105 pairs[index] = { image: null, caption: null, title: null }; // Reset after output
106 }
107 };
152 if (index !== -1) {
153 const pairIndex = Math.floor(index / 2);
154 const isImage = index % 2 === 0;
155 const content = event.data.image_uri
156 ? `<img src="${event.data.image_uri}" width=400/>`
157 : `<div>${event.data.text}</div>`;
158
159 if (isImage) {
160 pairs[pairIndex].image = content;
161 } else {
162 pairs[pairIndex].caption = content;