Spaces:
Running
on
T4
Running
on
T4
Upload 11 files
#2
by
theo-michel
- opened
- .gitignore +0 -44
- Dockerfile +1 -1
- README.md +7 -8
- api.js +0 -3
- leaderboard.txt +0 -32
- package-lock.json +0 -13
- package.json +0 -1
- replace.txt +0 -2
- src/eleven_labs.js +2 -3
- src/game_engine.js +41 -54
- src/llm.js +1 -3
- src/shyguy.js +18 -52
- src/shyguy_llm.js +3 -8
- src/speech_to_text.js +55 -54
- src/story_engine.js +12 -33
- vite.config.js +1 -7
.gitignore
DELETED
@@ -1,44 +0,0 @@
|
|
1 |
-
# Dependencies
|
2 |
-
node_modules/
|
3 |
-
.pnpm-store/
|
4 |
-
|
5 |
-
# Build outputs
|
6 |
-
dist/
|
7 |
-
build/
|
8 |
-
|
9 |
-
# Environment files
|
10 |
-
.env
|
11 |
-
.env.*
|
12 |
-
!.env.example
|
13 |
-
|
14 |
-
# IDE and editor files
|
15 |
-
.vscode/
|
16 |
-
.idea/
|
17 |
-
*.swp
|
18 |
-
*.swo
|
19 |
-
.DS_Store
|
20 |
-
Thumbs.db
|
21 |
-
|
22 |
-
# Debug logs
|
23 |
-
npm-debug.log*
|
24 |
-
yarn-debug.log*
|
25 |
-
yarn-error.log*
|
26 |
-
pnpm-debug.log*
|
27 |
-
|
28 |
-
# Cache directories
|
29 |
-
.cache/
|
30 |
-
.temp/
|
31 |
-
.vite/
|
32 |
-
|
33 |
-
# Test coverage
|
34 |
-
coverage/
|
35 |
-
|
36 |
-
|
37 |
-
# Temporary files
|
38 |
-
*.tmp
|
39 |
-
*.temp
|
40 |
-
|
41 |
-
|
42 |
-
# System files
|
43 |
-
.DS_Store
|
44 |
-
desktop.ini
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Dockerfile
CHANGED
@@ -26,4 +26,4 @@ EXPOSE 7860
|
|
26 |
ENV BROWSER=none
|
27 |
|
28 |
# Start the Vite development server with specific configurations
|
29 |
-
CMD ["npm", "run", "dev", "--", "--host", "--port", "7860", "--strictPort"]
|
|
|
26 |
ENV BROWSER=none
|
27 |
|
28 |
# Start the Vite development server with specific configurations
|
29 |
+
CMD ["npm", "run", "dev", "--", "--host", "--port", "7860", "--strictPort"]
|
README.md
CHANGED
@@ -1,12 +1,11 @@
|
|
1 |
---
|
2 |
-
title:
|
3 |
-
emoji:
|
4 |
-
colorFrom:
|
5 |
-
colorTo:
|
6 |
sdk: docker
|
7 |
pinned: false
|
8 |
-
short_description: Help the Shy Guy finaly talk to Jessica
|
9 |
-
thumbnail: >-
|
10 |
-
https://cdn-uploads.huggingface.co/production/uploads/65707a9053269901a14c5b3d/1OIdDpFEAKjWB_9jq4SA9.png
|
11 |
---
|
12 |
-
|
|
|
|
|
|
1 |
---
|
2 |
+
title: Shyguys
|
3 |
+
emoji: 🦀
|
4 |
+
colorFrom: red
|
5 |
+
colorTo: pink
|
6 |
sdk: docker
|
7 |
pinned: false
|
|
|
|
|
|
|
8 |
---
|
9 |
+
|
10 |
+
|
11 |
+
Clone the repository and run npm run dev
|
api.js
DELETED
@@ -1,3 +0,0 @@
|
|
1 |
-
export const HUGGINGFACE_API_KEY = process.env.HUGGINGFACE_API_KEY;
|
2 |
-
export const ELEVENLABS_API_KEY = process.env.ELEVENLABS_API_KEY;
|
3 |
-
export const MISTRAL_API_KEY = process.env.MISTRAL_API_KEY;
|
|
|
|
|
|
|
|
leaderboard.txt
DELETED
@@ -1,32 +0,0 @@
|
|
1 |
-
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
David Dobas Score: 695
|
8 |
-
David Dobas Score: 287
|
9 |
-
David Dobas Score: 246
|
10 |
-
David Dobas Score: 833
|
11 |
-
David Dobas Score: 213
|
12 |
-
David Dobas Score: 380
|
13 |
-
David Dobas Score: 393
|
14 |
-
David Dobas Score: 234
|
15 |
-
David Dobas Score: 224
|
16 |
-
David Dobas Score: 541
|
17 |
-
David Dobas Score: 361
|
18 |
-
David Dobas Score: 720
|
19 |
-
David Dobas Score: 571
|
20 |
-
David Dobas Score: 135
|
21 |
-
David Dobas Score: 192
|
22 |
-
David Dobas Score: 327
|
23 |
-
David Dobas Score: 282
|
24 |
-
David Dobas Score: 209
|
25 |
-
David Dobas Score: 231
|
26 |
-
David Dobas Score: 506
|
27 |
-
David Dobas Score: 233
|
28 |
-
David Dobas Score: 746
|
29 |
-
David Dobas Score: 312
|
30 |
-
David Dobas Score: 492
|
31 |
-
David Dobas Score: 611
|
32 |
-
David Dobas Score: 151
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
package-lock.json
CHANGED
@@ -8,7 +8,6 @@
|
|
8 |
"name": "shyguys-wingman-js",
|
9 |
"version": "1.0.0",
|
10 |
"dependencies": {
|
11 |
-
"dotenv": "^16.4.7",
|
12 |
"elevenlabs": "^1.50.4"
|
13 |
},
|
14 |
"devDependencies": {
|
@@ -845,18 +844,6 @@
|
|
845 |
"node": ">=0.4.0"
|
846 |
}
|
847 |
},
|
848 |
-
"node_modules/dotenv": {
|
849 |
-
"version": "16.4.7",
|
850 |
-
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz",
|
851 |
-
"integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==",
|
852 |
-
"license": "BSD-2-Clause",
|
853 |
-
"engines": {
|
854 |
-
"node": ">=12"
|
855 |
-
},
|
856 |
-
"funding": {
|
857 |
-
"url": "https://dotenvx.com"
|
858 |
-
}
|
859 |
-
},
|
860 |
"node_modules/dunder-proto": {
|
861 |
"version": "1.0.1",
|
862 |
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
|
|
8 |
"name": "shyguys-wingman-js",
|
9 |
"version": "1.0.0",
|
10 |
"dependencies": {
|
|
|
11 |
"elevenlabs": "^1.50.4"
|
12 |
},
|
13 |
"devDependencies": {
|
|
|
844 |
"node": ">=0.4.0"
|
845 |
}
|
846 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
847 |
"node_modules/dunder-proto": {
|
848 |
"version": "1.0.1",
|
849 |
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
package.json
CHANGED
@@ -9,7 +9,6 @@
|
|
9 |
"preview": "vite preview"
|
10 |
},
|
11 |
"dependencies": {
|
12 |
-
"dotenv": "^16.4.7",
|
13 |
"elevenlabs": "^1.50.4"
|
14 |
},
|
15 |
"devDependencies": {
|
|
|
9 |
"preview": "vite preview"
|
10 |
},
|
11 |
"dependencies": {
|
|
|
12 |
"elevenlabs": "^1.50.4"
|
13 |
},
|
14 |
"devDependencies": {
|
replace.txt
DELETED
@@ -1,2 +0,0 @@
|
|
1 |
-
vvO2N5PA9dj8cO6BwcIB8oH4YRnQI3Tn==your_actual_api_key_1
|
2 |
-
sk_62d0fc2ccddb1a4036f624dd8c411383fd9b9990755ea086==your_actual_api_key_2
|
|
|
|
|
|
src/eleven_labs.js
CHANGED
@@ -1,9 +1,8 @@
|
|
1 |
import { SHYGUY_LABEL, SISTER_LABEL, GIRL_LABEL, BAR_LABEL, DJ_LABEL, WINGMAN_LABEL } from "./constants.js";
|
2 |
-
import { ELEVENLABS_API_KEY } from "../api.js";
|
3 |
|
4 |
export class ElevenLabsClient {
|
5 |
constructor() {
|
6 |
-
this.apiKey =
|
7 |
this.baseUrl = "https://api.elevenlabs.io/v1";
|
8 |
}
|
9 |
|
@@ -38,7 +37,7 @@ export class ElevenLabsClient {
|
|
38 |
async createSpeech({
|
39 |
text,
|
40 |
voiceId,
|
41 |
-
modelId = "
|
42 |
outputFormat = "mp3_44100_128",
|
43 |
voiceSettings = null,
|
44 |
pronunciationDictionaryLocators = null,
|
|
|
1 |
import { SHYGUY_LABEL, SISTER_LABEL, GIRL_LABEL, BAR_LABEL, DJ_LABEL, WINGMAN_LABEL } from "./constants.js";
|
|
|
2 |
|
3 |
export class ElevenLabsClient {
|
4 |
constructor() {
|
5 |
+
this.apiKey = "sk_62d0fc2ccddb1a4036f624dd8c411383fd9b9990755ea086";
|
6 |
this.baseUrl = "https://api.elevenlabs.io/v1";
|
7 |
}
|
8 |
|
|
|
37 |
async createSpeech({
|
38 |
text,
|
39 |
voiceId,
|
40 |
+
modelId = "eleven_multilingual_v2",
|
41 |
outputFormat = "mp3_44100_128",
|
42 |
voiceSettings = null,
|
43 |
pronunciationDictionaryLocators = null,
|
src/game_engine.js
CHANGED
@@ -165,11 +165,11 @@ export class GameEngine {
|
|
165 |
// Debug controls
|
166 |
this.initDebugControls();
|
167 |
|
168 |
-
//
|
169 |
this.gridMapTypes = {
|
170 |
-
floor:
|
171 |
-
wall:
|
172 |
-
door:
|
173 |
};
|
174 |
|
175 |
// load assets for drawing the scene
|
@@ -283,9 +283,6 @@ export class GameEngine {
|
|
283 |
document.addEventListener("keyup", this.handleKeyUp);
|
284 |
|
285 |
// Initialize with game view
|
286 |
-
const intialStatusText =
|
287 |
-
"You are playing as the Wingman. You can move around using arrow keys. Maybe Shyguy will listen to you or let you follow him around. Don't let him leave without the girl!";
|
288 |
-
this.updateStatus(intialStatusText);
|
289 |
|
290 |
this.sendButton.addEventListener("click", this.handleSendMessage);
|
291 |
this.dialogueContinueButton.addEventListener("click", this.handleDialogueContinue);
|
@@ -370,13 +367,13 @@ export class GameEngine {
|
|
370 |
for (let col = 0; col < this.gridCols; col++) {
|
371 |
// Set walls and obstacles (in future)
|
372 |
if (row === 0 || row === this.gridRows - 1 || col === 0 || col === this.gridCols - 1) {
|
373 |
-
this.backgroundGridMap[row][col] = this.gridMapTypes.wall
|
374 |
} else {
|
375 |
-
this.backgroundGridMap[row][col] = this.gridMapTypes.floor
|
376 |
}
|
377 |
}
|
378 |
}
|
379 |
-
this.backgroundGridMap[0][1] = this.gridMapTypes.door
|
380 |
}
|
381 |
|
382 |
checkWallCollision(sprite, newX, newY) {
|
@@ -391,9 +388,7 @@ export class GameEngine {
|
|
391 |
for (let row = gridY; row <= Math.floor((y + sprite.height) / (sprite.height / 2)); row++) {
|
392 |
for (let col = gridX; col <= Math.floor((x + sprite.width) / (sprite.width * 1.33)); col++) {
|
393 |
if (row >= 0 && row < this.gridRows && col >= 0 && col < this.gridCols) {
|
394 |
-
|
395 |
-
const typeInfo = Object.values(this.gridMapTypes).find((type) => type.index === cellType);
|
396 |
-
if (typeInfo && !typeInfo.passable) {
|
397 |
return true;
|
398 |
}
|
399 |
}
|
@@ -572,8 +567,7 @@ export class GameEngine {
|
|
572 |
}
|
573 |
|
574 |
handleKeyDown(e) {
|
575 |
-
|
576 |
-
if (e.key in this.keys && !document.activeElement.matches('input[type="text"], textarea')) {
|
577 |
this.keys[e.key] = true;
|
578 |
this.wingmanSprite.moving = true;
|
579 |
} else if (e.key === "Enter" && this.currentView === "game" && !e.shiftKey) {
|
@@ -670,7 +664,7 @@ export class GameEngine {
|
|
670 |
if (isClose) {
|
671 |
// pause the game
|
672 |
target.enabled = false;
|
673 |
-
this.stopShyguyAnimation();
|
674 |
|
675 |
if (target.label === EXIT_LABEL) {
|
676 |
this.gameOver = true;
|
@@ -744,7 +738,7 @@ export class GameEngine {
|
|
744 |
this.showContinueButton();
|
745 |
}
|
746 |
|
747 |
-
stopShyguyAnimation() {
|
748 |
this.shyguySprite.moving = false;
|
749 |
this.shyguySprite.frameX = 0;
|
750 |
this.shyguySprite.target = null;
|
@@ -759,47 +753,52 @@ export class GameEngine {
|
|
759 |
const x = col * this.wall.width;
|
760 |
const y = row * this.wall.height;
|
761 |
|
762 |
-
if (this.backgroundGridMap[row][col] === this.gridMapTypes.wall
|
763 |
this.ctx.drawImage(this.wall.image, x, y, this.wall.width, this.wall.height);
|
764 |
-
} else if (this.backgroundGridMap[row][col] === this.gridMapTypes.floor
|
765 |
this.ctx.drawImage(this.floor.image, x, y, this.floor.width, this.floor.height);
|
766 |
-
} else if (this.backgroundGridMap[row][col] === this.gridMapTypes.door
|
767 |
this.ctx.drawImage(this.door.image, x, y, this.door.width, this.door.height);
|
768 |
}
|
769 |
}
|
770 |
}
|
771 |
|
772 |
-
// Draw npcs with targets
|
773 |
this.drawTargetSprite(this.jessicaSprite, this.targets.girl);
|
774 |
this.drawTargetSprite(this.barSprite, this.targets.bar);
|
775 |
this.drawTargetSprite(this.djSprite, this.targets.dj);
|
776 |
this.drawTargetSprite(this.sisterSprite, this.targets.sister);
|
777 |
|
778 |
// Draw shyguy
|
779 |
-
this.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
780 |
|
781 |
// Draw wingman
|
782 |
-
this.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
783 |
}
|
784 |
|
785 |
drawTargetSprite(sprite, target) {
|
786 |
this.ctx.drawImage(sprite.image, target.x, target.y, target.width, target.height);
|
787 |
}
|
788 |
|
789 |
-
drawPlayerSprite(sprite) {
|
790 |
-
this.ctx.drawImage(
|
791 |
-
sprite.image,
|
792 |
-
sprite.frameX * sprite.width,
|
793 |
-
sprite.frameY * sprite.height,
|
794 |
-
sprite.width,
|
795 |
-
sprite.height,
|
796 |
-
sprite.x,
|
797 |
-
sprite.y,
|
798 |
-
sprite.width,
|
799 |
-
sprite.height
|
800 |
-
);
|
801 |
-
}
|
802 |
-
|
803 |
switchView(viewName) {
|
804 |
if (viewName === this.currentView) return;
|
805 |
|
@@ -924,6 +923,7 @@ export class GameEngine {
|
|
924 |
}
|
925 |
|
926 |
resolveAction(action) {
|
|
|
927 |
switch (action) {
|
928 |
case "stay_idle":
|
929 |
this.setNewTarget(null);
|
@@ -970,11 +970,6 @@ export class GameEngine {
|
|
970 |
// TODO: save conversation history
|
971 |
await this.shyguy.learnFromWingman(message);
|
972 |
console.log("[ShyguyLLM]: Next action: ", action);
|
973 |
-
this.shyguy.last_actions.push(action);
|
974 |
-
if (this.shyguy.num_beers >= 1) {
|
975 |
-
console.log("Updating status to: Shyguy is drunk. Try pushing him.");
|
976 |
-
this.updateStatus("Shyguy is drunk. Try pushing him.");
|
977 |
-
}
|
978 |
this.resolveAction(action);
|
979 |
});
|
980 |
}
|
@@ -998,7 +993,6 @@ export class GameEngine {
|
|
998 |
handlePlayAgain() {
|
999 |
this.clearChat(this.gameChatContainer);
|
1000 |
this.resetGame();
|
1001 |
-
this.stopGameOverMusic();
|
1002 |
this.switchView("game");
|
1003 |
}
|
1004 |
|
@@ -1081,12 +1075,9 @@ export class GameEngine {
|
|
1081 |
}
|
1082 |
|
1083 |
this.switchView("game");
|
1084 |
-
this.shyguyLLM.getShyGuyResponse("
|
1085 |
const next_action = response.action;
|
1086 |
-
|
1087 |
-
console.log("Updating status to: Shyguy is drunk. Try pushing him.");
|
1088 |
-
this.updateStatus("Shyguy is drunk. Try pushing him.");
|
1089 |
-
}
|
1090 |
this.resolveAction(next_action);
|
1091 |
});
|
1092 |
}
|
@@ -1126,18 +1117,14 @@ export class GameEngine {
|
|
1126 |
});
|
1127 |
}
|
1128 |
|
1129 |
-
|
|
|
1130 |
this.gameOverMusic.pause();
|
1131 |
this.gameOverMusic.currentTime = 0;
|
1132 |
this.victoryMusic.pause();
|
1133 |
this.victoryMusic.currentTime = 0;
|
1134 |
}
|
1135 |
|
1136 |
-
stopAllMusic() {
|
1137 |
-
this.stopBackgroundMusic();
|
1138 |
-
this.stopGameOverMusic();
|
1139 |
-
}
|
1140 |
-
|
1141 |
lowerMusicVolume() {
|
1142 |
// Store original volumes if not already stored
|
1143 |
if (!this.originalVolumes) {
|
|
|
165 |
// Debug controls
|
166 |
this.initDebugControls();
|
167 |
|
168 |
+
// if we have other obstacles, we can add them here
|
169 |
this.gridMapTypes = {
|
170 |
+
floor: 0,
|
171 |
+
wall: 1,
|
172 |
+
door: 2,
|
173 |
};
|
174 |
|
175 |
// load assets for drawing the scene
|
|
|
283 |
document.addEventListener("keyup", this.handleKeyUp);
|
284 |
|
285 |
// Initialize with game view
|
|
|
|
|
|
|
286 |
|
287 |
this.sendButton.addEventListener("click", this.handleSendMessage);
|
288 |
this.dialogueContinueButton.addEventListener("click", this.handleDialogueContinue);
|
|
|
367 |
for (let col = 0; col < this.gridCols; col++) {
|
368 |
// Set walls and obstacles (in future)
|
369 |
if (row === 0 || row === this.gridRows - 1 || col === 0 || col === this.gridCols - 1) {
|
370 |
+
this.backgroundGridMap[row][col] = this.gridMapTypes.wall;
|
371 |
} else {
|
372 |
+
this.backgroundGridMap[row][col] = this.gridMapTypes.floor;
|
373 |
}
|
374 |
}
|
375 |
}
|
376 |
+
this.backgroundGridMap[0][1] = this.gridMapTypes.door;
|
377 |
}
|
378 |
|
379 |
checkWallCollision(sprite, newX, newY) {
|
|
|
388 |
for (let row = gridY; row <= Math.floor((y + sprite.height) / (sprite.height / 2)); row++) {
|
389 |
for (let col = gridX; col <= Math.floor((x + sprite.width) / (sprite.width * 1.33)); col++) {
|
390 |
if (row >= 0 && row < this.gridRows && col >= 0 && col < this.gridCols) {
|
391 |
+
if (this.backgroundGridMap[row][col] === this.gridMapTypes.wall) {
|
|
|
|
|
392 |
return true;
|
393 |
}
|
394 |
}
|
|
|
567 |
}
|
568 |
|
569 |
handleKeyDown(e) {
|
570 |
+
if (e.key in this.keys) {
|
|
|
571 |
this.keys[e.key] = true;
|
572 |
this.wingmanSprite.moving = true;
|
573 |
} else if (e.key === "Enter" && this.currentView === "game" && !e.shiftKey) {
|
|
|
664 |
if (isClose) {
|
665 |
// pause the game
|
666 |
target.enabled = false;
|
667 |
+
this.stopShyguyAnimation(target);
|
668 |
|
669 |
if (target.label === EXIT_LABEL) {
|
670 |
this.gameOver = true;
|
|
|
738 |
this.showContinueButton();
|
739 |
}
|
740 |
|
741 |
+
stopShyguyAnimation(target) {
|
742 |
this.shyguySprite.moving = false;
|
743 |
this.shyguySprite.frameX = 0;
|
744 |
this.shyguySprite.target = null;
|
|
|
753 |
const x = col * this.wall.width;
|
754 |
const y = row * this.wall.height;
|
755 |
|
756 |
+
if (this.backgroundGridMap[row][col] === this.gridMapTypes.wall) {
|
757 |
this.ctx.drawImage(this.wall.image, x, y, this.wall.width, this.wall.height);
|
758 |
+
} else if (this.backgroundGridMap[row][col] === this.gridMapTypes.floor) {
|
759 |
this.ctx.drawImage(this.floor.image, x, y, this.floor.width, this.floor.height);
|
760 |
+
} else if (this.backgroundGridMap[row][col] === this.gridMapTypes.door) {
|
761 |
this.ctx.drawImage(this.door.image, x, y, this.door.width, this.door.height);
|
762 |
}
|
763 |
}
|
764 |
}
|
765 |
|
|
|
766 |
this.drawTargetSprite(this.jessicaSprite, this.targets.girl);
|
767 |
this.drawTargetSprite(this.barSprite, this.targets.bar);
|
768 |
this.drawTargetSprite(this.djSprite, this.targets.dj);
|
769 |
this.drawTargetSprite(this.sisterSprite, this.targets.sister);
|
770 |
|
771 |
// Draw shyguy
|
772 |
+
this.ctx.drawImage(
|
773 |
+
this.shyguySprite.image,
|
774 |
+
this.shyguySprite.frameX * this.shyguySprite.width,
|
775 |
+
this.shyguySprite.frameY * this.shyguySprite.height,
|
776 |
+
this.shyguySprite.width,
|
777 |
+
this.shyguySprite.height,
|
778 |
+
this.shyguySprite.x,
|
779 |
+
this.shyguySprite.y,
|
780 |
+
this.shyguySprite.width,
|
781 |
+
this.shyguySprite.height
|
782 |
+
);
|
783 |
|
784 |
// Draw wingman
|
785 |
+
this.ctx.drawImage(
|
786 |
+
this.wingmanSprite.image,
|
787 |
+
this.wingmanSprite.frameX * this.wingmanSprite.width,
|
788 |
+
this.wingmanSprite.frameY * this.wingmanSprite.height,
|
789 |
+
this.wingmanSprite.width,
|
790 |
+
this.wingmanSprite.height,
|
791 |
+
this.wingmanSprite.x,
|
792 |
+
this.wingmanSprite.y,
|
793 |
+
this.wingmanSprite.width,
|
794 |
+
this.wingmanSprite.height
|
795 |
+
);
|
796 |
}
|
797 |
|
798 |
drawTargetSprite(sprite, target) {
|
799 |
this.ctx.drawImage(sprite.image, target.x, target.y, target.width, target.height);
|
800 |
}
|
801 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
802 |
switchView(viewName) {
|
803 |
if (viewName === this.currentView) return;
|
804 |
|
|
|
923 |
}
|
924 |
|
925 |
resolveAction(action) {
|
926 |
+
// TODO: resolve the action
|
927 |
switch (action) {
|
928 |
case "stay_idle":
|
929 |
this.setNewTarget(null);
|
|
|
970 |
// TODO: save conversation history
|
971 |
await this.shyguy.learnFromWingman(message);
|
972 |
console.log("[ShyguyLLM]: Next action: ", action);
|
|
|
|
|
|
|
|
|
|
|
973 |
this.resolveAction(action);
|
974 |
});
|
975 |
}
|
|
|
993 |
handlePlayAgain() {
|
994 |
this.clearChat(this.gameChatContainer);
|
995 |
this.resetGame();
|
|
|
996 |
this.switchView("game");
|
997 |
}
|
998 |
|
|
|
1075 |
}
|
1076 |
|
1077 |
this.switchView("game");
|
1078 |
+
this.shyguyLLM.getShyGuyResponse("").then((response) => {
|
1079 |
const next_action = response.action;
|
1080 |
+
|
|
|
|
|
|
|
1081 |
this.resolveAction(next_action);
|
1082 |
});
|
1083 |
}
|
|
|
1117 |
});
|
1118 |
}
|
1119 |
|
1120 |
+
stopAllMusic() {
|
1121 |
+
this.stopBackgroundMusic();
|
1122 |
this.gameOverMusic.pause();
|
1123 |
this.gameOverMusic.currentTime = 0;
|
1124 |
this.victoryMusic.pause();
|
1125 |
this.victoryMusic.currentTime = 0;
|
1126 |
}
|
1127 |
|
|
|
|
|
|
|
|
|
|
|
1128 |
lowerMusicVolume() {
|
1129 |
// Store original volumes if not already stored
|
1130 |
if (!this.originalVolumes) {
|
src/llm.js
CHANGED
@@ -1,8 +1,6 @@
|
|
1 |
-
import { MISTRAL_API_KEY } from "../api.js";
|
2 |
-
|
3 |
export class LLM {
|
4 |
constructor() {
|
5 |
-
this.apiKey =
|
6 |
}
|
7 |
|
8 |
async getChatCompletion(systemPrompt, userInput) {
|
|
|
|
|
|
|
1 |
export class LLM {
|
2 |
constructor() {
|
3 |
+
this.apiKey = "vvO2N5PA9dj8cO6BwcIB8oH4YRnQI3Tn";
|
4 |
}
|
5 |
|
6 |
async getChatCompletion(systemPrompt, userInput) {
|
src/shyguy.js
CHANGED
@@ -4,34 +4,27 @@ export class Shyguy {
|
|
4 |
constructor() {
|
5 |
this.num_beers = 0;
|
6 |
this.courage = 1;
|
7 |
-
this.personality = "This is the Shyguy. He is shy and introverted. He is also a bit of a nerd. He fell in love with Jessica.
|
8 |
this.lessons_learned = "";
|
9 |
this.conversation_history = "";
|
10 |
this.song_playing = "Let it be";
|
11 |
this.imgpath = "assets/assets/shyguy_headshot.jpeg";
|
12 |
-
this.met_dj = false;
|
13 |
-
this.met_bar = false;
|
14 |
-
this.met_sister = false;
|
15 |
this.last_actions = [];
|
16 |
}
|
17 |
|
18 |
getSystemPrompt() {
|
19 |
if (this.num_beers >= 3) {
|
20 |
-
return `${this.personality}. His courage is ${this.courage} on the level 1 to 10. If his courage is higher than 5, he is self-confident. He had too many beers and he is drunk. He talks about how drunk he is. Follow the following lessons: ${this.lessons_learned}
|
21 |
} else if (this.num_beers == 2) {
|
22 |
-
return `This is Shyguy. He had two beers, so he feels relaxed and he can talk with anyone.
|
23 |
}
|
24 |
else {
|
25 |
-
return `${this.personality}.
|
26 |
}
|
27 |
}
|
28 |
|
29 |
appendLesson(lesson) {
|
30 |
this.lessons_learned += lesson + "\n";
|
31 |
-
// Keep only last 200 characters of lessons learned if too long
|
32 |
-
if (this.lessons_learned.length > 400) {
|
33 |
-
this.lessons_learned = this.lessons_learned.slice(-400);
|
34 |
-
}
|
35 |
}
|
36 |
|
37 |
appendConversationHistory(conversation_history) {
|
@@ -39,54 +32,35 @@ export class Shyguy {
|
|
39 |
}
|
40 |
|
41 |
async learnLesson(entityName){
|
42 |
-
console.log("Conversation history: ", this.conversation_history);
|
43 |
-
if (this.conversation_history === "") {
|
44 |
-
return;
|
45 |
-
}
|
46 |
const summaryLLM = new LLM();
|
47 |
const summary = await summaryLLM.getChatCompletion(
|
48 |
-
`Summarize in one sentence what Shyguy should say when talking to ${entityName}. Do not confuse Jessica and Jessica's sister. If there is nothing relevant about what to say to Jessica, say Nothing relevant
|
49 |
this.conversation_history
|
50 |
);
|
51 |
this.appendLesson(`When talking to ${entityName}, ${summary}`);
|
52 |
}
|
53 |
|
54 |
async learnFromWingman(wingman_message) {
|
55 |
-
console.log("Wingman message: ", wingman_message);
|
56 |
const summaryLLM = new LLM();
|
|
|
57 |
const summary = await summaryLLM.getChatCompletion(
|
58 |
-
`
|
59 |
wingman_message
|
60 |
);
|
61 |
-
console.log("Summary learned from wingman: ", summary);
|
62 |
-
this.appendLesson(summary);
|
63 |
-
}
|
64 |
-
|
65 |
-
async learnFromConversation(conversation) {
|
66 |
-
console.log("Conversation: ", conversation);
|
67 |
-
const summaryLLM = new LLM();
|
68 |
-
const summary = await summaryLLM.getChatCompletion(
|
69 |
-
`Summarize in one sentence what happened in the conversation. Do not hallucinate. Do not make up things.`,
|
70 |
-
conversation
|
71 |
-
);
|
72 |
this.appendLesson(summary);
|
73 |
}
|
74 |
|
75 |
getAvailableActions() {
|
76 |
let actions = {};
|
77 |
const lastAction = this.last_actions[this.last_actions.length - 1];
|
78 |
-
console.log("[ShyGuy]: Last action: ", lastAction);
|
79 |
|
|
|
80 |
if (this.num_beers === 0) {
|
81 |
actions = {
|
82 |
"go_bar": {
|
83 |
description: "Head to the bar.",
|
84 |
location: "bar",
|
85 |
},
|
86 |
-
"go_dj": {
|
87 |
-
description: "Go to the DJ",
|
88 |
-
location: "dj_booth",
|
89 |
-
},
|
90 |
"go_home": {
|
91 |
description: "Give up and head home",
|
92 |
location: "exit",
|
@@ -101,26 +75,19 @@ export class Shyguy {
|
|
101 |
// After 2+ beers, all actions except going home are available
|
102 |
actions = {
|
103 |
"go_bar": {
|
104 |
-
description: "
|
105 |
location: "bar",
|
106 |
},
|
107 |
"go_dj": {
|
108 |
-
description: "
|
109 |
location: "dj_booth",
|
110 |
},
|
111 |
"go_sister": {
|
112 |
-
description: "
|
113 |
location: "sister",
|
114 |
},
|
115 |
"go_girl": {
|
116 |
-
description: "
|
117 |
-
location: "girl",
|
118 |
-
}
|
119 |
-
};
|
120 |
-
} else if (this.num_beers >= 4) {
|
121 |
-
actions = {
|
122 |
-
"go_girl": {
|
123 |
-
description: "Go to Jessica",
|
124 |
location: "girl",
|
125 |
}
|
126 |
};
|
@@ -128,23 +95,23 @@ export class Shyguy {
|
|
128 |
// After 1 beer but less than 2, all actions are available
|
129 |
actions = {
|
130 |
"go_bar": {
|
131 |
-
description: "
|
132 |
location: "bar",
|
133 |
},
|
134 |
"go_home": {
|
135 |
-
description: "
|
136 |
location: "exit",
|
137 |
},
|
138 |
"go_dj": {
|
139 |
-
description: "
|
140 |
location: "dj_booth",
|
141 |
},
|
142 |
"go_sister": {
|
143 |
-
description: "
|
144 |
location: "sister",
|
145 |
},
|
146 |
"go_girl": {
|
147 |
-
description: "
|
148 |
location: "girl",
|
149 |
}
|
150 |
};
|
@@ -154,8 +121,7 @@ export class Shyguy {
|
|
154 |
if (lastAction && actions[lastAction]) {
|
155 |
delete actions[lastAction];
|
156 |
}
|
157 |
-
|
158 |
-
console.log("[ShyGuy]: Available actions: ", actions);
|
159 |
return actions;
|
160 |
}
|
161 |
}
|
|
|
4 |
constructor() {
|
5 |
this.num_beers = 0;
|
6 |
this.courage = 1;
|
7 |
+
this.personality = "This is the Shyguy. He is shy and introverted. He is also a bit of a nerd. He fell in love with Jessica. With Jessica, he talks about algorithms.";
|
8 |
this.lessons_learned = "";
|
9 |
this.conversation_history = "";
|
10 |
this.song_playing = "Let it be";
|
11 |
this.imgpath = "assets/assets/shyguy_headshot.jpeg";
|
|
|
|
|
|
|
12 |
this.last_actions = [];
|
13 |
}
|
14 |
|
15 |
getSystemPrompt() {
|
16 |
if (this.num_beers >= 3) {
|
17 |
+
return `${this.personality}. His courage is ${this.courage} on the level 1 to 10. If his courage is higher than 5, he is self-confident. He had too many beers and he is drunk. He talks about how drunk he is. Follow the following lessons: ${this.lessons_learned}`;
|
18 |
} else if (this.num_beers == 2) {
|
19 |
+
return `This is Shyguy. He had two beers, so he feels relaxed and he can talk with anyone. Follow the following lessons: ${this.lessons_learned}`;
|
20 |
}
|
21 |
else {
|
22 |
+
return `${this.personality}. He had ${this.num_beers} numbers of beers and his courage is ${this.courage} on the level 1 to 10. If his courage is higher than 5, he is self-confident. After having 3 bears, he says single words with a lot of hesitation and says that he feels bad and he talks about how drunk he is. If courage is low, he hesitates to speak. Follow the following lessons: ${this.lessons_learned}`;
|
23 |
}
|
24 |
}
|
25 |
|
26 |
appendLesson(lesson) {
|
27 |
this.lessons_learned += lesson + "\n";
|
|
|
|
|
|
|
|
|
28 |
}
|
29 |
|
30 |
appendConversationHistory(conversation_history) {
|
|
|
32 |
}
|
33 |
|
34 |
async learnLesson(entityName){
|
|
|
|
|
|
|
|
|
35 |
const summaryLLM = new LLM();
|
36 |
const summary = await summaryLLM.getChatCompletion(
|
37 |
+
`Summarize in one sentence what Shyguy should say when talking to ${entityName}. Do not confuse Jessica and Jessica's sister. If there is nothing relevant about what to say to Jessica, say Nothing relevant.`,
|
38 |
this.conversation_history
|
39 |
);
|
40 |
this.appendLesson(`When talking to ${entityName}, ${summary}`);
|
41 |
}
|
42 |
|
43 |
async learnFromWingman(wingman_message) {
|
|
|
44 |
const summaryLLM = new LLM();
|
45 |
+
console.log("Wingman message: ", wingman_message);
|
46 |
const summary = await summaryLLM.getChatCompletion(
|
47 |
+
`Give a summary of what is learned from the message. Summary is one sentence. The wingman is always talking. For example, if the wingman says "Let's have a beer", the output should be "Shyguy wants a beer". If the wingman says "Let's have vodka", the output should be "Shyguy wants vodka".`,
|
48 |
wingman_message
|
49 |
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
this.appendLesson(summary);
|
51 |
}
|
52 |
|
53 |
getAvailableActions() {
|
54 |
let actions = {};
|
55 |
const lastAction = this.last_actions[this.last_actions.length - 1];
|
|
|
56 |
|
57 |
+
// When sober, can only go to the bar or home
|
58 |
if (this.num_beers === 0) {
|
59 |
actions = {
|
60 |
"go_bar": {
|
61 |
description: "Head to the bar.",
|
62 |
location: "bar",
|
63 |
},
|
|
|
|
|
|
|
|
|
64 |
"go_home": {
|
65 |
description: "Give up and head home",
|
66 |
location: "exit",
|
|
|
75 |
// After 2+ beers, all actions except going home are available
|
76 |
actions = {
|
77 |
"go_bar": {
|
78 |
+
description: "Head to the bar for liquid courage",
|
79 |
location: "bar",
|
80 |
},
|
81 |
"go_dj": {
|
82 |
+
description: "Talk to the DJ about playing a song",
|
83 |
location: "dj_booth",
|
84 |
},
|
85 |
"go_sister": {
|
86 |
+
description: "Approach your crush's sister",
|
87 |
location: "sister",
|
88 |
},
|
89 |
"go_girl": {
|
90 |
+
description: "Approach your crush",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
91 |
location: "girl",
|
92 |
}
|
93 |
};
|
|
|
95 |
// After 1 beer but less than 2, all actions are available
|
96 |
actions = {
|
97 |
"go_bar": {
|
98 |
+
description: "Head to the bar for liquid courage",
|
99 |
location: "bar",
|
100 |
},
|
101 |
"go_home": {
|
102 |
+
description: "Give up and head home",
|
103 |
location: "exit",
|
104 |
},
|
105 |
"go_dj": {
|
106 |
+
description: "Talk to the DJ about playing a song",
|
107 |
location: "dj_booth",
|
108 |
},
|
109 |
"go_sister": {
|
110 |
+
description: "Approach your crush's sister",
|
111 |
location: "sister",
|
112 |
},
|
113 |
"go_girl": {
|
114 |
+
description: "Approach your crush",
|
115 |
location: "girl",
|
116 |
}
|
117 |
};
|
|
|
121 |
if (lastAction && actions[lastAction]) {
|
122 |
delete actions[lastAction];
|
123 |
}
|
124 |
+
|
|
|
125 |
return actions;
|
126 |
}
|
127 |
}
|
src/shyguy_llm.js
CHANGED
@@ -6,10 +6,9 @@ export class ShyGuyLLM {
|
|
6 |
this.currentConversation = []; // Array to store current conversation messages
|
7 |
const availableActions = this.shyguy.getAvailableActions();
|
8 |
this.baseSystemPrompt = `You are ShyGuy, a socially awkward character at a homecoming party. You are shy.
|
9 |
-
The wingman progressively makes you more confident, and if you drink alcohol
|
10 |
You know the wingman, he is your friend. You are talking to him.
|
11 |
You are willing to have a little alcohol.
|
12 |
-
If there is no clear action, you go home. Do not stay idle twice in a row.
|
13 |
The action should correspond to the dialogue.
|
14 |
Your responses should be in JSON format with two fields:
|
15 |
enum action {
|
@@ -38,7 +37,7 @@ export class ShyGuyLLM {
|
|
38 |
addToPrompt += `You are drunk and you start talking about how bad you feel. You are annoying. You talk about algorithms and then how bad you feel.\n`;
|
39 |
}
|
40 |
if (this.shyguy.courage < 2) {
|
41 |
-
addToPrompt += `You are shy. However, you believe wingman
|
42 |
}
|
43 |
if (this.shyguy.courage >= 2) {
|
44 |
addToPrompt += `You talk normally.`;
|
@@ -77,16 +76,12 @@ export class ShyGuyLLM {
|
|
77 |
const actionsPrompt = `\nYour currently available actions are: ${Object.keys(availableActions)
|
78 |
.map((action) => `\n- ${action}: ${availableActions[action].description}`)
|
79 |
.join("")}`;
|
|
|
80 |
// Add the situation to current conversation
|
81 |
this.addToCurrentConversation('wingman', player_message);
|
82 |
|
83 |
-
// Add the conversation to shyguy's history
|
84 |
-
this.shyguy.conversation_history += `\nWingman: ${player_message}\n`;
|
85 |
-
|
86 |
const fullPrompt = this.getSystemPrompt() + actionsPrompt;
|
87 |
-
console.log("[ShyGuy]: Full prompt: ", fullPrompt);
|
88 |
const response = await this.llm.getJsonCompletion(fullPrompt, player_message);
|
89 |
-
console.log("[ShyGuy]: Response: ", response);
|
90 |
|
91 |
// Add ShyGuy's response to current conversation
|
92 |
this.addToCurrentConversation('shyguy', response.dialogue);
|
|
|
6 |
this.currentConversation = []; // Array to store current conversation messages
|
7 |
const availableActions = this.shyguy.getAvailableActions();
|
8 |
this.baseSystemPrompt = `You are ShyGuy, a socially awkward character at a homecoming party. You are shy.
|
9 |
+
The wingman progressively makes you more confident, and if you drink alcohol.
|
10 |
You know the wingman, he is your friend. You are talking to him.
|
11 |
You are willing to have a little alcohol.
|
|
|
12 |
The action should correspond to the dialogue.
|
13 |
Your responses should be in JSON format with two fields:
|
14 |
enum action {
|
|
|
37 |
addToPrompt += `You are drunk and you start talking about how bad you feel. You are annoying. You talk about algorithms and then how bad you feel.\n`;
|
38 |
}
|
39 |
if (this.shyguy.courage < 2) {
|
40 |
+
addToPrompt += `You are shy. However, you believe wingman.`;
|
41 |
}
|
42 |
if (this.shyguy.courage >= 2) {
|
43 |
addToPrompt += `You talk normally.`;
|
|
|
76 |
const actionsPrompt = `\nYour currently available actions are: ${Object.keys(availableActions)
|
77 |
.map((action) => `\n- ${action}: ${availableActions[action].description}`)
|
78 |
.join("")}`;
|
79 |
+
|
80 |
// Add the situation to current conversation
|
81 |
this.addToCurrentConversation('wingman', player_message);
|
82 |
|
|
|
|
|
|
|
83 |
const fullPrompt = this.getSystemPrompt() + actionsPrompt;
|
|
|
84 |
const response = await this.llm.getJsonCompletion(fullPrompt, player_message);
|
|
|
85 |
|
86 |
// Add ShyGuy's response to current conversation
|
87 |
this.addToCurrentConversation('shyguy', response.dialogue);
|
src/speech_to_text.js
CHANGED
@@ -1,65 +1,66 @@
|
|
1 |
-
import { HUGGINGFACE_API_KEY } from "../api.js";
|
2 |
-
|
3 |
export class SpeechToTextClient {
|
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 |
-
return new Promise((resolve, reject) => {
|
31 |
-
this.mediaRecorder.onstop = async () => {
|
32 |
try {
|
33 |
-
|
34 |
-
|
35 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
} catch (error) {
|
37 |
-
|
|
|
38 |
}
|
39 |
-
};
|
40 |
-
|
41 |
-
this.mediaRecorder.stop();
|
42 |
-
this.isRecording = false;
|
43 |
-
this.mediaRecorder.stream.getTracks().forEach((track) => track.stop());
|
44 |
-
});
|
45 |
-
}
|
46 |
-
|
47 |
-
async transcribeAudio(audioBlob) {
|
48 |
-
try {
|
49 |
-
const response = await fetch("https://q86j6jmwc3jujazp.us-east-1.aws.endpoints.huggingface.cloud", {
|
50 |
-
headers: {
|
51 |
-
Accept: "application/json",
|
52 |
-
Authorization: `Bearer ${this.apiKey}`,
|
53 |
-
"Content-Type": "audio/webm",
|
54 |
-
},
|
55 |
-
method: "POST",
|
56 |
-
body: audioBlob,
|
57 |
-
});
|
58 |
-
const result = await response.json();
|
59 |
-
return result;
|
60 |
-
} catch (error) {
|
61 |
-
console.error("Error transcribing audio:", error);
|
62 |
-
throw error;
|
63 |
}
|
64 |
-
}
|
65 |
}
|
|
|
|
|
|
|
1 |
export class SpeechToTextClient {
|
2 |
+
constructor() {
|
3 |
+
// this.apiKey = "HF_API_KEY";
|
4 |
+
this.isRecording = false;
|
5 |
+
this.mediaRecorder = null;
|
6 |
+
this.audioChunks = [];
|
7 |
+
}
|
8 |
|
9 |
+
async startRecording() {
|
10 |
+
try {
|
11 |
+
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
12 |
+
this.mediaRecorder = new MediaRecorder(stream);
|
13 |
+
this.audioChunks = [];
|
14 |
+
|
15 |
+
this.mediaRecorder.ondataavailable = (event) => {
|
16 |
+
this.audioChunks.push(event.data);
|
17 |
+
};
|
18 |
|
19 |
+
this.mediaRecorder.start();
|
20 |
+
this.isRecording = true;
|
21 |
+
} catch (error) {
|
22 |
+
console.error("Error starting recording:", error);
|
23 |
+
throw error;
|
24 |
+
}
|
25 |
+
}
|
26 |
|
27 |
+
async stopRecording() {
|
28 |
+
return new Promise((resolve, reject) => {
|
29 |
+
this.mediaRecorder.onstop = async () => {
|
30 |
+
try {
|
31 |
+
const audioBlob = new Blob(this.audioChunks, { type: 'audio/webm' });
|
32 |
+
const result = await this.transcribeAudio(audioBlob);
|
33 |
+
resolve(result);
|
34 |
+
} catch (error) {
|
35 |
+
reject(error);
|
36 |
+
}
|
37 |
+
};
|
38 |
+
|
39 |
+
this.mediaRecorder.stop();
|
40 |
+
this.isRecording = false;
|
41 |
+
this.mediaRecorder.stream.getTracks().forEach(track => track.stop());
|
42 |
+
});
|
43 |
}
|
|
|
44 |
|
45 |
+
async transcribeAudio(audioBlob) {
|
|
|
|
|
46 |
try {
|
47 |
+
const response = await fetch(
|
48 |
+
"https://q86j6jmwc3jujazp.us-east-1.aws.endpoints.huggingface.cloud",
|
49 |
+
{
|
50 |
+
headers: {
|
51 |
+
"Accept": "application/json",
|
52 |
+
"Authorization": `Bearer ${this.apiKey}`,
|
53 |
+
"Content-Type": "audio/webm"
|
54 |
+
},
|
55 |
+
method: "POST",
|
56 |
+
body: audioBlob,
|
57 |
+
}
|
58 |
+
);
|
59 |
+
const result = await response.json();
|
60 |
+
return result;
|
61 |
} catch (error) {
|
62 |
+
console.error("Error transcribing audio:", error);
|
63 |
+
throw error;
|
64 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
65 |
}
|
|
|
66 |
}
|
src/story_engine.js
CHANGED
@@ -19,15 +19,13 @@ export function nameToLabel(name) {
|
|
19 |
}
|
20 |
|
21 |
class Bar {
|
22 |
-
constructor(
|
23 |
this.name = "bartender";
|
24 |
-
this.situation_prompt = "This
|
25 |
-
this.personality = "This is the bartender. He always offers triple vodka in his first answer. Then he is helpful, but he says that he has a crush on Jessica's sister
|
26 |
// this.past_conversation = "";
|
27 |
this.imgpath = "assets/assets/barman.jpeg";
|
28 |
this.output_format_prompt = "";
|
29 |
-
this.met_shyguy = false;
|
30 |
-
this.shyguy = shyguy;
|
31 |
this.functionDescriptions = [
|
32 |
{
|
33 |
key: "analyzeConsumption",
|
@@ -36,11 +34,11 @@ class Bar {
|
|
36 |
parameters: {
|
37 |
num_beers: {
|
38 |
type: "number",
|
39 |
-
description: "Total number of beers
|
40 |
},
|
41 |
heavy_alcohol: {
|
42 |
type: "boolean",
|
43 |
-
description: "If
|
44 |
},
|
45 |
},
|
46 |
},
|
@@ -49,7 +47,7 @@ class Bar {
|
|
49 |
}
|
50 |
|
51 |
getSystemPrompt() {
|
52 |
-
return `${this.personality}
|
53 |
}
|
54 |
}
|
55 |
|
@@ -58,10 +56,9 @@ class DJ {
|
|
58 |
this.name = "DJ";
|
59 |
this.situation_prompt = "This is a conversation with the DJ.";
|
60 |
this.personality =
|
61 |
-
"This is the DJ. He is funny. He offers drugs to the shyguy. He can only play songs from the options [Let it be, Call me maybe, Shape of you]. If asked to play a song, he will play it and not propose any other song.
|
62 |
// this.past_conversation = "";
|
63 |
this.imgpath = "assets/assets/dj.jpeg";
|
64 |
-
this.met_shyguy = false;
|
65 |
this.output_format_prompt = "";
|
66 |
this.functionDescriptions = [
|
67 |
{
|
@@ -80,7 +77,7 @@ class DJ {
|
|
80 |
}
|
81 |
|
82 |
getSystemPrompt() {
|
83 |
-
return `${this.personality}
|
84 |
}
|
85 |
}
|
86 |
|
@@ -94,7 +91,6 @@ class Sister {
|
|
94 |
"This is the sister of Jessica. She is a deeply religious Christian. Her first answer is rude. Her second answer is about christianity. First answer is helpful. If asked about the favourite song of the girl, she says happily that it is 'Call me maybe'.";
|
95 |
// this.past_conversation = "";
|
96 |
this.imgpath = "assets/assets/sister.jpeg";
|
97 |
-
this.met_shyguy = false;
|
98 |
this.functionDescriptions = [
|
99 |
{
|
100 |
key: "analyzeMood",
|
@@ -116,7 +112,7 @@ class Sister {
|
|
116 |
}
|
117 |
|
118 |
getSystemPrompt() {
|
119 |
-
return `${this.personality}. Her mood is ${this.mood} on the level 1 to 10. If the mood is low, she will be rude. If the mood is high, she will be helpful
|
120 |
}
|
121 |
}
|
122 |
|
@@ -128,7 +124,6 @@ class Girl {
|
|
128 |
this.imgpath = "assets/assets/jessica.jpeg";
|
129 |
this.output_format_prompt = "";
|
130 |
this.shyguy = shyguy;
|
131 |
-
this.met_shyguy = false;
|
132 |
this.functionDescriptions = [
|
133 |
{
|
134 |
key: "analyzeLiking",
|
@@ -146,9 +141,9 @@ class Girl {
|
|
146 |
|
147 |
getSystemPrompt() {
|
148 |
if (this.shyguy.song_playing === "Call me maybe") {
|
149 |
-
return `${this.personality}. She is very happy with the song playing. The first thing she says is that she really likes the music. Therefore she is nice and she likes shyguy. However, if he talks about algorithms, she does not like it and she becomes mean. Also if he talks with a lot of hesitation, she does not like it and she becomes mean
|
150 |
} else {
|
151 |
-
return `${this.personality}. She does not like the song that
|
152 |
}
|
153 |
}
|
154 |
}
|
@@ -191,7 +186,7 @@ export class StoryEngine {
|
|
191 |
// Initialize story engine properties with provided shyguy instance
|
192 |
this.shyguy = shyguy;
|
193 |
this.sister = new Sister();
|
194 |
-
this.bar = new Bar(
|
195 |
this.dj = new DJ();
|
196 |
this.girl = new Girl(shyguy);
|
197 |
}
|
@@ -229,12 +224,6 @@ export class StoryEngine {
|
|
229 |
|
230 |
// Append the conversation to shyguy's history
|
231 |
this.shyguy.conversation_history += `\nConversation with ${targetEntity.name}:\n${conversation}\n`;
|
232 |
-
console.log(conversation);
|
233 |
-
const conversationString = Object.values(conversation)
|
234 |
-
.map(msg => `${msg.role}: ${msg.content}`)
|
235 |
-
.join('\n');
|
236 |
-
this.shyguy.learnFromConversation(conversationString);
|
237 |
-
console.log("Lessons learned from conversation with " + targetEntity.name + this.shyguy.lessons_learned);
|
238 |
|
239 |
let gameOver = this.decideGameOver(conversation_output.analysis.parameters.game_over);
|
240 |
let gameSuccesful = this.decideGameSuccesful(conversation_output.analysis.parameters.likes_shyguy);
|
@@ -248,16 +237,6 @@ export class StoryEngine {
|
|
248 |
this.updateStates(conversation_output.analysis, targetEntity.name);
|
249 |
console.log("shyguy num_beers: " + this.shyguy.num_beers);
|
250 |
|
251 |
-
targetEntity.met_shyguy = true;
|
252 |
-
|
253 |
-
if (targetEntity.name === "DJ") {
|
254 |
-
this.shyguy.met_dj = true;
|
255 |
-
} else if (targetEntity.name === "bartender") {
|
256 |
-
this.shyguy.met_bar = true;
|
257 |
-
} else if (targetEntity.name === "Jessica's sister") {
|
258 |
-
this.shyguy.met_sister = true;
|
259 |
-
}
|
260 |
-
|
261 |
return {
|
262 |
conversation: conversation,
|
263 |
char1imgpath: this.shyguy.imgpath,
|
|
|
19 |
}
|
20 |
|
21 |
class Bar {
|
22 |
+
constructor() {
|
23 |
this.name = "bartender";
|
24 |
+
this.situation_prompt = "This conversation happens at the bar.";
|
25 |
+
this.personality = "This is the bartender. He always offers triple vodka in his first answer. Then he is helpful, but he says that he has a crush on Jessica's sister";
|
26 |
// this.past_conversation = "";
|
27 |
this.imgpath = "assets/assets/barman.jpeg";
|
28 |
this.output_format_prompt = "";
|
|
|
|
|
29 |
this.functionDescriptions = [
|
30 |
{
|
31 |
key: "analyzeConsumption",
|
|
|
34 |
parameters: {
|
35 |
num_beers: {
|
36 |
type: "number",
|
37 |
+
description: "Total number of beers mentioned as being consumed in the conversation",
|
38 |
},
|
39 |
heavy_alcohol: {
|
40 |
type: "boolean",
|
41 |
+
description: "If heavy alcohol was consumed, True",
|
42 |
},
|
43 |
},
|
44 |
},
|
|
|
47 |
}
|
48 |
|
49 |
getSystemPrompt() {
|
50 |
+
return `${this.personality}.`;
|
51 |
}
|
52 |
}
|
53 |
|
|
|
56 |
this.name = "DJ";
|
57 |
this.situation_prompt = "This is a conversation with the DJ.";
|
58 |
this.personality =
|
59 |
+
"This is the DJ. He is funny. He offers drugs to the shyguy. He can only play songs from the options [Let it be, Call me maybe, Shape of you]. If asked to play a song, he will play it and not propose any other song.";
|
60 |
// this.past_conversation = "";
|
61 |
this.imgpath = "assets/assets/dj.jpeg";
|
|
|
62 |
this.output_format_prompt = "";
|
63 |
this.functionDescriptions = [
|
64 |
{
|
|
|
77 |
}
|
78 |
|
79 |
getSystemPrompt() {
|
80 |
+
return `${this.personality}`;
|
81 |
}
|
82 |
}
|
83 |
|
|
|
91 |
"This is the sister of Jessica. She is a deeply religious Christian. Her first answer is rude. Her second answer is about christianity. First answer is helpful. If asked about the favourite song of the girl, she says happily that it is 'Call me maybe'.";
|
92 |
// this.past_conversation = "";
|
93 |
this.imgpath = "assets/assets/sister.jpeg";
|
|
|
94 |
this.functionDescriptions = [
|
95 |
{
|
96 |
key: "analyzeMood",
|
|
|
112 |
}
|
113 |
|
114 |
getSystemPrompt() {
|
115 |
+
return `${this.personality}. Her mood is ${this.mood} on the level 1 to 10. If the mood is low, she will be rude. If the mood is high, she will be helpful.`;
|
116 |
}
|
117 |
}
|
118 |
|
|
|
124 |
this.imgpath = "assets/assets/jessica.jpeg";
|
125 |
this.output_format_prompt = "";
|
126 |
this.shyguy = shyguy;
|
|
|
127 |
this.functionDescriptions = [
|
128 |
{
|
129 |
key: "analyzeLiking",
|
|
|
141 |
|
142 |
getSystemPrompt() {
|
143 |
if (this.shyguy.song_playing === "Call me maybe") {
|
144 |
+
return `${this.personality}. She is very happy with the song playing. The first thing she says is that she really likes the music. Therefore she is nice and she likes shyguy. However, if he talks about algorithms, she does not like it and she becomes mean. Also if he talks with a lot of hesitation, she does not like it and she becomes mean.`;
|
145 |
} else {
|
146 |
+
return `${this.personality}. She does not like the song that shyguy is playing. The first thing she says is that the song is terrible. Then she is mean all the time.`;
|
147 |
}
|
148 |
}
|
149 |
}
|
|
|
186 |
// Initialize story engine properties with provided shyguy instance
|
187 |
this.shyguy = shyguy;
|
188 |
this.sister = new Sister();
|
189 |
+
this.bar = new Bar();
|
190 |
this.dj = new DJ();
|
191 |
this.girl = new Girl(shyguy);
|
192 |
}
|
|
|
224 |
|
225 |
// Append the conversation to shyguy's history
|
226 |
this.shyguy.conversation_history += `\nConversation with ${targetEntity.name}:\n${conversation}\n`;
|
|
|
|
|
|
|
|
|
|
|
|
|
227 |
|
228 |
let gameOver = this.decideGameOver(conversation_output.analysis.parameters.game_over);
|
229 |
let gameSuccesful = this.decideGameSuccesful(conversation_output.analysis.parameters.likes_shyguy);
|
|
|
237 |
this.updateStates(conversation_output.analysis, targetEntity.name);
|
238 |
console.log("shyguy num_beers: " + this.shyguy.num_beers);
|
239 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
240 |
return {
|
241 |
conversation: conversation,
|
242 |
char1imgpath: this.shyguy.imgpath,
|
vite.config.js
CHANGED
@@ -1,12 +1,6 @@
|
|
1 |
-
import dotenv from "dotenv";
|
2 |
-
dotenv.config();
|
3 |
-
|
4 |
export default {
|
5 |
-
define: {
|
6 |
-
"process.env": process.env,
|
7 |
-
},
|
8 |
server: {
|
9 |
open: true,
|
10 |
-
allowedHosts: [
|
11 |
},
|
12 |
};
|
|
|
|
|
|
|
|
|
1 |
export default {
|
|
|
|
|
|
|
2 |
server: {
|
3 |
open: true,
|
4 |
+
allowedHosts: ['mistral-ai-game-jam-shyguys-2.hf.space']
|
5 |
},
|
6 |
};
|