diff --git a/AudioQnA/front_end/.editorconfig b/AudioQnA/front_end/.editorconfig
new file mode 100644
index 00000000..2b7a6637
--- /dev/null
+++ b/AudioQnA/front_end/.editorconfig
@@ -0,0 +1,10 @@
+[*]
+indent_style = tab
+
+[package.json]
+indent_style = space
+indent_size = 2
+
+[*.md]
+indent_style = space
+indent_size = 2
diff --git a/AudioQnA/front_end/.env b/AudioQnA/front_end/.env
new file mode 100644
index 00000000..2db9ecf3
--- /dev/null
+++ b/AudioQnA/front_end/.env
@@ -0,0 +1,7 @@
+TTS_URL = 'http://x.x.x.x:yyyy'
+
+UPLOAD_URL = 'http://x.x.x.x:yyyy'
+
+CHAT_URL = 'http://x.x.x.x:yyyy'
+
+ASR_URL = 'http://x.x.x.x:yyyy'
diff --git a/AudioQnA/front_end/.eslintignore b/AudioQnA/front_end/.eslintignore
new file mode 100644
index 00000000..38972655
--- /dev/null
+++ b/AudioQnA/front_end/.eslintignore
@@ -0,0 +1,13 @@
+.DS_Store
+node_modules
+/build
+/.svelte-kit
+/package
+.env
+.env.*
+!.env.example
+
+# Ignore files for PNPM, NPM and YARN
+pnpm-lock.yaml
+package-lock.json
+yarn.lock
diff --git a/AudioQnA/front_end/.eslintrc.cjs b/AudioQnA/front_end/.eslintrc.cjs
new file mode 100644
index 00000000..cfe2be4d
--- /dev/null
+++ b/AudioQnA/front_end/.eslintrc.cjs
@@ -0,0 +1,20 @@
+module.exports = {
+ root: true,
+ parser: "@typescript-eslint/parser",
+ extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended", "prettier"],
+ plugins: ["svelte3", "@typescript-eslint", "neverthrow"],
+ ignorePatterns: ["*.cjs"],
+ overrides: [{ files: ["*.svelte"], processor: "svelte3/svelte3" }],
+ settings: {
+ "svelte3/typescript": () => require("typescript"),
+ },
+ parserOptions: {
+ sourceType: "module",
+ ecmaVersion: 2020,
+ },
+ env: {
+ browser: true,
+ es2017: true,
+ node: true,
+ },
+};
diff --git a/AudioQnA/front_end/.prettierignore b/AudioQnA/front_end/.prettierignore
new file mode 100644
index 00000000..38972655
--- /dev/null
+++ b/AudioQnA/front_end/.prettierignore
@@ -0,0 +1,13 @@
+.DS_Store
+node_modules
+/build
+/.svelte-kit
+/package
+.env
+.env.*
+!.env.example
+
+# Ignore files for PNPM, NPM and YARN
+pnpm-lock.yaml
+package-lock.json
+yarn.lock
diff --git a/AudioQnA/front_end/.prettierrc b/AudioQnA/front_end/.prettierrc
new file mode 100644
index 00000000..3b200610
--- /dev/null
+++ b/AudioQnA/front_end/.prettierrc
@@ -0,0 +1,13 @@
+{
+ "pluginSearchDirs": [
+ "."
+ ],
+ "overrides": [
+ {
+ "files": "*.svelte",
+ "options": {
+ "parser": "svelte"
+ }
+ }
+ ]
+}
\ No newline at end of file
diff --git a/AudioQnA/front_end/README.md b/AudioQnA/front_end/README.md
new file mode 100644
index 00000000..6239cb24
--- /dev/null
+++ b/AudioQnA/front_end/README.md
@@ -0,0 +1,36 @@
+
AudioQnA
+
+### 📸 Project Screenshots
+
+![project-screenshot](https://imgur.com/qrt8Lce.png)
+![project-screenshot](https://imgur.com/L12DP8Y.png)
+
+🧐 Features
+
+Here're some of the project's features:
+
+- Start a Talking Chat:Initiate voice chat, able to input voice content, and customize the conversation sound based on the uploaded file.
+- Upload File: Select local upload of voice file. Chat based on the uploaded sound.
+- Scroll to Bottom: The chat automatically slides to the bottom.
+
+🛠️ Get it Running:
+
+1. Clone the repo.
+
+2. cd command to the current folder.
+
+3. Modify the required .env variables.
+
+ ```
+ TTS_URL = ''
+
+ UPLOAD_URL = ''
+
+ CHAT_URL = ''
+
+ ASR_URL = ''
+ ```
+
+4. Execute `npm install` to install the corresponding dependencies.
+
+5. Execute `npm run dev` in both environments
diff --git a/AudioQnA/front_end/package.json b/AudioQnA/front_end/package.json
new file mode 100644
index 00000000..c9a150a9
--- /dev/null
+++ b/AudioQnA/front_end/package.json
@@ -0,0 +1,57 @@
+{
+ "name": "sveltekit-auth-example",
+ "version": "0.0.1",
+ "private": true,
+ "scripts": {
+ "dev": "vite dev --port 5175 --host 0.0.0.0",
+ "build": "vite build",
+ "preview": "vite preview",
+ "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
+ "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
+ "lint": "prettier --check . && eslint .",
+ "format": "prettier --write ."
+ },
+ "devDependencies": {
+ "@fortawesome/free-solid-svg-icons": "6.2.0",
+ "@sveltejs/adapter-auto": "1.0.0-next.75",
+ "@sveltejs/kit": "^1.30.4",
+ "@tailwindcss/typography": "0.5.7",
+ "@types/debug": "4.1.7",
+ "@typescript-eslint/eslint-plugin": "^5.27.0",
+ "@typescript-eslint/parser": "^5.27.0",
+ "autoprefixer": "^10.4.7",
+ "daisyui": "^3.5.0",
+ "debug": "4.3.4",
+ "eslint": "^8.16.0",
+ "eslint-config-prettier": "^8.3.0",
+ "eslint-plugin-neverthrow": "1.1.4",
+ "eslint-plugin-svelte3": "^4.0.0",
+ "neverthrow": "5.0.0",
+ "pocketbase": "0.7.0",
+ "postcss": "^8.4.23",
+ "postcss-load-config": "^4.0.1",
+ "postcss-preset-env": "^8.3.2",
+ "prettier": "^2.8.8",
+ "prettier-plugin-svelte": "^2.7.0",
+ "prettier-plugin-tailwindcss": "^0.3.0",
+ "svelte": "^3.59.1",
+ "svelte-check": "^2.7.1",
+ "svelte-fa": "3.0.3",
+ "svelte-preprocess": "^4.10.7",
+ "tailwindcss": "^3.1.5",
+ "ts-pattern": "4.0.5",
+ "tslib": "^2.3.1",
+ "typescript": "^4.7.4",
+ "vite": "^4.3.9"
+ },
+ "type": "module",
+ "dependencies": {
+ "echarts": "^5.4.2",
+ "flowbite-svelte": "^0.38.5",
+ "fuse": "^0.4.0",
+ "fuse.js": "^6.6.2",
+ "ramda": "^0.29.0",
+ "sse.js": "^0.6.1",
+ "svelte-notifications": "^0.9.98"
+ }
+}
diff --git a/AudioQnA/front_end/postcss.config.cjs b/AudioQnA/front_end/postcss.config.cjs
new file mode 100644
index 00000000..e68d4de2
--- /dev/null
+++ b/AudioQnA/front_end/postcss.config.cjs
@@ -0,0 +1,13 @@
+const tailwindcss = require("tailwindcss");
+const autoprefixer = require("autoprefixer");
+
+const config = {
+ plugins: [
+ //Some plugins, like tailwindcss/nesting, need to run before Tailwind,
+ tailwindcss(),
+ //But others, like autoprefixer, need to run after,
+ autoprefixer,
+ ],
+};
+
+module.exports = config;
diff --git a/AudioQnA/front_end/src/app.d.ts b/AudioQnA/front_end/src/app.d.ts
new file mode 100644
index 00000000..52e4acd9
--- /dev/null
+++ b/AudioQnA/front_end/src/app.d.ts
@@ -0,0 +1,16 @@
+// See: https://kit.svelte.dev/docs/types#app
+// import { Result} from "neverthrow";
+
+declare namespace App {
+ interface Locals {
+ user?: User;
+ }
+ // interface PageData { }
+ // interface PageError {}
+ // interface Platform {}
+}
+
+interface ChatMessage {
+ role: string;
+ content: string;
+}
diff --git a/AudioQnA/front_end/src/app.html b/AudioQnA/front_end/src/app.html
new file mode 100644
index 00000000..ba848b25
--- /dev/null
+++ b/AudioQnA/front_end/src/app.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ %sveltekit.head%
+
+
+ %sveltekit.body%
+
+
diff --git a/AudioQnA/front_end/src/app.postcss b/AudioQnA/front_end/src/app.postcss
new file mode 100644
index 00000000..c3e0519c
--- /dev/null
+++ b/AudioQnA/front_end/src/app.postcss
@@ -0,0 +1,82 @@
+/* Write your global styles here, in PostCSS syntax */
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+.btn {
+ @apply flex-nowrap;
+}
+a.btn {
+ @apply no-underline;
+}
+.input {
+ @apply text-base;
+}
+
+.bg-dark-blue {
+ background-color: #004a86;
+}
+
+.bg-light-blue {
+ background-color: #0068b5;
+}
+
+.bg-turquoise {
+ background-color: #00a3f6;
+}
+
+.bg-header {
+ background-color: #ffffff;
+}
+
+.bg-button {
+ background-color: #0068b5;
+}
+
+.bg-title {
+ background-color: #f7f7f7;
+}
+
+.text-header {
+ color: #0068b5;
+}
+
+.text-button {
+ color: #0071c5;
+}
+
+.text-title-color {
+ color: rgb(38,38,38);
+}
+
+.font-intel {
+ font-family: "intel-clear","tahoma",Helvetica,"helvetica",Arial,sans-serif;
+}
+
+.font-title-intel {
+ font-family: "intel-one","intel-clear",Helvetica,Arial,sans-serif;
+}
+
+.bg-footer {
+ background-color: #e7e7e7;
+}
+
+.bg-light-green {
+ background-color: #d7f3a1;
+}
+
+.bg-purple {
+ background-color: #653171;
+}
+
+.bg-dark-blue {
+ background-color: #224678;
+}
+
+.border-input-color {
+ border-color: #605e5c;
+}
+
+.w-12\/12 {
+ width: 100%
+}
\ No newline at end of file
diff --git a/AudioQnA/front_end/src/lib/assets/icons/png/audio1.png b/AudioQnA/front_end/src/lib/assets/icons/png/audio1.png
new file mode 100644
index 00000000..8733bdb9
Binary files /dev/null and b/AudioQnA/front_end/src/lib/assets/icons/png/audio1.png differ
diff --git a/AudioQnA/front_end/src/lib/assets/icons/png/audio2.png b/AudioQnA/front_end/src/lib/assets/icons/png/audio2.png
new file mode 100644
index 00000000..063a0a7f
Binary files /dev/null and b/AudioQnA/front_end/src/lib/assets/icons/png/audio2.png differ
diff --git a/AudioQnA/front_end/src/lib/assets/icons/svelte/arrow-path-icon.svelte b/AudioQnA/front_end/src/lib/assets/icons/svelte/arrow-path-icon.svelte
new file mode 100644
index 00000000..758e665d
--- /dev/null
+++ b/AudioQnA/front_end/src/lib/assets/icons/svelte/arrow-path-icon.svelte
@@ -0,0 +1,20 @@
+
+
+
+
+
diff --git a/AudioQnA/front_end/src/lib/assets/icons/svelte/assistant.svelte b/AudioQnA/front_end/src/lib/assets/icons/svelte/assistant.svelte
new file mode 100644
index 00000000..582baadd
--- /dev/null
+++ b/AudioQnA/front_end/src/lib/assets/icons/svelte/assistant.svelte
@@ -0,0 +1 @@
+
diff --git a/AudioQnA/front_end/src/lib/assets/icons/svelte/chat-bubble-left-icon.svelte b/AudioQnA/front_end/src/lib/assets/icons/svelte/chat-bubble-left-icon.svelte
new file mode 100644
index 00000000..e5b725bd
--- /dev/null
+++ b/AudioQnA/front_end/src/lib/assets/icons/svelte/chat-bubble-left-icon.svelte
@@ -0,0 +1,20 @@
+
+
+
+
+
diff --git a/AudioQnA/front_end/src/lib/assets/icons/svelte/chat.svelte b/AudioQnA/front_end/src/lib/assets/icons/svelte/chat.svelte
new file mode 100644
index 00000000..1ef266fb
--- /dev/null
+++ b/AudioQnA/front_end/src/lib/assets/icons/svelte/chat.svelte
@@ -0,0 +1 @@
+
diff --git a/AudioQnA/front_end/src/lib/assets/icons/svelte/check-icon.svelte b/AudioQnA/front_end/src/lib/assets/icons/svelte/check-icon.svelte
new file mode 100644
index 00000000..9794ad7e
--- /dev/null
+++ b/AudioQnA/front_end/src/lib/assets/icons/svelte/check-icon.svelte
@@ -0,0 +1,20 @@
+
+
+
+
+
diff --git a/AudioQnA/front_end/src/lib/assets/icons/svelte/intel.svelte b/AudioQnA/front_end/src/lib/assets/icons/svelte/intel.svelte
new file mode 100644
index 00000000..50039d5b
--- /dev/null
+++ b/AudioQnA/front_end/src/lib/assets/icons/svelte/intel.svelte
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
diff --git a/AudioQnA/front_end/src/lib/assets/icons/svelte/loading-button-spinner-icon.svelte b/AudioQnA/front_end/src/lib/assets/icons/svelte/loading-button-spinner-icon.svelte
new file mode 100644
index 00000000..0bd0526a
--- /dev/null
+++ b/AudioQnA/front_end/src/lib/assets/icons/svelte/loading-button-spinner-icon.svelte
@@ -0,0 +1,20 @@
+
+
+
+
diff --git a/AudioQnA/front_end/src/lib/assets/icons/svelte/message-avatar.svelte b/AudioQnA/front_end/src/lib/assets/icons/svelte/message-avatar.svelte
new file mode 100644
index 00000000..b5eb81d8
--- /dev/null
+++ b/AudioQnA/front_end/src/lib/assets/icons/svelte/message-avatar.svelte
@@ -0,0 +1,12 @@
+
+
+{#if role === "Human"}
+
+{:else}
+
+{/if}
diff --git a/AudioQnA/front_end/src/lib/assets/icons/svelte/plus-icon.svelte b/AudioQnA/front_end/src/lib/assets/icons/svelte/plus-icon.svelte
new file mode 100644
index 00000000..3b302851
--- /dev/null
+++ b/AudioQnA/front_end/src/lib/assets/icons/svelte/plus-icon.svelte
@@ -0,0 +1,22 @@
+
+
+
+
+
diff --git a/AudioQnA/front_end/src/lib/assets/icons/svelte/portrait.svelte b/AudioQnA/front_end/src/lib/assets/icons/svelte/portrait.svelte
new file mode 100644
index 00000000..de21c325
--- /dev/null
+++ b/AudioQnA/front_end/src/lib/assets/icons/svelte/portrait.svelte
@@ -0,0 +1,15 @@
+
diff --git a/AudioQnA/front_end/src/lib/assets/icons/svelte/voice-button.svelte b/AudioQnA/front_end/src/lib/assets/icons/svelte/voice-button.svelte
new file mode 100644
index 00000000..17b8e0b5
--- /dev/null
+++ b/AudioQnA/front_end/src/lib/assets/icons/svelte/voice-button.svelte
@@ -0,0 +1,163 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/AudioQnA/front_end/src/lib/assets/icons/svelte/x-mark-icon.svelte b/AudioQnA/front_end/src/lib/assets/icons/svelte/x-mark-icon.svelte
new file mode 100644
index 00000000..a347296f
--- /dev/null
+++ b/AudioQnA/front_end/src/lib/assets/icons/svelte/x-mark-icon.svelte
@@ -0,0 +1,20 @@
+
+
+
+
+
diff --git a/AudioQnA/front_end/src/lib/assets/icons/svg/1.svg b/AudioQnA/front_end/src/lib/assets/icons/svg/1.svg
new file mode 100644
index 00000000..38adea6f
--- /dev/null
+++ b/AudioQnA/front_end/src/lib/assets/icons/svg/1.svg
@@ -0,0 +1,92 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AudioQnA/front_end/src/lib/assets/icons/svg/2.svg b/AudioQnA/front_end/src/lib/assets/icons/svg/2.svg
new file mode 100644
index 00000000..0e6150e4
--- /dev/null
+++ b/AudioQnA/front_end/src/lib/assets/icons/svg/2.svg
@@ -0,0 +1,92 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AudioQnA/front_end/src/lib/assets/icons/svg/3.svg b/AudioQnA/front_end/src/lib/assets/icons/svg/3.svg
new file mode 100644
index 00000000..3ed7f7fc
--- /dev/null
+++ b/AudioQnA/front_end/src/lib/assets/icons/svg/3.svg
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AudioQnA/front_end/src/lib/assets/icons/svg/4.svg b/AudioQnA/front_end/src/lib/assets/icons/svg/4.svg
new file mode 100644
index 00000000..2b34e86b
--- /dev/null
+++ b/AudioQnA/front_end/src/lib/assets/icons/svg/4.svg
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AudioQnA/front_end/src/lib/assets/icons/svg/5.svg b/AudioQnA/front_end/src/lib/assets/icons/svg/5.svg
new file mode 100644
index 00000000..718f3b30
--- /dev/null
+++ b/AudioQnA/front_end/src/lib/assets/icons/svg/5.svg
@@ -0,0 +1,92 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/AudioQnA/front_end/src/lib/assets/icons/svg/Voice-Wave - Dark.svg b/AudioQnA/front_end/src/lib/assets/icons/svg/Voice-Wave - Dark.svg
new file mode 100644
index 00000000..53388b9c
--- /dev/null
+++ b/AudioQnA/front_end/src/lib/assets/icons/svg/Voice-Wave - Dark.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/AudioQnA/front_end/src/lib/assets/icons/svg/stop-recording.svg b/AudioQnA/front_end/src/lib/assets/icons/svg/stop-recording.svg
new file mode 100644
index 00000000..4f4e638b
--- /dev/null
+++ b/AudioQnA/front_end/src/lib/assets/icons/svg/stop-recording.svg
@@ -0,0 +1,6 @@
+
+
+
\ No newline at end of file
diff --git a/AudioQnA/front_end/src/lib/assets/icons/svg/upload.svg b/AudioQnA/front_end/src/lib/assets/icons/svg/upload.svg
new file mode 100644
index 00000000..55790f05
--- /dev/null
+++ b/AudioQnA/front_end/src/lib/assets/icons/svg/upload.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/AudioQnA/front_end/src/lib/assets/icons/svg/voice.svg b/AudioQnA/front_end/src/lib/assets/icons/svg/voice.svg
new file mode 100644
index 00000000..0cc1d520
--- /dev/null
+++ b/AudioQnA/front_end/src/lib/assets/icons/svg/voice.svg
@@ -0,0 +1,9 @@
+
+
+
+
\ No newline at end of file
diff --git a/AudioQnA/front_end/src/lib/assets/icons/svg/voiceOff.svg b/AudioQnA/front_end/src/lib/assets/icons/svg/voiceOff.svg
new file mode 100644
index 00000000..8161062a
--- /dev/null
+++ b/AudioQnA/front_end/src/lib/assets/icons/svg/voiceOff.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/AudioQnA/front_end/src/lib/assets/icons/svg/voiceOn.svg b/AudioQnA/front_end/src/lib/assets/icons/svg/voiceOn.svg
new file mode 100644
index 00000000..aeb96fab
--- /dev/null
+++ b/AudioQnA/front_end/src/lib/assets/icons/svg/voiceOn.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/AudioQnA/front_end/src/lib/common/sse.d.ts b/AudioQnA/front_end/src/lib/common/sse.d.ts
new file mode 100644
index 00000000..4980f9e7
--- /dev/null
+++ b/AudioQnA/front_end/src/lib/common/sse.d.ts
@@ -0,0 +1,12 @@
+declare module "sse.js" {
+ export type SSEOptions = EventSourceInit & {
+ headers?: Record;
+ payload?: string;
+ method?: string;
+ };
+
+ export class SSE extends EventSource {
+ constructor(url: string | URL, sseOptions?: SSEOptions);
+ stream(): void;
+ }
+}
diff --git a/AudioQnA/front_end/src/lib/common/timediff.ts b/AudioQnA/front_end/src/lib/common/timediff.ts
new file mode 100644
index 00000000..111664de
--- /dev/null
+++ b/AudioQnA/front_end/src/lib/common/timediff.ts
@@ -0,0 +1,23 @@
+export default function timeDifference(current: number, previous: number) {
+ const msPerMinute = 60 * 1000;
+ const msPerHour = msPerMinute * 60;
+ const msPerDay = msPerHour * 24;
+ const msPerMonth = msPerDay * 30;
+ const msPerYear = msPerDay * 365;
+
+ const elapsed = current - previous;
+
+ if (elapsed < msPerMinute) {
+ return Math.round(elapsed / 1000) + " seconds ago";
+ } else if (elapsed < msPerHour) {
+ return Math.round(elapsed / msPerMinute) + " minutes ago";
+ } else if (elapsed < msPerDay) {
+ return Math.round(elapsed / msPerHour) + " hours ago";
+ } else if (elapsed < msPerMonth) {
+ return "approximately " + Math.round(elapsed / msPerDay) + " days ago";
+ } else if (elapsed < msPerYear) {
+ return "approximately " + Math.round(elapsed / msPerMonth) + " months ago";
+ } else {
+ return "approximately " + Math.round(elapsed / msPerYear) + " years ago";
+ }
+}
diff --git a/AudioQnA/front_end/src/lib/components/layout.svelte b/AudioQnA/front_end/src/lib/components/layout.svelte
new file mode 100644
index 00000000..1644a52a
--- /dev/null
+++ b/AudioQnA/front_end/src/lib/components/layout.svelte
@@ -0,0 +1,21 @@
+
+
+
diff --git a/AudioQnA/front_end/src/lib/components/shared/shared-utils.ts b/AudioQnA/front_end/src/lib/components/shared/shared-utils.ts
new file mode 100644
index 00000000..2d959e3e
--- /dev/null
+++ b/AudioQnA/front_end/src/lib/components/shared/shared-utils.ts
@@ -0,0 +1,12 @@
+export function scrollToBottom(scrollToDiv: HTMLElement) {
+ if (scrollToDiv) {
+ setTimeout(
+ () =>
+ scrollToDiv.scroll({
+ behavior: "auto",
+ top: scrollToDiv.scrollHeight,
+ }),
+ 300,
+ );
+ }
+}
diff --git a/AudioQnA/front_end/src/lib/components/shared/shared.store.ts b/AudioQnA/front_end/src/lib/components/shared/shared.store.ts
new file mode 100644
index 00000000..32552df2
--- /dev/null
+++ b/AudioQnA/front_end/src/lib/components/shared/shared.store.ts
@@ -0,0 +1,18 @@
+import { derived, writable } from "svelte/store";
+
+import type { Chat, ChatListItem } from "./shared.type";
+
+/**
+ * Banners
+ */
+export const banners$ = writable([] as any);
+
+export const hasBanners$ = derived(banners$, (banners) => {
+ return banners.length > 0;
+});
+
+/**
+ * localStorage
+ */
+export const chatList$ = writable([] as ChatListItem[]);
+export const chats$ = writable({} as Record);
diff --git a/AudioQnA/front_end/src/lib/components/shared/shared.type.ts b/AudioQnA/front_end/src/lib/components/shared/shared.type.ts
new file mode 100644
index 00000000..141980db
--- /dev/null
+++ b/AudioQnA/front_end/src/lib/components/shared/shared.type.ts
@@ -0,0 +1,76 @@
+export interface ModelOptionType {
+ names: string[];
+ options: {
+ label: string;
+ value: number;
+ minRange: number;
+ maxRange: number;
+ step: number;
+ type: string;
+ }[];
+}
+
+export interface SelectedType {
+ [key: string]: string;
+ Model: string;
+ "knowledge base": string;
+ "advance option": string;
+}
+
+export enum LOCAL_STORAGE_KEY {
+ OPEN_AI_API_KEY = "openAiApiKey",
+ CHAT_LIST = "bChatList",
+ GPT_MODEL = "bGptModel",
+}
+
+export enum MESSAGE_ROLE {
+ SYSTEM = "system",
+ ASSISTANT = "assistant",
+ USER = "user",
+ HUMAN = "Human",
+}
+
+export enum BANNER_TYPE {
+ ERROR = "error",
+ INFO = "info",
+ WARNING = "warning",
+ SUCCESS = "success",
+}
+
+export enum ERROR {
+ LOCAL_STORAGE_SET_ITEM = "LOCAL_STORAGE_SET_ITEM",
+ OPENAI_CHAT_COMPLETION = "OPENAI_CHAT_COMPLETION",
+ REGISTRATION = "REGISTRATION",
+ LOGIN = "LOGIN",
+ PASSWORD_RESET = "PASSWORD_RESET",
+ USER_DATA_FETCH = "USER_DATA_FETCH",
+ PASSWORD_CHANGE = "PASSWORD_CHANGE",
+ CHECKOUT_SESSION_CREATE = "CHECKOUT_SESSION_CREATE",
+ DATA_SYNC_SAVE = "CHAT_SYNC_SAVE",
+ DATA_SYNC_SAVE_LIMIT = "CHAT_SYNC_SAVE_LIMIT",
+ DATA_SYNC_IMPORT = "CHAT_SYNC_IMPORT",
+ DATA_SYNC_DELETE_SAVED_CHAT = "CHAT_SYNC_DELETE_SAVED_CHAT",
+}
+
+export type Message = {
+ role: MESSAGE_ROLE;
+ content: string;
+};
+
+export type ChatListItem = {
+ chatId: string;
+ title: string;
+};
+
+export type Chat = {
+ chatId: string;
+ messages: Message[];
+};
+
+// In-memory only
+export type Banner = {
+ bannerId: string;
+ bannerType: BANNER_TYPE;
+ title: string;
+ description: string;
+};
diff --git a/AudioQnA/front_end/src/lib/components/talkbot/store.ts b/AudioQnA/front_end/src/lib/components/talkbot/store.ts
new file mode 100644
index 00000000..44117a23
--- /dev/null
+++ b/AudioQnA/front_end/src/lib/components/talkbot/store.ts
@@ -0,0 +1,3 @@
+import { writable } from "svelte/store";
+
+export const uploadName = writable("");
diff --git a/AudioQnA/front_end/src/lib/components/talkbot/upload-voice.svelte b/AudioQnA/front_end/src/lib/components/talkbot/upload-voice.svelte
new file mode 100644
index 00000000..411d1bd8
--- /dev/null
+++ b/AudioQnA/front_end/src/lib/components/talkbot/upload-voice.svelte
@@ -0,0 +1,61 @@
+
+
+
+
+ {#if loading}
+
+
uploading
+ {:else}
+
+
{$uploadName}
+ {/if}
+
+
+
+
+
+
diff --git a/AudioQnA/front_end/src/lib/components/talkbot/voice-button.svelte b/AudioQnA/front_end/src/lib/components/talkbot/voice-button.svelte
new file mode 100644
index 00000000..0bfe5bee
--- /dev/null
+++ b/AudioQnA/front_end/src/lib/components/talkbot/voice-button.svelte
@@ -0,0 +1,104 @@
+
+
+
+
+
+ {#if isRecording}
+
+ {:else}
+
+ {/if}
+
+{displayTimer(voiceTimer)}
diff --git a/AudioQnA/front_end/src/lib/components/talkbot/voice-wave.svelte b/AudioQnA/front_end/src/lib/components/talkbot/voice-wave.svelte
new file mode 100644
index 00000000..5e2320a4
--- /dev/null
+++ b/AudioQnA/front_end/src/lib/components/talkbot/voice-wave.svelte
@@ -0,0 +1,45 @@
+
+
+{#if running}
+
+{/if}
+
+
diff --git a/AudioQnA/front_end/src/lib/components/topnavigation/Index.svelte b/AudioQnA/front_end/src/lib/components/topnavigation/Index.svelte
new file mode 100644
index 00000000..8e0a81ac
--- /dev/null
+++ b/AudioQnA/front_end/src/lib/components/topnavigation/Index.svelte
@@ -0,0 +1,19 @@
+
+
+
diff --git a/AudioQnA/front_end/src/lib/modules/chat/chat-audio.svelte b/AudioQnA/front_end/src/lib/modules/chat/chat-audio.svelte
new file mode 100644
index 00000000..80d4b691
--- /dev/null
+++ b/AudioQnA/front_end/src/lib/modules/chat/chat-audio.svelte
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/AudioQnA/front_end/src/lib/modules/chat/chat-message.svelte b/AudioQnA/front_end/src/lib/modules/chat/chat-message.svelte
new file mode 100644
index 00000000..bc706b00
--- /dev/null
+++ b/AudioQnA/front_end/src/lib/modules/chat/chat-message.svelte
@@ -0,0 +1,55 @@
+
+
+
+ {#if type === "Assistant" || type === "assistant" || type === "system"}
+
+
+ {/if}
+
+
+ {#if message.includes("blob:")}
+
+ {:else}
+
{message}
+ {/if}
+
+ {#if displayTimer}
+
+ {/if}
+
+ {#if type === "Human" || type === "user"}
+
+
+ {/if}
+
+
+
diff --git a/AudioQnA/front_end/src/lib/modules/chat/message-timer.svelte b/AudioQnA/front_end/src/lib/modules/chat/message-timer.svelte
new file mode 100644
index 00000000..650fc3b1
--- /dev/null
+++ b/AudioQnA/front_end/src/lib/modules/chat/message-timer.svelte
@@ -0,0 +1,15 @@
+
+
+{messageTimer}
diff --git a/AudioQnA/front_end/src/lib/modules/chat/network.ts b/AudioQnA/front_end/src/lib/modules/chat/network.ts
new file mode 100644
index 00000000..8440d472
--- /dev/null
+++ b/AudioQnA/front_end/src/lib/modules/chat/network.ts
@@ -0,0 +1,81 @@
+import { SSE } from "sse.js";
+import { env } from "$env/dynamic/public";
+
+// upload, tts
+const TTS_URL = env.TTS_URL;
+const CHAT_URL = env.CHAT_URL;
+const ASR_URL = env.ASR_URL;
+const UPLOAD_URL = env.UPLOAD_URL;
+
+export async function fetchAudioText(file) {
+ const url = `${ASR_URL}`;
+ const formData = new FormData();
+ formData.append("file", file);
+ const init: RequestInit = {
+ method: "POST",
+ body: formData,
+ };
+
+ try {
+ const response = await fetch(url, init);
+ if (!response.ok) throw response.status;
+ return await response.json();
+ } catch (error) {
+ console.error("network error: ", error);
+ return undefined;
+ }
+}
+
+export async function fetchAudioStream(text) {
+ const url = `${TTS_URL}`;
+ const bodyData = {
+ text: text,
+ text_language: "auto",
+ };
+
+ return new SSE(url, {
+ headers: { "Content-Type": "application/json" },
+ payload: JSON.stringify(bodyData),
+ });
+}
+
+export async function fetchAudioEmbedding(file, text: string) {
+ const url = `${UPLOAD_URL}`;
+ const formData = new FormData();
+ formData.append("default_refer_file", file);
+ formData.append("default_refer_text", text);
+ formData.append("default_refer_language", "en");
+ const init: RequestInit = {
+ method: "POST",
+ body: formData,
+ };
+
+ try {
+ const response = await fetch(url, init);
+ if (!response.ok) throw response.status;
+ return await response.json();
+ } catch (error) {
+ console.error("network error: ", error);
+ return undefined;
+ }
+}
+
+export async function fetchTextResponse(query) {
+ const url = `${CHAT_URL}`;
+ const bodyData = {
+ query: query,
+ };
+ const init: RequestInit = {
+ method: "POST",
+ body: JSON.stringify(bodyData),
+ };
+
+ try {
+ const response = await fetch(url, init);
+ if (!response.ok) throw response.status;
+ return await response.json();
+ } catch (error) {
+ console.error("network error: ", error);
+ return undefined;
+ }
+}
diff --git a/AudioQnA/front_end/src/routes/+layout.svelte b/AudioQnA/front_end/src/routes/+layout.svelte
new file mode 100644
index 00000000..735f5634
--- /dev/null
+++ b/AudioQnA/front_end/src/routes/+layout.svelte
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
diff --git a/AudioQnA/front_end/src/routes/+page.svelte b/AudioQnA/front_end/src/routes/+page.svelte
new file mode 100644
index 00000000..fb8ed5be
--- /dev/null
+++ b/AudioQnA/front_end/src/routes/+page.svelte
@@ -0,0 +1,128 @@
+
+
+
+ Neural Chat
+
+
+
+
+
+
+
+ {#each chatMessages as message}
+
+ {/each}
+
+
+
+
+ {#if loading}
+
+
+
+
+
+
AudioQnA is thinking...
+
+ {/if}
+
+
+ {#if enableRegenerateMessage && enableRegenerate}
+
{
+ handleSubmit((enableRegenerate = true));
+ }}
+ type="button"
+ class="mx-auto mb-1 flex w-48 items-center justify-center gap-2 self-center whitespace-nowrap rounded-md bg-white px-3 py-2 text-sm text-gray-700 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50"
+ >
+
+ Regenerate response
+
+ {/if}
+
+
+
+ {handleSubmit()}} />
+
+
+
+
diff --git a/AudioQnA/front_end/static/favicon.png b/AudioQnA/front_end/static/favicon.png
new file mode 100644
index 00000000..75b997f8
Binary files /dev/null and b/AudioQnA/front_end/static/favicon.png differ
diff --git a/AudioQnA/front_end/svelte.config.js b/AudioQnA/front_end/svelte.config.js
new file mode 100644
index 00000000..a3a43f16
--- /dev/null
+++ b/AudioQnA/front_end/svelte.config.js
@@ -0,0 +1,24 @@
+import adapter from "@sveltejs/adapter-auto";
+import preprocess from "svelte-preprocess";
+import postcssPresetEnv from "postcss-preset-env";
+
+/** @type {import('@sveltejs/kit').Config} */
+const config = {
+ // Consult https://github.com/sveltejs/svelte-preprocess
+ // for more information about preprocessors
+ preprocess: preprocess({
+ sourceMap: true,
+ postcss: {
+ plugins: [postcssPresetEnv({ features: { "nesting-rules": true } })],
+ },
+ }),
+
+ kit: {
+ adapter: adapter(),
+ env: {
+ publicPrefix: "",
+ },
+ },
+};
+
+export default config;
diff --git a/AudioQnA/front_end/tailwind.config.cjs b/AudioQnA/front_end/tailwind.config.cjs
new file mode 100644
index 00000000..071a804d
--- /dev/null
+++ b/AudioQnA/front_end/tailwind.config.cjs
@@ -0,0 +1,11 @@
+const config = {
+ content: ["./src/**/*.{html,js,svelte,ts}"],
+
+ theme: {
+ extend: {},
+ },
+
+ plugins: [require("daisyui"), require("@tailwindcss/typography")],
+};
+
+module.exports = config;
diff --git a/AudioQnA/front_end/tsconfig.json b/AudioQnA/front_end/tsconfig.json
new file mode 100644
index 00000000..0f47472f
--- /dev/null
+++ b/AudioQnA/front_end/tsconfig.json
@@ -0,0 +1,13 @@
+{
+ "extends": "./.svelte-kit/tsconfig.json",
+ "compilerOptions": {
+ "allowJs": true,
+ "checkJs": true,
+ "esModuleInterop": true,
+ "forceConsistentCasingInFileNames": true,
+ "resolveJsonModule": true,
+ "skipLibCheck": true,
+ "sourceMap": true,
+ "strict": true
+ }
+}
diff --git a/AudioQnA/front_end/vite.config.ts b/AudioQnA/front_end/vite.config.ts
new file mode 100644
index 00000000..013d0297
--- /dev/null
+++ b/AudioQnA/front_end/vite.config.ts
@@ -0,0 +1,8 @@
+import { sveltekit } from "@sveltejs/kit/vite";
+import type { UserConfig } from "vite";
+
+const config: UserConfig = {
+ plugins: [sveltekit()],
+};
+
+export default config;