Public
Edited
Nov 8, 2023
Insert cell
Insert cell
Insert cell
example_markdown2 = ({
prompt: "Write an example markdown cell with two sentences separated by a space of one line.",
time: 1699221659348,
comment: "Example of a markdown cell"
} &&
md` This is a markdown cell. You can use **bold**, _italic_, and [links](http://example.com).`)
Insert cell
example_markdown = ({
prompt: "Write an example markdown cell",
time: 1699221659348,
comment: "Example of a markdown cell"
} &&
md` This is a markdown cell. You can use **bold**, _italic_, and [links](http://example.com).`)
Insert cell
hexbin_heatmap = ({
prompt:
'Create a Hexbin heatmap of Olympic athletes aaccording to their weight and height which are filled with a color that encodes frequency. Use the inbuilt dataset "olympians" variable',
time: 1699296536008,
comment:
"Create a Hexbin heatmap of Olympic athletes according to their weight and height filled with a color that encodes frequency."
} &&
Plot.dot(
olympians,
Plot.hexbin({ fill: "count" }, { x: "weight", y: "height" })
).plot({ color: { scheme: "YlGnBu" } }))
Insert cell
blob_url = ({
prompt: "convert the hexbin_heatmap SVGElement to blob URL ",
time: 1699302857881,
comment: "Convert the hexbin_heatmap SVGElement to blob URL"
} &&
URL.createObjectURL(
new Blob([new XMLSerializer().serializeToString(hexbin_heatmap)], {
type: "image/svg+xml"
})
))
Insert cell
viewof form = ({
prompt:
'use the already imported view literal to make reactive form which has\n\n2 tabs name "first", "second", which switch between two text areas called "a", "b" with placehoders "A", "B" and a single "submit" button at the bottom. Pressing submit should update the cell bound to the form. The result should be an object shaped {a:..., b:...} where the values map to the text area values.\n',
time: 1699298358615,
comment:
"Create a reactive form with two tabs 'first' and 'second' switching between two text areas 'a' and 'b' with placeholders 'A' and 'B' and a submit button. On submit, it updates the cell bound to the form. The result will be an object shaped {a:..., b:...} where the values map to the text area values."
} &&
cautious(
(apply, reset) => view`
<input type="radio" name="tab" checked onclick=${() => {
document.getElementById("firstContent").style.display = "block";
document.getElementById("secondContent").style.display = "none";
}}>
<label for="first">First</label>
<input type="radio" name="tab" onclick=${() => {
document.getElementById("firstContent").style.display = "none";
document.getElementById("secondContent").style.display = "block";
}}>
<label for="second">Second</label>
<br>
<div id="firstContent">
${["a", Inputs.textarea({ placeholder: "A" })]}
</div>
<div id="secondContent" style="display: none;">
${["b", Inputs.textarea({ placeholder: "B" })]}
</div>
<br>
<button onClick=${apply}>Submit</button>`
))
Insert cell
form
Insert cell
THREE = ({
prompt: "Import threeJS with orbit controls as THREE",
time: 1699299731104,
comment: "Importing three.js with orbit controls as three"
} &&
Promise.all([
import("https://esm.sh/three"),
import("https://esm.sh/three/examples/jsm/controls/OrbitControls.js")
]).then(([THREE, { OrbitControls }]) => ({ ...THREE, OrbitControls })))
Insert cell
demo_scene = {
({
prompt: "create a THREE cool demo scene using blob_url as a texture",
time: 1699303031445,
comment:
"Creating a 3D scene with a rotating cube using three.js. The cube is textured with the blob URL of the hexbin heatmap SVG."
});
const height = 500;
// Create a scene
const scene = new THREE.Scene();

// Create a camera
const camera = new THREE.PerspectiveCamera(15, width / height, 0.1, 1000);
camera.position.z = 5;

// Create a renderer
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(width, height);

// Create a cube
const geometry = new THREE.BoxGeometry(1, 1, 1);
const loader = new THREE.TextureLoader();
const material = new THREE.MeshBasicMaterial({ map: loader.load(blob_url) });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);

