Skip to content

Commit 53bd1f6

Browse files
committed
Add a LanguageModel class that implements the Llama2 architecture via llama2.c and Emscripten
See https://github.com/gohai/llama2.c-emscripten for details.
1 parent f875305 commit 53bd1f6

File tree

16 files changed

+671
-0
lines changed

16 files changed

+671
-0
lines changed

examples/LanguageModel/index.html

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<title>Language Model Example</title>
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.7.0/p5.min.js"></script>
8+
<script src="../../dist/ml5.js"></script>
9+
</head>
10+
<body>
11+
<input placeholder="Prompt" id="prompt"></input> <input type="button" value="Generate" id="generate" disabled></input>
12+
<script src="sketch.js"></script>
13+
</body>
14+
</html>

examples/LanguageModel/sketch.js

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
let lm;
2+
let curWord = 0;
3+
let angle = 0;
4+
let radius = 60;
5+
6+
function setup() {
7+
createCanvas(400, 400);
8+
background(0);
9+
10+
lm = ml5.languageModel(onModelLoaded);
11+
}
12+
13+
function draw() {
14+
fill(0, 5);
15+
rect(0, 0, width, height);
16+
}
17+
18+
function onModelLoaded() {
19+
console.log('Model loaded');
20+
select('#generate').removeAttribute('disabled');
21+
select('#generate').mouseClicked(generateText);
22+
}
23+
24+
function generateText() {
25+
let prompt = select('#prompt').value();
26+
console.log('Prompt: ' + prompt);
27+
28+
let options = {
29+
temperature: 0.9
30+
};
31+
lm.generate(prompt, options, onToken);
32+
33+
curWord = 0;
34+
}
35+
36+
function onToken(lm) {
37+
console.log(lm.tokens[lm.tokens.length-1]);
38+
39+
while (curWord < lm.words.length) {
40+
push();
41+
translate(width/2, height/2);
42+
rotate(radians(angle));
43+
translate(radius, 0);
44+
rotate(radians(-angle));
45+
angle = angle + 5;
46+
radius += 0.5;
47+
if (radius > width/2 || radius > height/2) {
48+
radius = 60;
49+
}
50+
fill(255);
51+
textAlign(CENTER);
52+
textSize(10);
53+
text(lm.words[curWord], 0, 0);
54+
pop();
55+
curWord++;
56+
}
57+
58+
if (lm.finished) {
59+
console.log('Generation finished');
60+
}
61+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<title>Language Model Example</title>
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.7.0/p5.min.js"></script>
8+
<script src="../../dist/ml5.js"></script>
9+
</head>
10+
<body>
11+
<input placeholder="Prompt" id="prompt"></input> <input type="button" value="Generate" id="generate"></input>
12+
<div id="output"></div>
13+
<script src="sketch.js"></script>
14+
</body>
15+
</html>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
let lm;
2+
3+
async function setup() {
4+
noCanvas();
5+
6+
lm = await ml5.languageModel();
7+
console.log('Model loaded');
8+
9+
select('#generate').mouseClicked(generateText);
10+
}
11+
12+
function draw() {
13+
}
14+
15+
async function generateText() {
16+
let prompt = select('#prompt').value();
17+
console.log('Prompt: ' + prompt);
18+
19+
let out = await lm.generate(prompt);
20+
console.log('Generated: ' + out);
21+
select('#output').html(out);
22+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<title>Language Model Example</title>
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.7.0/p5.min.js"></script>
8+
<script src="../../dist/ml5.js"></script>
9+
</head>
10+
<body>
11+
<input placeholder="Prompt" id="prompt"></input> <input type="button" value="Generate" id="generate"></input>
12+
<script src="sketch.js"></script>
13+
</body>
14+
</html>
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
let lm;
2+
let curWord = 0;
3+
let angle = 0;
4+
let radius = 60;
5+
6+
function setup() {
7+
createCanvas(400, 400);
8+
background(0);
9+
10+
lm = ml5.languageModel(onModelLoaded);
11+
}
12+
13+
function draw() {
14+
fill(0, 5);
15+
rect(0, 0, width, height);
16+
}
17+
18+
function onModelLoaded() {
19+
console.log('Model loaded');
20+
select('#generate').removeAttribute('disabled');
21+
select('#generate').mouseClicked(generateText);
22+
}
23+
24+
function generateText() {
25+
let prompt = select('#prompt').value();
26+
console.log('Prompt: ' + prompt);
27+
28+
let options = {
29+
temperature: 0.9
30+
};
31+
lm.generate(prompt, options);
32+
lm.on('token', onToken);
33+
lm.on('word', onWord);
34+
lm.on('finished', onFinshed);
35+
}
36+
37+
38+
function onToken(lm) {
39+
console.log(lm.tokens[lm.tokens.length-1]);
40+
}
41+
42+
function onWord(word, lm) {
43+
push();
44+
translate(width/2, height/2);
45+
rotate(radians(angle));
46+
translate(radius, 0);
47+
rotate(radians(-angle));
48+
angle = angle + 5;
49+
radius += 0.5;
50+
if (radius > width/2 || radius > height/2) {
51+
radius = 60;
52+
}
53+
fill(255);
54+
textAlign(CENTER);
55+
textSize(10);
56+
text(word, 0, 0);
57+
pop();
58+
}
59+
60+
function onFinshed(lm) {
61+
console.log('Generation finished');
62+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<title>Language Model Example</title>
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.7.0/p5.min.js"></script>
8+
<script src="../../dist/ml5.js"></script>
9+
</head>
10+
<body>
11+
<input placeholder="Prompt" id="prompt"></input> <input type="button" value="Generate" id="generate" disabled></input>
12+
<script src="sketch.js"></script>
13+
</body>
14+
</html>
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
let lm;
2+
let numOptions = 40;
3+
4+
async function setup() {
5+
noCanvas();
6+
7+
lm = await ml5.languageModel(onModelLoaded);
8+
}
9+
10+
function draw() {
11+
}
12+
13+
function onModelLoaded() {
14+
console.log('Model loaded');
15+
select('#generate').removeAttribute('disabled');
16+
select('#generate').mouseClicked(generateText);
17+
}
18+
19+
function generateText() {
20+
let prompt = select('#prompt').value();
21+
console.log('Prompt: ' + prompt);
22+
23+
select('#prompt').remove();
24+
select('#generate').remove();
25+
let btn = createElement('button', prompt);
26+
btn.attribute('disabled', 'disabled');
27+
select('body').child(btn);
28+
29+
let options = {
30+
temperature: 0.9
31+
};
32+
33+
lm.manualStart(prompt, options, onTokens);
34+
}
35+
36+
function onTokens(tokens, lm) {
37+
for (let i=0; i < numOptions; i++) {
38+
let btn = createElement('button', tokens[i].str);
39+
btn.class('continuation');
40+
btn.id(tokens[i].index);
41+
btn.mousePressed(selectToken);
42+
select('body').child(btn);
43+
}
44+
}
45+
46+
function selectToken() {
47+
let nextToken = parseInt(this.id());
48+
49+
this.removeClass('continuation');
50+
this.attribute('disabled', 'disabled');
51+
this.mousePressed(null);
52+
53+
let others = selectAll('.continuation');
54+
for (let i=0; i < others.length; i++) {
55+
others[i].remove();
56+
}
57+
58+
lm.manualNext(nextToken, onTokens);
59+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8">
5+
<title>Language Model Example</title>
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.7.0/p5.min.js"></script>
8+
<script src="../../dist/ml5.js"></script>
9+
</head>
10+
<body>
11+
<input placeholder="Prompt" id="prompt"></input> <input type="button" value="Generate" id="generate"></input>
12+
<script src="sketch.js"></script>
13+
</body>
14+
</html>
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
let lm;
2+
let numOptions = 40;
3+
4+
async function setup() {
5+
noCanvas();
6+
7+
lm = await ml5.languageModel();
8+
console.log('Model loaded');
9+
10+
select('#generate').mouseClicked(generateText);
11+
}
12+
13+
function draw() {
14+
}
15+
16+
async function generateText() {
17+
let prompt = select('#prompt').value();
18+
console.log('Prompt: ' + prompt);
19+
20+
select('#prompt').remove();
21+
select('#generate').remove();
22+
let btn = createElement('button', prompt);
23+
btn.attribute('disabled', 'disabled');
24+
select('body').child(btn);
25+
26+
let options = {
27+
temperature: 0.9
28+
};
29+
30+
let tokens = await lm.manualStart(prompt, options);
31+
32+
for (let i=0; i < numOptions; i++) {
33+
let btn = createElement('button', tokens[i].str);
34+
btn.class('continuation');
35+
btn.id(tokens[i].index);
36+
btn.mousePressed(selectToken);
37+
select('body').child(btn);
38+
}
39+
}
40+
41+
async function selectToken() {
42+
let nextToken = parseInt(this.id());
43+
44+
this.removeClass('continuation');
45+
this.attribute('disabled', 'disabled');
46+
this.mousePressed(null);
47+
48+
let others = selectAll('.continuation');
49+
for (let i=0; i < others.length; i++) {
50+
others[i].remove();
51+
}
52+
53+
let tokens = await lm.manualNext(nextToken);
54+
55+
for (let i=0; i < numOptions; i++) {
56+
let btn = createElement('button', tokens[i].str);
57+
btn.class('continuation');
58+
btn.id(tokens[i].index);
59+
btn.mousePressed(selectToken);
60+
select('body').child(btn);
61+
}
62+
}

0 commit comments

Comments
 (0)