Skip to content

Commit 1e93a94

Browse files
authored
Merge pull request #10 from commontoolsinc/2024-05-21-experiments
Graph serialization formats
2 parents 773b849 + 4d2f17e commit 1e93a94

File tree

132 files changed

+7162
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

132 files changed

+7162
-0
lines changed

static/frp-graph-04/apiKey.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
export function fetchApiKey() {
2+
let apiKey = localStorage.getItem("apiKey");
3+
4+
if (!apiKey) {
5+
// Prompt the user for the API key if it doesn't exist
6+
const userApiKey = prompt("Please enter your API key:");
7+
8+
if (userApiKey) {
9+
// Save the API key in localStorage
10+
localStorage.setItem("apiKey", userApiKey);
11+
apiKey = userApiKey;
12+
} else {
13+
// Handle the case when the user cancels or doesn't provide an API key
14+
alert("API key not provided. Some features may not work.");
15+
}
16+
}
17+
18+
return apiKey;
19+
}

static/frp-graph-04/connect.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import {
2+
distinctUntilChanged,
3+
share,
4+
tap,
5+
Subject,
6+
} from "https://cdn.jsdelivr.net/npm/rxjs@7.8.1/+esm";
7+
import { applyPolicy } from "./policy.js";
8+
9+
export function connect(output, input) {
10+
output
11+
.pipe(
12+
distinctUntilChanged(),
13+
applyPolicy(),
14+
tap((v) => input.next(v)),
15+
share(),
16+
)
17+
.subscribe();
18+
}
19+
20+
export function ground(output) {
21+
connect(output, new Subject());
22+
}

static/frp-graph-04/demo.js

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
const name$ = BehaviourNode("");
2+
const nameUi$ = GeneratedNameUI();
3+
const nameTagUi$ = GeneratedNameTagUI();
4+
const danger$ = DangerousUI();
5+
const cursor$ = Cursor();
6+
const combined$ = CombinedDataUI();
7+
const backstoryUi$ = GeneratedBackstoryUI();
8+
const portraitUi$ = PortraitUI();
9+
const statsUi$ = GeneratedStatsUI();
10+
11+
const character$ = combineLatest([
12+
nameUi$.out.name,
13+
statsUi$.out.str,
14+
statsUi$.out.dex,
15+
statsUi$.out.con,
16+
statsUi$.out.int,
17+
statsUi$.out.wis,
18+
statsUi$.out.cha,
19+
]);
20+
21+
const backstory$ = character$.pipe(
22+
filter(
23+
(v) =>
24+
v.name.length > 0 &&
25+
(v.stats.str > 0 ||
26+
v.stats.dex > 0 ||
27+
v.stats.con > 0 ||
28+
v.stats.int > 0 ||
29+
v.stats.wis > 0 ||
30+
v.stats.cha > 0),
31+
),
32+
debounceTime(1000),
33+
distinctUntilChanged(),
34+
switchMap((character) => {
35+
console.log("character", character);
36+
return from(
37+
doLLM(
38+
JSON.stringify(character),
39+
"Write a possible backstory for this fantasy character in 280 characters or less.",
40+
),
41+
);
42+
}),
43+
map(extractResponse),
44+
share(),
45+
);
46+
47+
const image$ = backstory$.pipe(
48+
debounceTime(1000),
49+
distinctUntilChanged(),
50+
switchMap((backstory) => {
51+
console.log("backstory", backstory);
52+
return from(
53+
generateImage(
54+
"Create a fantasy portrait of character based on this bio: " +
55+
backstory,
56+
),
57+
);
58+
}),
59+
share(),
60+
);
61+
62+
connect(name$.out.value, nameUi$.in.name);
63+
64+
connect(nameUi$.out.name, nameTagUi$.in.name);
65+
connect(nameUi$.out.name, nameTagUi$.in.render);
66+
connect(backstory$, backstoryUi$.in.backstory);
67+
connect(backstory$, backstoryUi$.in.render);
68+
connect(image$, portraitUi$.in.img);
69+
connect(image$, portraitUi$.in.render);
70+
71+
connect(character$, combined$.in.data);
72+
connect(character$, combined$.in.render);
73+
74+
ground(nameUi$.out.ui);
75+
ground(nameTagUi$.out.ui);
76+
ground(combined$.out.ui);
77+
ground(backstoryUi$.out.ui);
78+
ground(portraitUi$.out.ui);
79+
ground(statsUi$.out.ui);

