neetnestor's picture
Build playground webapp
4879fd8
raw
history blame
3.71 kB
import * as webllm from "https://esm.run/@mlc-ai/web-llm";
import hljs from "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/es/highlight.min.js";
import { Type } from "./lib/typebox/index.mjs";
let engine = null;
const availableModels = webllm.prebuiltAppConfig.model_list
.filter(
(m) =>
m.model_id.startsWith("Llama-3") ||
m.model_id.startsWith("Hermes-2") ||
m.model_id.startsWith("Phi-3")
)
.map((m) => m.model_id);
let selectedModel = "Hermes-2-Pro-Llama-3-8B-q4f32_1-MLC";
availableModels.forEach((modelId) => {
const option = document.createElement("option");
option.value = modelId;
option.textContent = modelId;
document.getElementById("model-selection").appendChild(option);
});
document.getElementById("model-selection").value = selectedModel;
document.getElementById("model-selection").onchange = (e) => {
selectedModel = e.target.value;
engine = null;
};
document.getElementById(
"prompt"
).value = `Hermione Granger is a character in Harry Potter. Please fill in the following information about this character in JSON format.
Name is a string of character name.
House is one of Gryffindor, Hufflepuff, Ravenclaw, Slytherin.
Blood status is one of Pure-blood, Half-blood, Muggle-born.
Occupation is one of Student, Professor, Ministry of Magic, Other.
Wand is an object with wood, core, and length.
Alive is a boolean.
Patronus is a string.
`;
// JSON editor setup
const editor = ace.edit("schema", {
// mode: "ace/mode/javascript",
mode: "ace/mode/javascript",
theme: 'ace/theme/github',
wrap: true,
});
editor.setTheme("ace/theme/github");
editor.setValue(`Type.Object({
"name": Type.String(),
"house": Type.Enum({
"Gryffindor": "Gryffindor",
"Hufflepuff": "Hufflepuff",
"Ravenclaw": "Ravenclaw",
"Slytherin": "Slytherin",
}),
"blood_status": Type.Enum({
"Pure-blood": "Pure-blood",
"Half-blood": "Half-blood",
"Muggle-born": "Muggle-born",
}),
"occupation": Type.Enum({
"Student": "Student",
"Professor": "Professor",
"Ministry of Magic": "Ministry of Magic",
"Other": "Other",
}),
"wand": Type.Object({
"wood": Type.String(),
"core": Type.String(),
"length": Type.Number(),
}),
"alive": Type.Boolean(),
"patronus": Type.String(),
})`);
// Generate button
document.getElementById("generate").onclick = async () => {
const schemaInput = editor.getValue();
let T;
try {
T = eval(schemaInput);
} catch (e) {
console.error("Invalid schema", e);
return;
}
const schema = JSON.stringify(T);
if (!engine) {
engine = await webllm.CreateMLCEngine(selectedModel, {
initProgressCallback: (progress) => {
console.log(progress);
document.getElementById("output").textContent = progress.text;
},
});
}
const request = {
stream: true,
messages: [
{
role: "user",
content: document.getElementById("prompt").value,
},
],
max_tokens: 128,
response_format: {
type: "json_object",
schema: schema,
},
};
let curMessage = "";
const generator = await engine.chatCompletion(request);
for await (const chunk of generator) {
const curDelta = chunk.choices[0]?.delta.content;
if (curDelta) {
curMessage += curDelta;
}
console.log(curMessage);
document.getElementById("output").textContent = curMessage;
}
const finalMessage = await engine.getMessage();
console.log(finalMessage);
if (hljs) {
document.getElementById("output").innerHTML = hljs.highlight(finalMessage, {
language: "json",
}).value;
} else {
document.getElementById("output").textContent = finalMessage;
}
};