Skip to content

Commit

Permalink
feat: OpenAI API
Browse files Browse the repository at this point in the history
- Added DALL-E and ChatGPT features to web socket server
  • Loading branch information
jasonjgardner committed Apr 23, 2023
1 parent 163e77b commit 36a3c47
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 3 deletions.
3 changes: 2 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ RP_PACK_UUID=68a061ba-18fc-4930-a56a-1da78742daa1
RP_MODULE_UUID=ad91326d-3455-4ea2-b12d-9e49591fa1f2
BP_PACK_UUID=eefdf10b-b20b-4580-8515-d6a2c35db762
BP_MODULE_UUID=a684c1d3-ad02-4ddb-9241-cfd132b79621
GITHUB_ACTION_REPOSITORY=jasonjgardner/minecraft-rtx-rainbow
GITHUB_ACTION_REPOSITORY=jasonjgardner/minecraft-rtx-rainbow
OPENAI_API_KEY=
66 changes: 66 additions & 0 deletions src/functions/chatgpt.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { load } from "https://deno.land/std@0.184.0/dotenv/mod.ts";
import openai from "npm:openai@^3.2.1";
import { Image } from "imagescript/mod.ts";
import type { Axis, WssParams } from "../../typings/types.ts";
import { convertImage } from "../components/ImagePrinter.ts";
import assemble from "../components/_assemble.ts";
import { join } from "path/mod.ts";

const { Configuration, OpenAIApi } = openai;

const env = await load();
const OPENAI_API_KEY = env.OPENAI_API_KEY || Deno.env.get("OPENAI_API_KEY") ||
"";

const SYSTEM_PROMPT = "Act as a Minecraft Bedrock add-on creator. " +
"You will be asked to create commands, functions, and structures for a Minecraft Bedrock Edition add-on. " +
"You will provide responses in the form of a Minecraft command. " +
"Reply with the solutions only, no explanations.";
const getRandomPrompt = () => {
const prompts = [
"Summon a zombie",
"Play a prank on nearby players",
"Teleport a player to a random location",
];

return prompts[Math.floor(Math.random() * prompts.length)];
};

const configuration = new Configuration({
apiKey: OPENAI_API_KEY,
});

const client = new OpenAIApi(configuration);

export default async function chatgpt(
{ parameters, queueCommandRequest }: WssParams,
) {
const prompt = parameters.get("prompt") ?? getRandomPrompt();

const completion = await client.createChatCompletion({
model: "gpt-3.5-turbo",
messages: [
{ role: "system", content: SYSTEM_PROMPT },
{ role: "user", name: "Minecraft", content: prompt },
],
temperature: 0.3,
n: 1,
});

const completionCommands =
(completion.data.choices[0].message?.content?.split("\n") ?? []).map((c) =>
c.replace(/^\//, "").trim()
).filter((c) => c.length > 0);

console.group("ChatGPT response");
console.log(completionCommands);
console.groupEnd();

const commands: string[] = [];

commands.push(
...completionCommands,
);

commands.map((c) => queueCommandRequest(c));
}
80 changes: 80 additions & 0 deletions src/functions/dalle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { load } from "https://deno.land/std@0.184.0/dotenv/mod.ts";
import openai from "npm:openai@^3.2.1";
import { Image } from "imagescript/mod.ts";
import type { Axis, WssParams } from "../../typings/types.ts";
import { convertImage } from "../components/ImagePrinter.ts";
import assemble from "../components/_assemble.ts";
import { join } from "path/mod.ts";

const { Configuration, OpenAIApi } = openai;

const env = await load();
const OPENAI_API_KEY = env.OPENAI_API_KEY || Deno.env.get("OPENAI_API_KEY") ||
"";

const outputDir = join(Deno.cwd(), "out");

const getRandomPrompt = () => {
const prompts = [
"A unicorn in space",
"A dog in a hat",
];

return prompts[Math.floor(Math.random() * prompts.length)];
};

const configuration = new Configuration({
apiKey: OPENAI_API_KEY,
});
const client = new OpenAIApi(configuration);

function getBlockLibrary(material: string, exclude?: string[]) {
return assemble(exclude).filter((b) => b.behaviorId.includes(material));
}

export default async function dalle(
{ parameters, queueCommandRequest, formatPosition }: WssParams,
) {
const axis = parameters.get("axis") ?? "y";
const material = parameters.get("material") ?? "plastic";
const exclude = (parameters.get("exclude") ?? "").split(",");
const position = parameters.get("position") ?? "0 0 0";
const useAbsolutePosition = parameters.get("absolute") === "true";
const [x, y, z] = position.split(" ").map((v) => parseInt(v, 10));
const prompt = parameters.get("prompt") ?? getRandomPrompt();
const response = await client.createImage({
prompt,
n: 1,
size: "256x256",
});

const imageUrl: string = response.data.data[0].url ?? "";
const imageRes = await fetch(imageUrl);
const imageData = await imageRes.arrayBuffer();
const decoded = await Image.decode(imageData);

try {
await Deno.writeFile(
join(outputDir, prompt.trim().replace(/[\s:\/\\#\$\?]+/gi, "-") + ".png"),
new Uint8Array(imageData),
);
} catch (err) {
console.warn(`Failed saving image from DALL-E: ${err}`);
}

const resized = decoded.resize(128, 128);

const commands: string[] = [];

commands.push(
...convertImage(
resized,
getBlockLibrary(material, exclude),
[x, y, z],
<Axis> axis,
useAbsolutePosition === true,
),
);

commands.map((c) => queueCommandRequest(c));
}
4 changes: 2 additions & 2 deletions src/versions.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"RP": "2.3.0",
"BP": "2.3.0"
"RP": "2.3.1",
"BP": "2.3.1"
}

0 comments on commit 36a3c47

Please sign in to comment.