static/frp-graph-04/graph.js

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
import {
2+
combineLatest,
3+
debounceTime,
4+
delay,
5+
distinctUntilChanged,
6+
filter,
7+
from,
8+
fromEvent,
9+
map,
10+
mergeMap,
11+
share,
12+
switchMap,
13+
tap,
14+
} from "https://cdn.jsdelivr.net/npm/rxjs@7.8.1/+esm";
15+
import { connect, ground } from "./connect.js";
16+
import { doLLM, extractResponse, generateImage } from "./llm.js";
17+
import { BehaviourNode } from "./nodes/BehaviourNode.js";
18+
import { CombinedDataUI } from "./nodes/CombinedDataUI.js";
19+
import { Cursor } from "./nodes/Cursor.js";
20+
import { DangerousUI } from "./nodes/DangerousUI.js";
21+
import { GeneratedBackstoryUI } from "./nodes/GeneratedBackstoryUI.js";
22+
import { GeneratedNameTagUI } from "./nodes/GeneratedNameTagUI.js";
23+
import { GeneratedNameUI } from "./nodes/GeneratedNameUI.js";
24+
import { PortraitUI } from "./nodes/PortraitUI.js";
25+
import { GeneratedStatsUI } from "./nodes/GeneratedStatsUI.js";
26+
27+
const startButton = document.getElementById("startWorkflow");
28+
29+
const name$ = BehaviourNode("");
30+
const nameUi$ = GeneratedNameUI();
31+
const nameTagUi$ = GeneratedNameTagUI();
32+
const danger$ = DangerousUI();
33+
const cursor$ = Cursor();
34+
const combined$ = CombinedDataUI();
35+
const backstoryUi$ = GeneratedBackstoryUI();
36+
const portraitUi$ = PortraitUI();
37+
const statsUi$ = GeneratedStatsUI();
38+
39+
const character$ = combineLatest([
40+
nameUi$.out.name,
41+
statsUi$.out.str,
42+
statsUi$.out.dex,
43+
statsUi$.out.con,
44+
statsUi$.out.int,
45+
statsUi$.out.wis,
46+
statsUi$.out.cha,
47+
]).pipe(
48+
map(([name, str, dex, con, int, wis, cha]) => ({
49+
name,
50+
stats: {
51+
str,
52+
dex,
53+
con,
54+
int,
55+
wis,
56+
cha,
57+
},
58+
})),
59+
);
60+
61+
const backstory$ = character$.pipe(
62+
filter(
63+
(v) =>
64+
v.name.length > 0 &&
65+
(v.stats.str > 0 ||
66+
v.stats.dex > 0 ||
67+
v.stats.con > 0 ||
68+
v.stats.int > 0 ||
69+
v.stats.wis > 0 ||
70+
v.stats.cha > 0),
71+
),
72+
debounceTime(1000),
73+
distinctUntilChanged(),
74+
switchMap((character) => {
75+
console.log("character", character);
76+
return from(
77+
doLLM(
78+
JSON.stringify(character),
79+
"Write a possible backstory for this fantasy character in 280 characters or less.",
80+
),
81+
);
82+
}),
83+
map(extractResponse),
84+
share(),
85+
);
86+
87+
const image$ = backstory$.pipe(
88+
debounceTime(1000),
89+
distinctUntilChanged(),
90+
switchMap((backstory) => {
91+
console.log("backstory", backstory);
92+
return from(
93+
generateImage(
94+
"Create a fantasy portrait of character based on this bio: " +
95+
backstory,
96+
),
97+
);
98+
}),
99+
share(),
100+
);
101+
102+
connect(name$.out.value, nameUi$.in.name);
103+
104+
connect(character$, combined$.in.data);
105+
connect(character$, combined$.in.render);
106+
107+
connect(nameUi$.out.name, nameTagUi$.in.name);
108+
connect(nameUi$.out.name, nameTagUi$.in.render);
109+
connect(backstory$, backstoryUi$.in.backstory);
110+
connect(backstory$, backstoryUi$.in.render);
111+
connect(image$, portraitUi$.in.img);
112+
connect(image$, portraitUi$.in.render);
113+
114+
ground(nameUi$.out.ui);
115+
ground(nameTagUi$.out.ui);
116+
ground(combined$.out.ui);
117+
// ground(danger$.out.ui);
118+
ground(backstoryUi$.out.ui);
119+
ground(portraitUi$.out.ui);
120+
ground(statsUi$.out.ui);
121+
122+
character$.subscribe(console.log);
123+
124+
ground(
125+
fromEvent(startButton, "click").pipe(
126+
tap(() => {
127+
// name$.in.value.next("Ben" + Math.floor(Math.random() * 1000));
128+
nameUi$.in.generate.next();
129+
nameTagUi$.in.generate.next();
130+
// danger$.in.generate.next();
131+
backstoryUi$.in.generate.next();
132+
statsUi$.in.generate.next();
133+
134+
cursor$.in.render.next();
135+
combined$.in.render.next();
136+
}),
137+
),
138+
);