// Create an animation loop
const animate = () => {
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
requestAnimationFrame(animate);
};
animate();

// Enable orbit controls
const controls = new THREE.OrbitControls(camera, renderer.domElement);

return renderer.domElement;
}
Insert cell
relativity_derivation = ({
prompt:
"Using the tex literal (KaTeX) intermingled with markdown, write a derivation of relativity.",
time: 1699388874563,
comment: "Derivation of relativity equation using KaTeX and markdown"
} &&
md`The derivation of the relativity equation starts from the principle of relativity, which states that the laws of physics are the same in all inertial frames of reference.

From this principle, we derive the Lorentz transformation, which describes how measurements of space and time by two observers moving relative to each other are related. The Lorentz transformation in one dimension is:

${tex`
\begin{aligned}
x' &= \gamma (x - vt) \\
t' &= \gamma \left(t - \frac{vx}{c^2}\right)
\end{aligned}
`}

where:

- ${tex`x'`} and ${tex`t'`} are the space and time coordinates measured by the observer moving with velocity ${tex`v`},
- ${tex`x`} and ${tex`t`} are the space and time coordinates measured by the observer at rest,
- ${tex`gamma = \frac{1}{\sqrt{1 - v^2/c^2}}`} is the Lorentz factor, and
- ${tex`c`} is the speed of light.

From the Lorentz transformation, we can derive the famous equation of special relativity, which states that energy is equivalent to mass times the speed of light squared:

${tex`E = mc^2`}
`)
Insert cell
pong_game = {
({
prompt: "Create an automated retro looking game of pong",
time: 1699389743848,
comment: "Creating an automated retro-looking game of Pong"
});

const canvas = document.createElement("canvas");
canvas.width = width;
canvas.height = 200;
const context = canvas.getContext("2d");

const ball = { x: width / 2, y: 20, dx: 3, dy: 2, radius: 15 };
const paddle = { x: 5, y: canvas.height / 2, width: 20, height: 60 };

const drawBall = () => {
context.beginPath();
context.rect(
ball.x,
ball.y - ball.radius,
ball.radius * 2,
ball.radius * 2
);
context.fillStyle = "#FFFFFF";
context.fill();
context.closePath();
};

const drawPaddle = () => {
context.beginPath();
context.rect(paddle.x, paddle.y, paddle.width, paddle.height);
context.fillStyle = "#FFFFFF";
context.fill();
context.closePath();
};

const update = () => {
context.fillStyle = "#000000";
context.fillRect(0, 0, canvas.width, canvas.height);
drawBall();
drawPaddle();

if (
ball.x + ball.dx > canvas.width - ball.radius ||
ball.x + ball.dx < ball.radius + 10
) {
ball.dx = -ball.dx;
}

if (ball.y + ball.dy < ball.radius) {
ball.dy = -ball.dy;
} else if (ball.y + ball.dy > canvas.height - ball.radius) {
if (ball.x > paddle.x && ball.x < paddle.x + paddle.width) {
ball.dy = -ball.dy;
} else {
ball.dy = -ball.dy;
}
}
ball.x += ball.dx;
ball.y += ball.dy;
paddle.y = ball.y - 30;
};

const interval = setInterval(update, 10);

return canvas;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
ndd = _ndd
Insert cell
formatted_instruction = {
if (response.action == "upsert_cell") {
let code = undefined;
const prompt = {
prompt: response.prompt,
time: response.time,
comment: response.comment
};
if (response.code.trim().startsWith("{")) {
code = `{ (${JSON.stringify(prompt)})\n${response.code.trim().slice(1)}`;
} else {
code = `(${JSON.stringify(prompt)}) && ${response.code}`;
}
return `${response.cell_name} = ${code}`;
}
return response.content;
}
Insert cell
response = on_prompt
Insert cell
on_prompt = {
return viewof ask.send([
...mutable context,
{
role: "user",
content: feedback_prompt + prompt
}
]);
}
Insert cell
mutable context = undefined
Insert cell
update_context = {
const context = cells
.filter((c) => c.prompt)
.sort((a, b) => a.time - b.time)
.flatMap((c) => [
{
role: "user",
content: c.prompt
},
{
role: "assistant",
content: null,
function_call: {
name: "upsert_cell",
arguments: JSON.stringify({
cell_name: c.cell_name,
code: c.code,
comment: c.comment
})
}
}
]);
if (!_.isEqual(mutable context, context)) {
mutable context = context;
}
}
Insert cell
Insert cell
Insert cell
observableDefinitionToCode = (source) => {
try {
const defn = "(" + source + ")";
const ast = acorn.parse(defn);
const functionExpression = ast.body[0].expression;
if (functionExpression.type !== "FunctionExpression")
throw functionExpression;
const block = defn.slice(
functionExpression.body.start,
functionExpression.body.end
);

const exprMatch = /{return\(\n([\s\S]*)\n\)}$/.exec(block);
if (exprMatch) return exprMatch[1].trim();
else return block;
} catch (e) {
return undefined;
}
}
Insert cell
Insert cell
Insert cell
Insert cell
excludes = [
"viewof feedback_cells_selector",
"feedback_cells_selector",
"feedback_cells",
"feedback_prompt",
"find_prompt",
"viewof feedback_cells",
"null",
"viewof reset",
"reset",
"viewof prompt",
"prompt",
"suggestion",
"initial last_salient_summary",
"mutable last_salient_summary",
"initial context",
"mutable context",
"observableDefinitionToCode",
"viewof model",
"model",
"viewof OPENAI_API_KEY",
"OPENAI_API_KEY",
"settings",
"system_prompt",
"functions",
"viewof history",
"history",
"viewof ask",
"ask",
"openAiResponse",
"instruction",
"acorn",
"inspect",
"dirty_json",
"parseJSON",
"update_context",
"viewof suggestion",
"formatted_instruction",
"response",
"on_prompt",
"viewof context_viz",
"context_viz",
"context",
"code",
"cells",
"events",
"viz",
"vizUpdater",
"ndd",
"_ndd",
"excludes",
"_events",
"variables",
"_mainVariables",
"on_salient_event"
]
Insert cell
import {
_ndd,
events as _events, // Important to alias to avoid self-triggering loops when visualizing
mainVariables as _mainVariables
} with { excludes as excludes } from "@tomlarkworthy/ndd"
Insert cell
functions = [
{
name: "upsert_cell",
description: "Upsert a cell in notebook",
parameters: {
type: "object",
properties: {
cell_name: {
type: "string",
description: "Name of cell to add"
},
code: {
type: "string",
description: "Single expression or code block"
},
comment: {
type: "string",
description: "Explaination for code"
}
},
required: ["cell_name", "code", "comment"]
}
},
{
name: "wait",
description: "Wait for next user instruction",
parameters: { type: "object", properties: {} }
}
]
Insert cell
viewof history = Inputs.input([])
Insert cell
viewof ask = flowQueue({ timeout_ms: 60000 })
Insert cell
ask
Insert cell
openAiResponse = {
const response = await fetch("https://api.openai.com/v1/chat/completions", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${OPENAI_API_KEY}`
},
body: JSON.stringify({
functions: functions,
function_call: { name: "upsert_cell" },
messages: [
{
role: "system",
content: system_prompt
},
...ask
],
...viewof settings.value
})
});

if (response.status !== 200)
throw new Error(`${response.status}: ${await response.text()}`);

return response.json();
}
Insert cell
parseJSON(openAiResponse.choices[0].message.function_call.arguments)
Insert cell
instruction = {
const message = openAiResponse.choices[0].message;
if (message.function_call === undefined)
return {
action: "reply",
content: message.content
};
return {
...parseJSON(message.function_call.arguments),
prompt: ask[ask.length - 1].content,
action: message.function_call.name,
time: Date.now()
};
}
Insert cell
viewof ask.resolve(instruction)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more