Back to packages list

Vals using lodash

Description from the NPM package:
Lodash modular utilities.

The beginnings of a val town implementation of the approach to declarative sqlite migrations laid out in this post: Simple declarative schema migration for SQLite

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
import { createSqlite } from "https://esm.town/v/postpostscript/sqliteWasm?v=148";
import { sqlite } from "https://esm.town/v/std/sqlite?v=6";
import _ from "npm:lodash";
// The schema that we want to end up with
const schema = `
create table sales (product TEXT, year INTEGER, income INTEGER, type TEXT);
create table inventory (product TEXT, count INTEGER);
`;
// Create a new db and create the "pristine" tables from the schema above
const pristine = createSqlite();
await pristine.batch(schema.trim().split("\n"));
// Create an object that contains the table names and sql of our target state
const pristineTables = Object.fromEntries(
(await pristine.execute(`SELECT name, sql FROM sqlite_schema
WHERE type = 'table' AND name != 'sqlite_sequence'`)).rows as unknown as string[][],
);
// Create an object that gets the names and sql for the tables in our current db state
const currentTables = Object.fromEntries(
(await sqlite.execute(`SELECT name, sql FROM sqlite_schema
WHERE type = 'table' AND name != 'sqlite_sequence'`)).rows as unknown as string[][],
);
// Figure out which tables are changed and which tables are new
const newTables = _.difference(_.keys(pristineTables), _.keys(currentTables));
const changedTables = _.intersection(_.keys(pristineTables), _.keys(currentTables));
// Log the create statement for the new tables
for (const table of newTables) {
const createTableSql = pristineTables[table];
console.log(createTableSql);
}
// Log the create statement for the changed table with the suffix _new
for (const table of changedTables) {
const regex = new RegExp(` ${table} `);
const createTableSql = pristineTables[table].replace(regex, ` ${table}_new `);
console.log(createTableSql);
}
1
2
3
4
5
6
7
export const toArrayExample = (async () => {
const { default: _ } = await import("npm:lodash");
return [
_.toArray("hi 🇺🇸").join(", "),
_.toArray("hi 🏴󠁧󠁢󠁳󠁣󠁴󠁿").join(", "),
];
})();
1
2
3
4
export async function shuffle(a) {
const { default: shuffle } = await import("npm:lodash");
return shuffle(a);
}
1
2
3
4
5
6
export async function assert(a, b, message?: string) {
const { default: { isEqual } } = await import("npm:lodash");
if (!isEqual(a, b)) {
throw new Error("Assert failed! " + (message ?? ""));
}
}
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
import { openaiChatCompletion } from "https://esm.town/v/andreterron/openaiChatCompletion";
export const generateValCode = async (
key: string,
description: string,
org?: string,
) => {
const SYSTEM_MESSAGE = `You are a coding assistant.
The user will give you a description of the code they want, and you should immediatelly start writing code, don't add any description before or after.
Write the code in JavaScript, and if you need imports, use dynamic imports, and for npm, prefix the package with \`npm:\`. Example:
\`\`\`javascript
const lodash = await import('npm:lodash');
\`\`\`
`;
const response = await openaiChatCompletion({
openaiKey: key,
organization: org,
body: {
model: "gpt-3.5-turbo",
messages: [
{ role: "system", content: SYSTEM_MESSAGE },
{
role: "user",
content: `Here's the description of the function I want to write:
${description}
Please start writing the function now, and just write the function, no console.log required:
`,
},
],
},
});
const message: string = response.choices[0].message.content;
const codeBlockStart = message.indexOf("```");
const codeBlockEnd = message.indexOf("```", codeBlockStart + 3);
const code = message
.slice(
Math.max(0, codeBlockStart),
codeBlockEnd === -1 ? message.length : codeBlockEnd + 3,
)
.trim()
.replace(/^```[a-zA-Z0-9]*\n/, "")
.replace(/```$/, "")
.trim();
return code;
};

ChatGPT Plugin for Val Town

Run code on Val Town from ChatGPT.

Usage