static/frp-graph-04/imagine.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import {
2+
mergeMap,
3+
map,
4+
from,
5+
tap,
6+
} from "https://cdn.jsdelivr.net/npm/rxjs@7.8.1/+esm";
7+
import { doLLM, extractResponse, grabViewTemplate, uiPrompt } from "./llm.js";
8+
import { applyPolicy } from "./policy.js";
9+
import { render } from "./render.js";
10+
11+
export function placeholder(id) {
12+
return tap((description) => {
13+
render(id, `<div class="description">{{description}}</div>`, {
14+
description,
15+
});
16+
});
17+
}
18+
19+
export function imagine(id, prompt) {
20+
return (v) =>
21+
v.pipe(
22+
map(() => prompt),
23+
placeholder(id),
24+
mergeMap((description) =>
25+
from(doLLM(description + "Return only the code.", uiPrompt)),
26+
),
27+
map(extractResponse),
28+
map(grabViewTemplate),
29+
applyPolicy(),
30+
);
31+
}

static/frp-graph-04/index.html

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<!doctype html>
2+
<html>
3+
<head>
4+
<title>rxjs</title>
5+
</head>
6+
<style type="text/css">
7+
.debug {
8+
font-size: 8px;
9+
max-height: 128px;
10+
max-width: 50vw;
11+
overflow-y: auto;
12+
background-color: #f0f0f0;
13+
border: 1px solid #ccc;
14+
padding: 4px;
15+
border-radius: 4px;
16+
}
17+
18+
#workflow {
19+
display: flex;
20+
flex-direction: column;
21+
flex-wrap: wrap;
22+
gap: 8px;
23+
}
24+
25+
#workflow > * {
26+
border: 1px dashed #ccc;
27+
padding: 8px;
28+
}
29+
30+
.columns {
31+
display: flex;
32+
gap: 16px;
33+
}
34+
35+
.columns > * {
36+
flex: 1;
37+
}
38+
39+
.description {
40+
font-size: 10px;
41+
font-family: monospace;
42+
}
43+
</style>
44+
<body>
45+
<button id="initialRender">Initial Render</button>
46+
<button id="startWorkflow">Start Workflow</button>
47+
<div class="columns">
48+
<div id="workflow"></div>
49+
<div id="debug"></div>
50+
</div>
51+
52+
<script type="module">
53+
import "./graph.js";
54+
</script>
55+
</body>
56+
</html>

0 commit comments

Comments
 (0)