Spaces:
Running
on
T4
Running
on
T4
Upload 56 files
Browse filesUpdated to hide api keys (there might be some small diffs as the version I had uploaded was a bit old)
We need to add the secrets before merging
- Dockerfile +1 -1
- README.md +0 -3
- api.js +3 -0
- package-lock.json +13 -0
- package.json +1 -0
- src/eleven_labs.js +2 -1
- src/llm.js +3 -1
- src/shyguy.js +2 -2
- src/speech_to_text.js +54 -55
- vite.config.js +7 -1
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
@@ -6,6 +6,3 @@ colorTo: pink
|
|
6 |
sdk: docker
|
7 |
pinned: false
|
8 |
---
|
9 |
-
|
10 |
-
|
11 |
-
Clone the repository and run npm run dev
|
|
|
6 |
sdk: docker
|
7 |
pinned: false
|
8 |
---
|
|
|
|
|
|
api.js
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
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;
|
package-lock.json
CHANGED
@@ -8,6 +8,7 @@
|
|
8 |
"name": "shyguys-wingman-js",
|
9 |
"version": "1.0.0",
|
10 |
"dependencies": {
|
|
|
11 |
"elevenlabs": "^1.50.4"
|
12 |
},
|
13 |
"devDependencies": {
|
@@ -844,6 +845,18 @@
|
|
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",
|
|
|
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 |
"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",
|
package.json
CHANGED
@@ -9,6 +9,7 @@
|
|
9 |
"preview": "vite preview"
|
10 |
},
|
11 |
"dependencies": {
|
|
|
12 |
"elevenlabs": "^1.50.4"
|
13 |
},
|
14 |
"devDependencies": {
|
|
|
9 |
"preview": "vite preview"
|
10 |
},
|
11 |
"dependencies": {
|
12 |
+
"dotenv": "^16.4.7",
|
13 |
"elevenlabs": "^1.50.4"
|
14 |
},
|
15 |
"devDependencies": {
|
src/eleven_labs.js
CHANGED
@@ -1,8 +1,9 @@
|
|
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 =
|
6 |
this.baseUrl = "https://api.elevenlabs.io/v1";
|
7 |
}
|
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 = ELEVENLABS_API_KEY;
|
7 |
this.baseUrl = "https://api.elevenlabs.io/v1";
|
8 |
}
|
9 |
|
src/llm.js
CHANGED
@@ -1,6 +1,8 @@
|
|
|
|
|
|
1 |
export class LLM {
|
2 |
constructor() {
|
3 |
-
this.apiKey =
|
4 |
}
|
5 |
|
6 |
async getChatCompletion(systemPrompt, userInput) {
|
|
|
1 |
+
import { MISTRAL_API_KEY } from "../api.js";
|
2 |
+
|
3 |
export class LLM {
|
4 |
constructor() {
|
5 |
+
this.apiKey = MISTRAL_API_KEY;
|
6 |
}
|
7 |
|
8 |
async getChatCompletion(systemPrompt, userInput) {
|
src/shyguy.js
CHANGED
@@ -4,7 +4,7 @@ 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. With Jessica, he talks about algorithms.";
|
8 |
this.lessons_learned = "";
|
9 |
this.conversation_history = "";
|
10 |
this.song_playing = "Let it be";
|
@@ -19,7 +19,7 @@ export class Shyguy {
|
|
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}.
|
23 |
}
|
24 |
}
|
25 |
|
|
|
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. He is super shy.";
|
8 |
this.lessons_learned = "";
|
9 |
this.conversation_history = "";
|
10 |
this.song_playing = "Let it be";
|
|
|
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}. His courage is ${this.courage} on the level 1 to 10. If his courage is higher than 5, he is self-confident. He is really shy and he fears talking with people. It is not easy to persuade him. He doe not want to drink at first.Follow the following lessons: ${this.lessons_learned}`;
|
23 |
}
|
24 |
}
|
25 |
|
src/speech_to_text.js
CHANGED
@@ -1,66 +1,65 @@
|
|
|
|
|
|
1 |
export class SpeechToTextClient {
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
this.mediaRecorder.ondataavailable = (event) => {
|
16 |
-
this.audioChunks.push(event.data);
|
17 |
-
};
|
18 |
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
console.error("Error starting recording:", error);
|
23 |
-
throw error;
|
24 |
-
}
|
25 |
-
}
|
26 |
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
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 |
-
|
|
|
|
|
46 |
try {
|
47 |
-
|
48 |
-
|
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 |
-
|
63 |
-
throw error;
|
64 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
65 |
}
|
|
|
66 |
}
|
|
|
1 |
+
import { HUGGINGFACE_API_KEY } from "../api.js";
|
2 |
+
|
3 |
export class SpeechToTextClient {
|
4 |
+
constructor() {
|
5 |
+
this.apiKey = HUGGINGFACE_API_KEY;
|
6 |
+
this.isRecording = false;
|
7 |
+
this.mediaRecorder = null;
|
8 |
+
this.audioChunks = [];
|
9 |
+
}
|
10 |
|
11 |
+
async startRecording() {
|
12 |
+
try {
|
13 |
+
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
14 |
+
this.mediaRecorder = new MediaRecorder(stream);
|
15 |
+
this.audioChunks = [];
|
|
|
|
|
|
|
|
|
16 |
|
17 |
+
this.mediaRecorder.ondataavailable = (event) => {
|
18 |
+
this.audioChunks.push(event.data);
|
19 |
+
};
|
|
|
|
|
|
|
|
|
20 |
|
21 |
+
this.mediaRecorder.start();
|
22 |
+
this.isRecording = true;
|
23 |
+
} catch (error) {
|
24 |
+
console.error("Error starting recording:", error);
|
25 |
+
throw error;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
26 |
}
|
27 |
+
}
|
28 |
|
29 |
+
async stopRecording() {
|
30 |
+
return new Promise((resolve, reject) => {
|
31 |
+
this.mediaRecorder.onstop = async () => {
|
32 |
try {
|
33 |
+
const audioBlob = new Blob(this.audioChunks, { type: "audio/webm" });
|
34 |
+
const result = await this.transcribeAudio(audioBlob);
|
35 |
+
resolve(result);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
36 |
} catch (error) {
|
37 |
+
reject(error);
|
|
|
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 |
}
|
vite.config.js
CHANGED
@@ -1,6 +1,12 @@
|
|
|
|
|
|
|
|
1 |
export default {
|
|
|
|
|
|
|
2 |
server: {
|
3 |
open: true,
|
4 |
-
allowedHosts: [
|
5 |
},
|
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: ["jakubrada-shyguyswingman.hf.space"],
|
11 |
},
|
12 |
};
|