I haven't been able to get it to do very useful things yet. It certainly can evaluate simple JS code:

It would be awesome if it knew how to use other APIs and make fetch calls to them, but it has been failing at that.

Limitations

This plugin currently only has unauthenticated access to POST /v1/eval, which basically means that all it can do is evaluate JavaScript or TypeScript.

In theory it could refer to any existing vals in Val Town, but it wouldn't know about those unless you told it.

Future directions

Once we have more robust APIs to search for existing vals, this plugin could be WAY more valuable! In theory GPT4 could first search for vals to do a certain task and then if it finds one it could then write code based on that val. In practice however, that might require too many steps for poor GPT. We might need to use some sort of agent or langchain thing if we wanted that sort of behavior.

Adding authentication could also enable it to make requests using your secrets and private vals and create new vals for you. However I am dubious that this would actually be practically useful.

Installation

  1. Select GPT-4 (requires ChatGPT Plus)
  2. Click No plugins enabled

  1. Click "Install an unverified plugin" or "Develop your own plugin" (I'm not sure the difference)

  1. Paste in this val's express endpoint

https://stevekrouse-chatGPTPlugin.express.val.run
  1. Click through the prompts until it's installed
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
import { fetchJSON } from "https://esm.town/v/stevekrouse/fetchJSON";
import { openaiOpenAPI } from "https://esm.town/v/stevekrouse/openaiOpenAPI";
// https://stevekrouse-chatgptplugin.express.val.run/.well-known/ai-plugin.json
export async function chatGPTPlugin(req: express.Request, res: express.Response) {
if (req.path === "/.well-known/ai-plugin.json") {
res.json({
"schema_version": "v1",
"name_for_human": "Val Town",
"name_for_model": "val_town",
"description_for_human": "Run JavaScript or TypeScript on Val Town",
"description_for_model": `Val Town is a social programming environment.
Vals are JavaScript & TypeScript code.
They run server-side on Deno.
\`fetch\` is in the environment to access any PUBLIC real-time APIs or data feeds.
Answer any questions about times after your cut off date by querying PUBLIC APIs.
Do NOT use any API that requires a secret key.
Only use PUBLIC APIs.
Do NOT use \`YOUR_API_KEY\`.
Do NOT import axios or node-fetch. Instead use \`fetch\`.
Do NOT use newlines. Just use semicolons.
You can import libraries from npm: \`const {default: _} = await import("npm:lodash")\`
You MUST \`return\` the final value of the computation that you want.`,
"auth": {
"type": "none",
},
"api": {
"type": "openapi",
"url": "/openapi",
},
"logo_url":
"https://www.val.town/build/_assets/vt-whiteOnBlack-HPPYQAQ6.png",
"contact_email": "steve@val.town",
"legal_info_url": "https://val.town",
});
}
else if (req.path === "/openapi") {
// OpenAPI Spec
// only POST /v1/eval for now
res.send(openaiOpenAPI);
}
else if (req.path === "/v1/eval") {
// Proxy /v1/eval to api.val.town
try {
console.log(req.body);
let result = await fetchJSON(
"https://api.val.town/v1/eval",
{ method: "POST", body: JSON.stringify(req.body) },
);
console.log(result);
res.json(result);
}
catch (e) {
console.log("Error in evaluating " + e.message);
console.log(e.stack);
}
}
else {
console.error("Unknown path: " + req.path);
res.status(404).end();
}
}
1
export const _ = import("npm:lodash");
1
2
3
4
export const npmDefaultErrorExample = (async () => {
const _ = await import("npm:lodash");
return _.partition([1, 2, 3, 4], (n) => n % 2);
})();
1
2
3
4
export const npmDefaultExample = (async () => {
const { default: _ } = await import("npm:lodash");
return _.partition([1, 2, 3, 4], (n) => n % 2);
})();
1
2
3
4
export const importSSSS = (async () => {
const { default: _ } = await import("npm:lodash");
return _.groupBy([{ a: 1 }, { a: 2 }], "a");
})();
1
2
3
import lodash from "npm:lodash";
export const _ = lodash;
1
Next