Removed V1 definetely
2
.gitmodules
vendored
@ -14,7 +14,7 @@
|
|||||||
path = zoos/models_zoo
|
path = zoos/models_zoo
|
||||||
url = https://github.com/ParisNeo/models_zoo.git
|
url = https://github.com/ParisNeo/models_zoo.git
|
||||||
branch = main
|
branch = main
|
||||||
[submodule "lollms"]
|
[submodule "lollms_core"]
|
||||||
path = lollms_core
|
path = lollms_core
|
||||||
url = https://github.com/ParisNeo/lollms.git
|
url = https://github.com/ParisNeo/lollms.git
|
||||||
branch = main
|
branch = main
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 6f583fe3164d389fbcc91617e5b58b21cb9c33a6
|
Subproject commit ec5b4bd018067af50a0cb2e6c06d3dbfbad88de8
|
@ -1,62 +0,0 @@
|
|||||||
/* Wait animation */
|
|
||||||
.lds-facebook {
|
|
||||||
display: inline-block;
|
|
||||||
position: relative;
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
}
|
|
||||||
.lds-facebook div {
|
|
||||||
display: inline-block;
|
|
||||||
position: absolute;
|
|
||||||
left: 8px;
|
|
||||||
width: 8px;
|
|
||||||
background: #fff;
|
|
||||||
animation: lds-facebook 1.2s cubic-bezier(0, 0.5, 0.5, 1) infinite;
|
|
||||||
}
|
|
||||||
.lds-facebook div:nth-child(1) {
|
|
||||||
left: 4px;
|
|
||||||
animation-delay: -0.24s;
|
|
||||||
}
|
|
||||||
.lds-facebook div:nth-child(2) {
|
|
||||||
left: 16px;
|
|
||||||
animation-delay: -0.12s;
|
|
||||||
}
|
|
||||||
.lds-facebook div:nth-child(3) {
|
|
||||||
left: 28px;
|
|
||||||
animation-delay: 0;
|
|
||||||
}
|
|
||||||
@keyframes lds-facebook {
|
|
||||||
0% {
|
|
||||||
top: 8px;
|
|
||||||
height: 34px;
|
|
||||||
}
|
|
||||||
50%, 100% {
|
|
||||||
top: 12px;
|
|
||||||
height: 18px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.activeDiscussion {
|
|
||||||
background-color: #16a34a; /*Equivalent to bg-green-600*/
|
|
||||||
}
|
|
||||||
|
|
||||||
:root {
|
|
||||||
--color-primary-light: #ffffff;
|
|
||||||
--color-secondary-light: #f2f2f2;
|
|
||||||
|
|
||||||
--color-primary-dark: #1a1a1a;
|
|
||||||
--color-secondary-dark: #333333;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Default light mode styles */
|
|
||||||
.text-primary {
|
|
||||||
color: var(--color-primary-light);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Dark mode styles */
|
|
||||||
@media (prefers-color-scheme: dark) {
|
|
||||||
.mode-dark .text-primary {
|
|
||||||
color: var(--color-primary-dark);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
|||||||
/* Style for the help page */
|
|
||||||
.container {
|
|
||||||
max-width: 960px;
|
|
||||||
margin: 0 auto;
|
|
||||||
padding: 0 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-title {
|
|
||||||
margin-top: 2rem;
|
|
||||||
margin-bottom: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-title h2 {
|
|
||||||
font-size: 2.5rem;
|
|
||||||
font-weight: bold;
|
|
||||||
text-transform: uppercase;
|
|
||||||
letter-spacing: 0.1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-title p {
|
|
||||||
font-size: 1.125rem;
|
|
||||||
font-weight: 300;
|
|
||||||
}
|
|
||||||
|
|
||||||
.list-disc,
|
|
||||||
.list-decimal {
|
|
||||||
margin-left: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.list-inside {
|
|
||||||
margin-left: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.faq dt {
|
|
||||||
font-weight: bold;
|
|
||||||
margin-top: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.faq dd {
|
|
||||||
margin-left: 0;
|
|
||||||
}
|
|
||||||
|
|
261947
static/css/tailwind-dark.css
1
static/css/tailwind-dark.min.css
vendored
1
static/css/tailwind.min.css
vendored
@ -1,805 +0,0 @@
|
|||||||
/*
|
|
||||||
! tailwindcss v3.1.4 | MIT License | https://tailwindcss.com
|
|
||||||
*//*
|
|
||||||
1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
|
|
||||||
2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
|
|
||||||
*/
|
|
||||||
|
|
||||||
*,
|
|
||||||
::before,
|
|
||||||
::after {
|
|
||||||
box-sizing: border-box; /* 1 */
|
|
||||||
border-width: 0; /* 2 */
|
|
||||||
border-style: solid; /* 2 */
|
|
||||||
border-color: #e5e7eb; /* 2 */
|
|
||||||
}
|
|
||||||
|
|
||||||
::before,
|
|
||||||
::after {
|
|
||||||
--tw-content: '';
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
1. Use a consistent sensible line-height in all browsers.
|
|
||||||
2. Prevent adjustments of font size after orientation changes in iOS.
|
|
||||||
3. Use a more readable tab size.
|
|
||||||
4. Use the user's configured `sans` font-family by default.
|
|
||||||
*/
|
|
||||||
|
|
||||||
html {
|
|
||||||
line-height: 1.5; /* 1 */
|
|
||||||
-webkit-text-size-adjust: 100%; /* 2 */
|
|
||||||
-moz-tab-size: 4; /* 3 */
|
|
||||||
-o-tab-size: 4;
|
|
||||||
tab-size: 4; /* 3 */
|
|
||||||
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; /* 4 */
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
1. Remove the margin in all browsers.
|
|
||||||
2. Inherit line-height from `html` so users can set them as a class directly on the `html` element.
|
|
||||||
*/
|
|
||||||
|
|
||||||
body {
|
|
||||||
margin: 0; /* 1 */
|
|
||||||
line-height: inherit; /* 2 */
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
1. Add the correct height in Firefox.
|
|
||||||
2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655)
|
|
||||||
3. Ensure horizontal rules are visible by default.
|
|
||||||
*/
|
|
||||||
|
|
||||||
hr {
|
|
||||||
height: 0; /* 1 */
|
|
||||||
color: inherit; /* 2 */
|
|
||||||
border-top-width: 1px; /* 3 */
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Add the correct text decoration in Chrome, Edge, and Safari.
|
|
||||||
*/
|
|
||||||
|
|
||||||
abbr:where([title]) {
|
|
||||||
-webkit-text-decoration: underline dotted;
|
|
||||||
text-decoration: underline dotted;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Remove the default font size and weight for headings.
|
|
||||||
*/
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 36px;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
h2,
|
|
||||||
h3,
|
|
||||||
h4,
|
|
||||||
h5,
|
|
||||||
h6 {
|
|
||||||
font-size: inherit;
|
|
||||||
font-weight: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Reset links to optimize for opt-in styling instead of opt-out.
|
|
||||||
*/
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: inherit;
|
|
||||||
text-decoration: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Add the correct font weight in Edge and Safari.
|
|
||||||
*/
|
|
||||||
|
|
||||||
b,
|
|
||||||
strong {
|
|
||||||
font-weight: bolder;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
1. Use the user's configured `mono` font family by default.
|
|
||||||
2. Correct the odd `em` font sizing in all browsers.
|
|
||||||
*/
|
|
||||||
|
|
||||||
code,
|
|
||||||
kbd,
|
|
||||||
samp,
|
|
||||||
pre {
|
|
||||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; /* 1 */
|
|
||||||
font-size: 1em; /* 2 */
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Add the correct font size in all browsers.
|
|
||||||
*/
|
|
||||||
|
|
||||||
small {
|
|
||||||
font-size: 80%;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Prevent `sub` and `sup` elements from affecting the line height in all browsers.
|
|
||||||
*/
|
|
||||||
|
|
||||||
sub,
|
|
||||||
sup {
|
|
||||||
font-size: 75%;
|
|
||||||
line-height: 0;
|
|
||||||
position: relative;
|
|
||||||
vertical-align: baseline;
|
|
||||||
}
|
|
||||||
|
|
||||||
sub {
|
|
||||||
bottom: -0.25em;
|
|
||||||
}
|
|
||||||
|
|
||||||
sup {
|
|
||||||
top: -0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297)
|
|
||||||
2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016)
|
|
||||||
3. Remove gaps between table borders by default.
|
|
||||||
*/
|
|
||||||
|
|
||||||
table {
|
|
||||||
text-indent: 0; /* 1 */
|
|
||||||
border-color: inherit; /* 2 */
|
|
||||||
border-collapse: collapse; /* 3 */
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
1. Change the font styles in all browsers.
|
|
||||||
2. Remove the margin in Firefox and Safari.
|
|
||||||
3. Remove default padding in all browsers.
|
|
||||||
*/
|
|
||||||
|
|
||||||
button,
|
|
||||||
input,
|
|
||||||
optgroup,
|
|
||||||
select,
|
|
||||||
textarea {
|
|
||||||
font-family: inherit; /* 1 */
|
|
||||||
font-size: 100%; /* 1 */
|
|
||||||
font-weight: inherit; /* 1 */
|
|
||||||
line-height: inherit; /* 1 */
|
|
||||||
color: inherit; /* 1 */
|
|
||||||
margin: 0; /* 2 */
|
|
||||||
padding: 0; /* 3 */
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Remove the inheritance of text transform in Edge and Firefox.
|
|
||||||
*/
|
|
||||||
|
|
||||||
button,
|
|
||||||
select {
|
|
||||||
text-transform: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
1. Correct the inability to style clickable types in iOS and Safari.
|
|
||||||
2. Remove default button styles.
|
|
||||||
*/
|
|
||||||
|
|
||||||
button,
|
|
||||||
[type='button'],
|
|
||||||
[type='reset'],
|
|
||||||
[type='submit'] {
|
|
||||||
-webkit-appearance: button; /* 1 */
|
|
||||||
background-color: transparent; /* 2 */
|
|
||||||
background-image: none; /* 2 */
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Use the modern Firefox focus style for all focusable elements.
|
|
||||||
*/
|
|
||||||
|
|
||||||
:-moz-focusring {
|
|
||||||
outline: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737)
|
|
||||||
*/
|
|
||||||
|
|
||||||
:-moz-ui-invalid {
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Add the correct vertical alignment in Chrome and Firefox.
|
|
||||||
*/
|
|
||||||
|
|
||||||
progress {
|
|
||||||
vertical-align: baseline;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Correct the cursor style of increment and decrement buttons in Safari.
|
|
||||||
*/
|
|
||||||
|
|
||||||
::-webkit-inner-spin-button,
|
|
||||||
::-webkit-outer-spin-button {
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
1. Correct the odd appearance in Chrome and Safari.
|
|
||||||
2. Correct the outline style in Safari.
|
|
||||||
*/
|
|
||||||
|
|
||||||
[type='search'] {
|
|
||||||
-webkit-appearance: textfield; /* 1 */
|
|
||||||
outline-offset: -2px; /* 2 */
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Remove the inner padding in Chrome and Safari on macOS.
|
|
||||||
*/
|
|
||||||
|
|
||||||
::-webkit-search-decoration {
|
|
||||||
-webkit-appearance: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
1. Correct the inability to style clickable types in iOS and Safari.
|
|
||||||
2. Change font properties to `inherit` in Safari.
|
|
||||||
*/
|
|
||||||
|
|
||||||
::-webkit-file-upload-button {
|
|
||||||
-webkit-appearance: button; /* 1 */
|
|
||||||
font: inherit; /* 2 */
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Add the correct display in Chrome and Safari.
|
|
||||||
*/
|
|
||||||
|
|
||||||
summary {
|
|
||||||
display: list-item;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Removes the default spacing and border for appropriate elements.
|
|
||||||
*/
|
|
||||||
|
|
||||||
blockquote,
|
|
||||||
dl,
|
|
||||||
dd,
|
|
||||||
h1,
|
|
||||||
h2,
|
|
||||||
h3,
|
|
||||||
h4,
|
|
||||||
h5,
|
|
||||||
h6,
|
|
||||||
hr,
|
|
||||||
figure,
|
|
||||||
p,
|
|
||||||
pre {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
fieldset {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
legend {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
ol,
|
|
||||||
ul,
|
|
||||||
menu {
|
|
||||||
list-style: none;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Prevent resizing textareas horizontally by default.
|
|
||||||
*/
|
|
||||||
|
|
||||||
textarea {
|
|
||||||
resize: vertical;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300)
|
|
||||||
2. Set the default placeholder color to the user's configured gray 400 color.
|
|
||||||
*/
|
|
||||||
|
|
||||||
input::-moz-placeholder, textarea::-moz-placeholder {
|
|
||||||
opacity: 1; /* 1 */
|
|
||||||
color: #9ca3af; /* 2 */
|
|
||||||
}
|
|
||||||
|
|
||||||
input:-ms-input-placeholder, textarea:-ms-input-placeholder {
|
|
||||||
opacity: 1; /* 1 */
|
|
||||||
color: #9ca3af; /* 2 */
|
|
||||||
}
|
|
||||||
|
|
||||||
input::placeholder,
|
|
||||||
textarea::placeholder {
|
|
||||||
opacity: 1; /* 1 */
|
|
||||||
color: #9ca3af; /* 2 */
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Set the default cursor for buttons.
|
|
||||||
*/
|
|
||||||
|
|
||||||
button,
|
|
||||||
[role="button"] {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Make sure disabled buttons don't get the pointer cursor.
|
|
||||||
*/
|
|
||||||
:disabled {
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14)
|
|
||||||
2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210)
|
|
||||||
This can trigger a poorly considered lint error in some tools but is included by design.
|
|
||||||
*/
|
|
||||||
|
|
||||||
img,
|
|
||||||
svg,
|
|
||||||
video,
|
|
||||||
canvas,
|
|
||||||
audio,
|
|
||||||
iframe,
|
|
||||||
embed,
|
|
||||||
object {
|
|
||||||
display: block; /* 1 */
|
|
||||||
vertical-align: middle; /* 2 */
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14)
|
|
||||||
*/
|
|
||||||
|
|
||||||
img,
|
|
||||||
video {
|
|
||||||
max-width: 100%;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
*, ::before, ::after {
|
|
||||||
--tw-border-spacing-x: 0;
|
|
||||||
--tw-border-spacing-y: 0;
|
|
||||||
--tw-translate-x: 0;
|
|
||||||
--tw-translate-y: 0;
|
|
||||||
--tw-rotate: 0;
|
|
||||||
--tw-skew-x: 0;
|
|
||||||
--tw-skew-y: 0;
|
|
||||||
--tw-scale-x: 1;
|
|
||||||
--tw-scale-y: 1;
|
|
||||||
--tw-pan-x: ;
|
|
||||||
--tw-pan-y: ;
|
|
||||||
--tw-pinch-zoom: ;
|
|
||||||
--tw-scroll-snap-strictness: proximity;
|
|
||||||
--tw-ordinal: ;
|
|
||||||
--tw-slashed-zero: ;
|
|
||||||
--tw-numeric-figure: ;
|
|
||||||
--tw-numeric-spacing: ;
|
|
||||||
--tw-numeric-fraction: ;
|
|
||||||
--tw-ring-inset: ;
|
|
||||||
--tw-ring-offset-width: 0px;
|
|
||||||
--tw-ring-offset-color: #fff;
|
|
||||||
--tw-ring-color: rgb(59 130 246 / 0.5);
|
|
||||||
--tw-ring-offset-shadow: 0 0 #0000;
|
|
||||||
--tw-ring-shadow: 0 0 #0000;
|
|
||||||
--tw-shadow: 0 0 #0000;
|
|
||||||
--tw-shadow-colored: 0 0 #0000;
|
|
||||||
--tw-blur: ;
|
|
||||||
--tw-brightness: ;
|
|
||||||
--tw-contrast: ;
|
|
||||||
--tw-grayscale: ;
|
|
||||||
--tw-hue-rotate: ;
|
|
||||||
--tw-invert: ;
|
|
||||||
--tw-saturate: ;
|
|
||||||
--tw-sepia: ;
|
|
||||||
--tw-drop-shadow: ;
|
|
||||||
--tw-backdrop-blur: ;
|
|
||||||
--tw-backdrop-brightness: ;
|
|
||||||
--tw-backdrop-contrast: ;
|
|
||||||
--tw-backdrop-grayscale: ;
|
|
||||||
--tw-backdrop-hue-rotate: ;
|
|
||||||
--tw-backdrop-invert: ;
|
|
||||||
--tw-backdrop-opacity: ;
|
|
||||||
--tw-backdrop-saturate: ;
|
|
||||||
--tw-backdrop-sepia: ;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-backdrop {
|
|
||||||
--tw-border-spacing-x: 0;
|
|
||||||
--tw-border-spacing-y: 0;
|
|
||||||
--tw-translate-x: 0;
|
|
||||||
--tw-translate-y: 0;
|
|
||||||
--tw-rotate: 0;
|
|
||||||
--tw-skew-x: 0;
|
|
||||||
--tw-skew-y: 0;
|
|
||||||
--tw-scale-x: 1;
|
|
||||||
--tw-scale-y: 1;
|
|
||||||
--tw-pan-x: ;
|
|
||||||
--tw-pan-y: ;
|
|
||||||
--tw-pinch-zoom: ;
|
|
||||||
--tw-scroll-snap-strictness: proximity;
|
|
||||||
--tw-ordinal: ;
|
|
||||||
--tw-slashed-zero: ;
|
|
||||||
--tw-numeric-figure: ;
|
|
||||||
--tw-numeric-spacing: ;
|
|
||||||
--tw-numeric-fraction: ;
|
|
||||||
--tw-ring-inset: ;
|
|
||||||
--tw-ring-offset-width: 0px;
|
|
||||||
--tw-ring-offset-color: #fff;
|
|
||||||
--tw-ring-color: rgb(59 130 246 / 0.5);
|
|
||||||
--tw-ring-offset-shadow: 0 0 #0000;
|
|
||||||
--tw-ring-shadow: 0 0 #0000;
|
|
||||||
--tw-shadow: 0 0 #0000;
|
|
||||||
--tw-shadow-colored: 0 0 #0000;
|
|
||||||
--tw-blur: ;
|
|
||||||
--tw-brightness: ;
|
|
||||||
--tw-contrast: ;
|
|
||||||
--tw-grayscale: ;
|
|
||||||
--tw-hue-rotate: ;
|
|
||||||
--tw-invert: ;
|
|
||||||
--tw-saturate: ;
|
|
||||||
--tw-sepia: ;
|
|
||||||
--tw-drop-shadow: ;
|
|
||||||
--tw-backdrop-blur: ;
|
|
||||||
--tw-backdrop-brightness: ;
|
|
||||||
--tw-backdrop-contrast: ;
|
|
||||||
--tw-backdrop-grayscale: ;
|
|
||||||
--tw-backdrop-hue-rotate: ;
|
|
||||||
--tw-backdrop-invert: ;
|
|
||||||
--tw-backdrop-opacity: ;
|
|
||||||
--tw-backdrop-saturate: ;
|
|
||||||
--tw-backdrop-sepia: ;
|
|
||||||
}
|
|
||||||
|
|
||||||
::backdrop {
|
|
||||||
--tw-border-spacing-x: 0;
|
|
||||||
--tw-border-spacing-y: 0;
|
|
||||||
--tw-translate-x: 0;
|
|
||||||
--tw-translate-y: 0;
|
|
||||||
--tw-rotate: 0;
|
|
||||||
--tw-skew-x: 0;
|
|
||||||
--tw-skew-y: 0;
|
|
||||||
--tw-scale-x: 1;
|
|
||||||
--tw-scale-y: 1;
|
|
||||||
--tw-pan-x: ;
|
|
||||||
--tw-pan-y: ;
|
|
||||||
--tw-pinch-zoom: ;
|
|
||||||
--tw-scroll-snap-strictness: proximity;
|
|
||||||
--tw-ordinal: ;
|
|
||||||
--tw-slashed-zero: ;
|
|
||||||
--tw-numeric-figure: ;
|
|
||||||
--tw-numeric-spacing: ;
|
|
||||||
--tw-numeric-fraction: ;
|
|
||||||
--tw-ring-inset: ;
|
|
||||||
--tw-ring-offset-width: 0px;
|
|
||||||
--tw-ring-offset-color: #fff;
|
|
||||||
--tw-ring-color: rgb(59 130 246 / 0.5);
|
|
||||||
--tw-ring-offset-shadow: 0 0 #0000;
|
|
||||||
--tw-ring-shadow: 0 0 #0000;
|
|
||||||
--tw-shadow: 0 0 #0000;
|
|
||||||
--tw-shadow-colored: 0 0 #0000;
|
|
||||||
--tw-blur: ;
|
|
||||||
--tw-brightness: ;
|
|
||||||
--tw-contrast: ;
|
|
||||||
--tw-grayscale: ;
|
|
||||||
--tw-hue-rotate: ;
|
|
||||||
--tw-invert: ;
|
|
||||||
--tw-saturate: ;
|
|
||||||
--tw-sepia: ;
|
|
||||||
--tw-drop-shadow: ;
|
|
||||||
--tw-backdrop-blur: ;
|
|
||||||
--tw-backdrop-brightness: ;
|
|
||||||
--tw-backdrop-contrast: ;
|
|
||||||
--tw-backdrop-grayscale: ;
|
|
||||||
--tw-backdrop-hue-rotate: ;
|
|
||||||
--tw-backdrop-invert: ;
|
|
||||||
--tw-backdrop-opacity: ;
|
|
||||||
--tw-backdrop-saturate: ;
|
|
||||||
--tw-backdrop-sepia: ;
|
|
||||||
}
|
|
||||||
.mx-6 {
|
|
||||||
margin-left: 1.5rem;
|
|
||||||
margin-right: 1.5rem;
|
|
||||||
}
|
|
||||||
.my-4 {
|
|
||||||
margin-top: 1rem;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
.my-1 {
|
|
||||||
margin-top: 0.25rem;
|
|
||||||
margin-bottom: 0.25rem;
|
|
||||||
}
|
|
||||||
.mx-1 {
|
|
||||||
margin-left: 0.25rem;
|
|
||||||
margin-right: 0.25rem;
|
|
||||||
}
|
|
||||||
.flex {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
.h-screen {
|
|
||||||
height: 100vh;
|
|
||||||
}
|
|
||||||
.h-20 {
|
|
||||||
height: 5rem;
|
|
||||||
}
|
|
||||||
.h-12 {
|
|
||||||
height: 3rem;
|
|
||||||
}
|
|
||||||
.h-full {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
.max-h-full {
|
|
||||||
max-height: 100%;
|
|
||||||
}
|
|
||||||
.w-screen {
|
|
||||||
width: 100vw;
|
|
||||||
}
|
|
||||||
.w-full {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.w-12 {
|
|
||||||
width: 3rem;
|
|
||||||
}
|
|
||||||
.flex-col {
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
.items-center {
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
.justify-between {
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
.space-y-0 > :not([hidden]) ~ :not([hidden]) {
|
|
||||||
--tw-space-y-reverse: 0;
|
|
||||||
margin-top: calc(0px * calc(1 - var(--tw-space-y-reverse)));
|
|
||||||
margin-bottom: calc(0px * var(--tw-space-y-reverse));
|
|
||||||
}
|
|
||||||
.space-x-2 > :not([hidden]) ~ :not([hidden]) {
|
|
||||||
--tw-space-x-reverse: 0;
|
|
||||||
margin-right: calc(0.5rem * var(--tw-space-x-reverse));
|
|
||||||
margin-left: calc(0.5rem * calc(1 - var(--tw-space-x-reverse)));
|
|
||||||
}
|
|
||||||
.overflow-hidden {
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
.overflow-y-auto {
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
.rounded-md {
|
|
||||||
border-radius: 0.375rem;
|
|
||||||
}
|
|
||||||
.border-b {
|
|
||||||
border-bottom-width: 1px;
|
|
||||||
}
|
|
||||||
.border-t {
|
|
||||||
border-top-width: 1px;
|
|
||||||
}
|
|
||||||
.border-accent {
|
|
||||||
border-color: var(--accent);
|
|
||||||
}
|
|
||||||
.bg-primary {
|
|
||||||
background-color: var(--primary);
|
|
||||||
}
|
|
||||||
.bg-tertiary {
|
|
||||||
background-color: var(--tertiary);
|
|
||||||
}
|
|
||||||
.bg-secondary {
|
|
||||||
background-color: var(--secondary);
|
|
||||||
}
|
|
||||||
.bg-accent {
|
|
||||||
background-color: var(--accent);
|
|
||||||
}
|
|
||||||
.p-4 {
|
|
||||||
padding: 1rem;
|
|
||||||
}
|
|
||||||
.p-2 {
|
|
||||||
padding: 0.5rem;
|
|
||||||
}
|
|
||||||
.px-6 {
|
|
||||||
padding-left: 1.5rem;
|
|
||||||
padding-right: 1.5rem;
|
|
||||||
}
|
|
||||||
.px-4 {
|
|
||||||
padding-left: 1rem;
|
|
||||||
padding-right: 1rem;
|
|
||||||
}
|
|
||||||
.text-2xl {
|
|
||||||
font-size: 1.5rem;
|
|
||||||
line-height: 2rem;
|
|
||||||
}
|
|
||||||
.text-sm {
|
|
||||||
font-size: 0.875rem;
|
|
||||||
line-height: 1.25rem;
|
|
||||||
}
|
|
||||||
.font-bold {
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
.font-normal {
|
|
||||||
font-weight: 400;
|
|
||||||
}
|
|
||||||
.font-medium {
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
.text-gray-400 {
|
|
||||||
--tw-text-opacity: 1;
|
|
||||||
color: rgb(156 163 175 / var(--tw-text-opacity));
|
|
||||||
}
|
|
||||||
.text-black {
|
|
||||||
--tw-text-opacity: 1;
|
|
||||||
color: rgb(0 0 0 / var(--tw-text-opacity));
|
|
||||||
}
|
|
||||||
.underline {
|
|
||||||
-webkit-text-decoration-line: underline;
|
|
||||||
text-decoration-line: underline;
|
|
||||||
}
|
|
||||||
.outline-none {
|
|
||||||
outline: 2px solid transparent;
|
|
||||||
outline-offset: 2px;
|
|
||||||
}
|
|
||||||
.drop-shadow-sm {
|
|
||||||
--tw-drop-shadow: drop-shadow(0 1px 1px rgb(0 0 0 / 0.05));
|
|
||||||
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
|
||||||
}
|
|
||||||
.transition-colors {
|
|
||||||
transition-property: color, background-color, border-color, fill, stroke, -webkit-text-decoration-color;
|
|
||||||
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke;
|
|
||||||
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, -webkit-text-decoration-color;
|
|
||||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
||||||
transition-duration: 150ms;
|
|
||||||
}
|
|
||||||
.ease-in-out {
|
|
||||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
:root {
|
|
||||||
--primary: #1a1d21;
|
|
||||||
--secondary: #212529;
|
|
||||||
--teriary: #23282c;
|
|
||||||
--accent: #6691e7;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hover\:bg-\[\#7ba0ea\]:hover {
|
|
||||||
--tw-bg-opacity: 1;
|
|
||||||
background-color: rgb(123 160 234 / var(--tw-bg-opacity));
|
|
||||||
}
|
|
||||||
|
|
||||||
.active\:bg-\[\#3d73e1\]:active {
|
|
||||||
--tw-bg-opacity: 1;
|
|
||||||
background-color: rgb(61 115 225 / var(--tw-bg-opacity));
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 640px) {
|
|
||||||
|
|
||||||
.sm\:space-x-reverse > :not([hidden]) ~ :not([hidden]) {
|
|
||||||
--tw-space-x-reverse: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sm\:border-b {
|
|
||||||
border-bottom-width: 1px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
|
||||||
|
|
||||||
.md\:h-1\/2 {
|
|
||||||
height: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.md\:w-1\/3 {
|
|
||||||
width: 33.333333%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.md\:flex-row {
|
|
||||||
flex-direction: row;
|
|
||||||
}
|
|
||||||
|
|
||||||
.md\:flex-col {
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.md\:border-r {
|
|
||||||
border-right-width: 1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.md\:border-b-0 {
|
|
||||||
border-bottom-width: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.md\:border-b {
|
|
||||||
border-bottom-width: 1px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 1024px) {
|
|
||||||
|
|
||||||
.lg\:w-1\/4 {
|
|
||||||
width: 25%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 1280px) {
|
|
||||||
|
|
||||||
.xl\:w-1\/5 {
|
|
||||||
width: 20%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.collapsible-header {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
.collapsible-content {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Wait animation */
|
|
||||||
.lds-facebook {
|
|
||||||
display: inline-block;
|
|
||||||
position: relative;
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
}
|
|
||||||
.lds-facebook div {
|
|
||||||
display: inline-block;
|
|
||||||
position: absolute;
|
|
||||||
left: 8px;
|
|
||||||
width: 8px;
|
|
||||||
background: #fff;
|
|
||||||
animation: lds-facebook 1.2s cubic-bezier(0, 0.5, 0.5, 1) infinite;
|
|
||||||
}
|
|
||||||
.lds-facebook div:nth-child(1) {
|
|
||||||
left: 4px;
|
|
||||||
animation-delay: -0.24s;
|
|
||||||
}
|
|
||||||
.lds-facebook div:nth-child(2) {
|
|
||||||
left: 16px;
|
|
||||||
animation-delay: -0.12s;
|
|
||||||
}
|
|
||||||
.lds-facebook div:nth-child(3) {
|
|
||||||
left: 28px;
|
|
||||||
animation-delay: 0;
|
|
||||||
}
|
|
||||||
@keyframes lds-facebook {
|
|
||||||
0% {
|
|
||||||
top: 8px;
|
|
||||||
height: 34px;
|
|
||||||
}
|
|
||||||
50%, 100% {
|
|
||||||
top: 12px;
|
|
||||||
height: 18px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
li {
|
|
||||||
text-shadow: #0000;
|
|
||||||
}
|
|
||||||
|
|
||||||
ul {
|
|
||||||
list-style-type: disc;
|
|
||||||
}
|
|
||||||
|
|
||||||
ol {
|
|
||||||
list-style-type: decimal;
|
|
||||||
}
|
|
1
static/css/tailwindcss.min.css
vendored
1
static/css/utilities.min.css
vendored
Before Width: | Height: | Size: 222 KiB |
Before Width: | Height: | Size: 2.4 KiB |
@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#fff" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-moon"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path></svg>
|
|
Before Width: | Height: | Size: 281 B |
Before Width: | Height: | Size: 245 KiB |
Before Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 7.4 KiB |
Before Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 222 KiB |
Before Width: | Height: | Size: 37 KiB |
@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#currentColor" stroke="#fff" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-sun"><circle cx="12" cy="12" r="5"></circle><line x1="12" y1="1" x2="12" y2="3"></line><line x1="12" y1="21" x2="12" y2="23"></line><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line><line x1="1" y1="12" x2="3" y2="12"></line><line x1="21" y1="12" x2="23" y2="12"></line><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line></svg>
|
|
Before Width: | Height: | Size: 651 B |
Before Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 30 KiB |
@ -1 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!-- Font Awesome Pro 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M402.6 83.2l90.2 90.2c3.8 3.8 3.8 10 0 13.8L274.4 405.6l-92.8 10.3c-12.4 1.4-22.9-9.1-21.5-21.5l10.3-92.8L388.8 83.2c3.8-3.8 10-3.8 13.8 0zm162-22.9l-48.8-48.8c-15.2-15.2-39.9-15.2-55.2 0l-35.4 35.4c-3.8 3.8-3.8 10 0 13.8l90.2 90.2c3.8 3.8 10 3.8 13.8 0l35.4-35.4c15.2-15.3 15.2-40 0-55.2zM384 346.2V448H64V128h229.8c3.2 0 6.2-1.3 8.5-3.5l40-40c7.6-7.6 2.2-20.5-8.5-20.5H48C21.5 64 0 85.5 0 112v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V306.2c0-10.7-12.9-16-20.5-8.5l-40 40c-2.2 2.3-3.5 5.3-3.5 8.5z"/></svg>
|
|
Before Width: | Height: | Size: 724 B |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 14 KiB |
@ -1,203 +0,0 @@
|
|||||||
// Dirty fix for disabling speech synth for firefox browsers :()
|
|
||||||
if (!userAgent.match(/firefox|fxios/i)) {
|
|
||||||
isStarted = false;
|
|
||||||
isSpeaking = false;
|
|
||||||
const SpeechRecognition = window.SpeechRecognition || webkitSpeechRecognition;
|
|
||||||
const recognition = new SpeechRecognition();
|
|
||||||
const synth = window.speechSynthesis || webkitspeechSynthesis;
|
|
||||||
var voices = synth.getVoices();
|
|
||||||
function prepre_audio() {
|
|
||||||
recognition.continuous = true;
|
|
||||||
recognition.interimResults = true;
|
|
||||||
recognition.maxAlternatives = 10;
|
|
||||||
language_select = document.getElementById("language")
|
|
||||||
}
|
|
||||||
voices = [];
|
|
||||||
function populateVoicesList() {
|
|
||||||
voices = synth.getVoices();
|
|
||||||
voice_select = document.getElementById("voice")
|
|
||||||
voice_select.innerHTML = "";
|
|
||||||
for (let i = 0; i < voices.length; i++) {
|
|
||||||
if (
|
|
||||||
voices[i].lang.startsWith(
|
|
||||||
language_select.value.substring(0, 2)
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
const option = document.createElement("option");
|
|
||||||
option.textContent = `${voices[i].name} (${voices[i].lang})`;
|
|
||||||
|
|
||||||
if (voices[i].default) {
|
|
||||||
option.textContent += " — DEFAULT";
|
|
||||||
}
|
|
||||||
|
|
||||||
option.setAttribute("data-lang", voices[i].lang);
|
|
||||||
option.setAttribute("data-name", voices[i].name);
|
|
||||||
voice_select.appendChild(option);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
voice_select.addEventListener("change", function () {
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// Audio code
|
|
||||||
function splitString(string, maxLength) {
|
|
||||||
const sentences = string.match(/[^.!?]+[.!?]/g);
|
|
||||||
const strings = [];
|
|
||||||
let currentString = "";
|
|
||||||
|
|
||||||
if (sentences) {
|
|
||||||
for (const sentence of sentences) {
|
|
||||||
if (currentString.length + sentence.length > maxLength) {
|
|
||||||
strings.push(currentString);
|
|
||||||
currentString = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
currentString += `${sentence} `;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
strings.push(string);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentString) {
|
|
||||||
strings.push(currentString);
|
|
||||||
}
|
|
||||||
|
|
||||||
return strings;
|
|
||||||
}
|
|
||||||
function addListeners(button, utterThis) {
|
|
||||||
utterThis.onstart = (event) => {
|
|
||||||
isSpeaking = true;
|
|
||||||
button.style.backgroundColor = "red";
|
|
||||||
button.style.boxShadow = "2px 2px 0.5px #808080";
|
|
||||||
};
|
|
||||||
|
|
||||||
utterThis.onend = (event) => {
|
|
||||||
isSpeaking = false;
|
|
||||||
button.style.backgroundColor = "";
|
|
||||||
button.style.boxShadow = "";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function attachAudio_modules(div, container) {
|
|
||||||
if (container.getElementsByClassName("audio-out-button").length > 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const audio_out_button = document.createElement("button");
|
|
||||||
audio_out_button.title = "Listen to message";
|
|
||||||
audio_out_button.id = "audio-out-button";
|
|
||||||
audio_out_button.classList.add("audio_btn",'bg-gray-500', 'hover:bg-gray-700', 'text-white', 'font-bold', 'py-0', 'px-0', 'rounded-r', "w-10", "h-10");
|
|
||||||
audio_out_button.innerHTML = "🕪";
|
|
||||||
audio_out_button.classList.add("audio-out-button");
|
|
||||||
container.appendChild(audio_out_button);
|
|
||||||
|
|
||||||
function play_audio() {
|
|
||||||
console.log("Playing audio")
|
|
||||||
if (isSpeaking) {
|
|
||||||
|
|
||||||
audio_out_button.style.backgroundColor = "";
|
|
||||||
audio_out_button.style.boxShadow = "";
|
|
||||||
synth.cancel();
|
|
||||||
isSpeaking = false;
|
|
||||||
} else {
|
|
||||||
isSpeaking = true;
|
|
||||||
text = div.textContent;
|
|
||||||
|
|
||||||
const selectedOption =
|
|
||||||
voice_select.selectedOptions[0].getAttribute("data-name");
|
|
||||||
var selectedVoice = null;
|
|
||||||
for (let i = 0; i < voices.length; i++) {
|
|
||||||
if (voices[i].name === selectedOption) {
|
|
||||||
selectedVoice = voices[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (selectedVoice && selectedVoice.voiceURI === "native") {
|
|
||||||
const utterThis = new SpeechSynthesisUtterance(text);
|
|
||||||
utterThis.voice = selectedVoice;
|
|
||||||
addListeners(audio_out_button, utterThis);
|
|
||||||
synth.speak(utterThis);
|
|
||||||
} else {
|
|
||||||
console.log("Not native")
|
|
||||||
texts = splitString(text, 200);
|
|
||||||
console.log(`Text to say ${texts}`)
|
|
||||||
texts.forEach((text) => {
|
|
||||||
const utterThis = new SpeechSynthesisUtterance(text);
|
|
||||||
utterThis.voice = selectedVoice;
|
|
||||||
addListeners(audio_out_button, utterThis);
|
|
||||||
synth.speak(utterThis);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
audio_out_button.addEventListener("click", () => {
|
|
||||||
play_audio();
|
|
||||||
});
|
|
||||||
// TODO : activate using configuration file
|
|
||||||
//if (global["auto_audio"]) {
|
|
||||||
// play_audio();
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
|
|
||||||
function add_audio_in_ui() {
|
|
||||||
const input = document.getElementById("user-input");
|
|
||||||
// const wrapper = document.createElement("div");
|
|
||||||
// wrapper.classList.add("flex", "items-center");
|
|
||||||
var btn = document.querySelectorAll("#audio_in_tool");
|
|
||||||
|
|
||||||
var found = false;
|
|
||||||
// Iterate through the children
|
|
||||||
for (var i = 0; i < btn.length; i++) {
|
|
||||||
var child = btn[i];
|
|
||||||
// Check if the wrapper element contains the current child element
|
|
||||||
if (input.parentNode.parentNode.contains(child)) {
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (!found) {
|
|
||||||
const audio_in_button = document.createElement("button");
|
|
||||||
audio_in_button.title = "Type with your voice";
|
|
||||||
audio_in_button.id = "audio_in_tool";
|
|
||||||
audio_in_button.classList.add("audio_btn");
|
|
||||||
audio_in_button.innerHTML = "🎤";
|
|
||||||
|
|
||||||
input.parentNode.parentNode.insertBefore(
|
|
||||||
audio_in_button,
|
|
||||||
input.parentNode
|
|
||||||
);
|
|
||||||
|
|
||||||
input.classList.add("flex-1");
|
|
||||||
audio_in_button.classList.add("ml-2");
|
|
||||||
|
|
||||||
audio_in_button.addEventListener("click", () => {
|
|
||||||
if (isStarted) {
|
|
||||||
recognition.stop();
|
|
||||||
isStarted = false;
|
|
||||||
} else {
|
|
||||||
recognition.lang = language_select.value;
|
|
||||||
recognition.start();
|
|
||||||
isStarted = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
recognition.addEventListener("result", (event) => {
|
|
||||||
let transcript = "";
|
|
||||||
for (const result of event.results) {
|
|
||||||
transcript += result[0].transcript;
|
|
||||||
}
|
|
||||||
if (transcript != "") {
|
|
||||||
input.value = transcript;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
recognition.addEventListener("start", () => {
|
|
||||||
audio_in_button.style.backgroundColor = "red";
|
|
||||||
audio_in_button.style.boxShadow = "2px 2px 0.5px #808080";
|
|
||||||
});
|
|
||||||
|
|
||||||
recognition.addEventListener("end", () => {
|
|
||||||
audio_in_button.style.backgroundColor = "";
|
|
||||||
audio_in_button.style.boxShadow = "";
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,323 +0,0 @@
|
|||||||
// Dirty fix for disabling speech synth for firefox browsers :()
|
|
||||||
const userAgent = navigator.userAgent;
|
|
||||||
|
|
||||||
async function copyToClipboard(text) {
|
|
||||||
try {
|
|
||||||
await navigator.clipboard.writeText(text);
|
|
||||||
console.log('Text copied to clipboard');
|
|
||||||
} catch (err) {
|
|
||||||
console.error('Failed to copy text: ', err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function addMessage(sender, message, id, rank = 0, can_edit = false) {
|
|
||||||
const chatWindow = document.getElementById('chat-window');
|
|
||||||
const chatForm = document.getElementById('chat-form');
|
|
||||||
const userInput = document.getElementById('user-input');
|
|
||||||
|
|
||||||
const messageElement = document.createElement('div');
|
|
||||||
messageElement.classList.add('bg-secondary', 'drop-shadow-sm', 'p-4', 'mx-6', 'my-4', 'flex', 'flex-col', 'space-x-2', 'rounded-lg', 'shadow-lg', 'bg-gray-300', 'text-black', 'dark:text-gray-200', 'dark:bg-gray-800', 'hover:bg-gray-400', 'dark:hover:bg-gray-700', 'transition-colors', 'duration-300');
|
|
||||||
|
|
||||||
messageElement.id = id
|
|
||||||
//messageElement.classList.add(sender);
|
|
||||||
messageElement.setAttribute('id', id);
|
|
||||||
|
|
||||||
const senderElement = document.createElement('div');
|
|
||||||
senderElement.classList.add('font-normal', 'underline', 'text-sm');
|
|
||||||
senderElement.innerHTML = sender;
|
|
||||||
|
|
||||||
const messageTextElement = document.createElement('div');
|
|
||||||
messageTextElement.classList.add('font-medium', 'text-md', 'whitespace-pre-wrap');
|
|
||||||
messageTextElement.innerHTML = message;
|
|
||||||
// Create a hidden div element needed to buffer responses before commiting them to the visible message
|
|
||||||
const hiddenElement = document.createElement('div');
|
|
||||||
hiddenElement.style.display = 'none';
|
|
||||||
hiddenElement.innerHTML = '';
|
|
||||||
|
|
||||||
messageElement.appendChild(senderElement);
|
|
||||||
messageElement.appendChild(messageTextElement);
|
|
||||||
|
|
||||||
if (can_edit) {
|
|
||||||
// Create buttons container
|
|
||||||
const buttonsContainer = document.createElement('div');
|
|
||||||
// Add the 'flex' class to the div
|
|
||||||
buttonsContainer.classList.add('flex');
|
|
||||||
|
|
||||||
// Add the 'justify-end' class to the div
|
|
||||||
buttonsContainer.classList.add('justify-end');
|
|
||||||
|
|
||||||
// Set the width and height of the container to 100%
|
|
||||||
buttonsContainer.style.width = '100%';
|
|
||||||
buttonsContainer.style.height = '100%';
|
|
||||||
const clipboardButton = document.createElement('button');
|
|
||||||
clipboardButton.classList.add('bg-gray-500', 'hover:bg-gray-700', 'text-white', 'font-bold', 'py-0', 'px-0', "w-10", "h-10");
|
|
||||||
clipboardButton.style.float = 'right'; // set the float property to right
|
|
||||||
clipboardButton.style.display = 'inline-block'
|
|
||||||
clipboardButton.innerHTML = '';
|
|
||||||
const clipboardImg = document.createElement('img');
|
|
||||||
clipboardImg.src = "/static/images/copy.png";
|
|
||||||
clipboardImg.classList.add('py-1', 'px-1', 'rounded', 'w-10', 'h-10');
|
|
||||||
clipboardButton.title = "clipboard message";
|
|
||||||
clipboardButton.appendChild(clipboardImg)
|
|
||||||
clipboardButton.addEventListener('click', () => {
|
|
||||||
copyToClipboard(messageTextElement.innerText)
|
|
||||||
})
|
|
||||||
const resendButton = document.createElement('button');
|
|
||||||
resendButton.classList.add('bg-gray-500', 'hover:bg-gray-700', 'text-white', 'font-bold', 'py-0', 'px-0', "w-10", "h-10");
|
|
||||||
resendButton.style.float = 'right'; // set the float property to right
|
|
||||||
resendButton.style.display = 'inline-block'
|
|
||||||
resendButton.innerHTML = '';
|
|
||||||
const resendImg = document.createElement('img');
|
|
||||||
resendImg.src = "/static/images/refresh.png";
|
|
||||||
resendImg.classList.add('py-1', 'px-1', 'rounded', 'w-10', 'h-10');
|
|
||||||
resendButton.title = "Resend message";
|
|
||||||
resendButton.appendChild(resendImg)
|
|
||||||
resendButton.addEventListener('click', () => {
|
|
||||||
// get user input and clear input field
|
|
||||||
message = userInput.value;
|
|
||||||
userInput.value = '';
|
|
||||||
|
|
||||||
// add user message to chat window
|
|
||||||
const sendbtn = document.querySelector("#submit-input")
|
|
||||||
const waitAnimation = document.querySelector("#wait-animation")
|
|
||||||
const stopGeneration = document.querySelector("#stop-generation")
|
|
||||||
|
|
||||||
sendbtn.style.display = "none";
|
|
||||||
waitAnimation.style.display = "block";
|
|
||||||
stopGeneration.style.display = "block";
|
|
||||||
|
|
||||||
globals.bot_msg = addMessage("", "", 0, 0, can_edit = true);
|
|
||||||
globals.user_msg = undefined
|
|
||||||
// scroll to bottom of chat window
|
|
||||||
chatWindow.scrollTop = chatWindow.scrollHeight;
|
|
||||||
send_message('generate_msg_from',{prompt: message, id: messageElement.id})
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
const editButton = document.createElement('button');
|
|
||||||
editButton.classList.add('bg-gray-500', 'hover:bg-gray-700', 'text-white', 'font-bold', 'py-0', 'px-0', "w-10", "h-10", "rounded-l");
|
|
||||||
editButton.style.float = 'right'; // set the float property to right
|
|
||||||
editButton.style.display = 'inline-block'
|
|
||||||
editButton.innerHTML = '';
|
|
||||||
const editImg = document.createElement('img');
|
|
||||||
editImg.src = "/static/images/edit_discussion.png";
|
|
||||||
editImg.classList.add('py-1', 'px-1', 'rounded', 'w-10', 'h-10');
|
|
||||||
editButton.title = "Edit message";
|
|
||||||
editButton.appendChild(editImg)
|
|
||||||
|
|
||||||
editButton.addEventListener('click', () => {
|
|
||||||
const inputBlock = document.createElement('div')
|
|
||||||
inputBlock.classList.add('flex','flex-col');
|
|
||||||
const inputField = document.createElement('textarea');
|
|
||||||
inputField.type = 'text';
|
|
||||||
inputField.classList.add('font-medium', 'resize-y','h-24', 'text-md', 'border', 'border-gray-300', 'p-1');
|
|
||||||
inputField.value = messageTextElement.innerText;
|
|
||||||
|
|
||||||
//buttonsContainer.style.display = "none"
|
|
||||||
|
|
||||||
const saveButton = document.createElement('button');
|
|
||||||
saveButton.classList.add('bg-gray-500', 'hover:bg-gray-700', 'text-white', 'font-bold', 'py-2', 'px-4', 'my-2', 'ml-2');
|
|
||||||
saveButton.innerHTML = 'Save';
|
|
||||||
inputBlock.appendChild(inputField)
|
|
||||||
inputBlock.appendChild(saveButton)
|
|
||||||
saveButton.addEventListener('click', () => {
|
|
||||||
const newText = inputField.value;
|
|
||||||
messageTextElement.innerText = newText;
|
|
||||||
// make request to update message
|
|
||||||
const url = `/update_message?id=${id}&message=${newText}`;
|
|
||||||
fetch(url)
|
|
||||||
.then(response => {
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error('Network response was not ok');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.log("Updated")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('There was a problem updating the message:', error);
|
|
||||||
});
|
|
||||||
//buttonsContainer.style.display = 'block'
|
|
||||||
messageElement.replaceChild(messageTextElement, inputBlock);
|
|
||||||
//messageElement.removeChild(inputField);
|
|
||||||
messageElement.removeChild(saveButton);
|
|
||||||
});
|
|
||||||
|
|
||||||
messageElement.replaceChild(inputBlock, messageTextElement);
|
|
||||||
inputField.focus();
|
|
||||||
});
|
|
||||||
|
|
||||||
const deleteButton = document.createElement('button');
|
|
||||||
deleteButton.classList.add('bg-gray-500', 'hover:bg-gray-700', 'text-white', 'font-bold', 'py-0', 'px-0', "w-10", "h-10");
|
|
||||||
deleteButton.style.float = 'right'; // set the float property to right
|
|
||||||
deleteButton.style.display = 'inline-block'
|
|
||||||
deleteButton.innerHTML = '';
|
|
||||||
const deleteImg = document.createElement('img');
|
|
||||||
deleteImg.src = "/static/images/delete_discussion.png";
|
|
||||||
deleteImg.classList.add('py-2', 'px-2', 'rounded', 'w-15', 'h-15');
|
|
||||||
deleteButton.title = "Delete message";
|
|
||||||
deleteButton.appendChild(deleteImg)
|
|
||||||
deleteButton.addEventListener('click', () => {
|
|
||||||
const url = `/delete_message?id=${id}`;
|
|
||||||
fetch(url)
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(data => {
|
|
||||||
console.log(data.new_rank)
|
|
||||||
messageElement.style.display = "none"
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('There was a problem updating the message:', error);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
const rank_up = document.createElement('button');
|
|
||||||
rank_up.classList.add('bg-gray-500', 'hover:bg-gray-700', 'text-white', 'font-bold', 'py-0', 'px-0', "w-10", "h-10");
|
|
||||||
rank_up.title = "Upvote";
|
|
||||||
rank_up.style.float = 'right'; // set the float property to right
|
|
||||||
rank_up.style.display = 'inline-block'
|
|
||||||
rank_up.innerHTML = '';
|
|
||||||
const thumbUpImg = document.createElement('img');
|
|
||||||
thumbUpImg.src = "/static/images/thumb_up.png";
|
|
||||||
thumbUpImg.classList.add('py-2', 'px-2', 'rounded', 'w-15', 'h-15');
|
|
||||||
rank_up.appendChild(thumbUpImg)
|
|
||||||
const thumbUpBadge = document.createElement('span');
|
|
||||||
thumbUpBadge.innerText = "";
|
|
||||||
thumbUpBadge.classList.add('inline-flex', 'items-center', 'justify-center', 'h-4', 'w-4', 'rounded-full', 'bg-red-500', 'text-white', 'text-xs', 'top-0', 'right-0');
|
|
||||||
rank_up.appendChild(thumbUpBadge)
|
|
||||||
|
|
||||||
rank_up.addEventListener('click', () => {
|
|
||||||
const url = `/message_rank_up?id=${id}`;
|
|
||||||
fetch(url)
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(data => {
|
|
||||||
console.log(data.new_rank)
|
|
||||||
if (data.new_rank > 0) {
|
|
||||||
thumbUpBadge.innerText = `${data.new_rank}`
|
|
||||||
thumbDownBadge.innerText = ``
|
|
||||||
thumbUpBadge.display = `block`
|
|
||||||
thumbDownBadge.display = 'none'
|
|
||||||
}
|
|
||||||
else if (data.new_rank < 0) {
|
|
||||||
thumbUpBadge.innerText = ``
|
|
||||||
thumbDownBadge.innerText = `${data.new_rank}`
|
|
||||||
thumbUpBadge.display = `none`
|
|
||||||
thumbDownBadge.display = 'block'
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
thumbUpBadge.innerText = ``
|
|
||||||
thumbDownBadge.innerText = ``
|
|
||||||
thumbUpBadge.display = `none`
|
|
||||||
thumbDownBadge.display = 'none'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('There was a problem updating the message:', error);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const rank_down = document.createElement('button');
|
|
||||||
rank_down.classList.add('bg-gray-500', 'hover:bg-gray-700', 'text-white', 'font-bold', 'py-0', 'px-0', "w-10", "h-10");
|
|
||||||
rank_down.title = "Downvote";
|
|
||||||
rank_down.style.float = 'right'; // set the float property to right
|
|
||||||
rank_down.style.display = 'inline-block'
|
|
||||||
rank_down.innerHTML = '';
|
|
||||||
const thumbDownImg = document.createElement('img');
|
|
||||||
thumbDownImg.src = "/static/images/thumb_down.png";
|
|
||||||
thumbDownImg.classList.add('py-2', 'px-2', 'rounded', 'w-15', 'h-15');
|
|
||||||
rank_down.appendChild(thumbDownImg)
|
|
||||||
const thumbDownBadge = document.createElement('span');
|
|
||||||
thumbDownBadge.innerText = "";
|
|
||||||
thumbDownBadge.classList.add('inline-flex', 'items-center', 'justify-center', 'h-4', 'w-4', 'rounded-full', 'bg-red-500', 'text-white', 'text-xs', 'top-0', 'right-0');
|
|
||||||
rank_down.appendChild(thumbDownBadge)
|
|
||||||
|
|
||||||
rank_down.addEventListener('click', () => {
|
|
||||||
const url = `/message_rank_down?id=${id}`;
|
|
||||||
fetch(url)
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(data => {
|
|
||||||
console.log(data)
|
|
||||||
if (data.new_rank > 0) {
|
|
||||||
thumbUpBadge.innerText = `${data.new_rank}`
|
|
||||||
thumbDownBadge.innerText = ``
|
|
||||||
thumbUpBadge.display = `block`
|
|
||||||
thumbDownBadge.display = 'none'
|
|
||||||
}
|
|
||||||
else if (data.new_rank < 0) {
|
|
||||||
thumbUpBadge.innerText = ``
|
|
||||||
thumbDownBadge.innerText = `${data.new_rank}`
|
|
||||||
thumbUpBadge.display = `none`
|
|
||||||
thumbDownBadge.display = 'block'
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
thumbUpBadge.innerText = ``
|
|
||||||
thumbDownBadge.innerText = ``
|
|
||||||
thumbUpBadge.display = `none`
|
|
||||||
thumbDownBadge.display = 'none'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('There was a problem updating the message:', error);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
buttonsContainer.appendChild(editButton);
|
|
||||||
buttonsContainer.appendChild(clipboardButton);
|
|
||||||
buttonsContainer.appendChild(resendButton);
|
|
||||||
buttonsContainer.appendChild(deleteButton);
|
|
||||||
|
|
||||||
buttonsContainer.appendChild(rank_up);
|
|
||||||
buttonsContainer.appendChild(rank_down);
|
|
||||||
messageElement.appendChild(buttonsContainer);
|
|
||||||
// Dirty fix for disabling speech synth for firefox browsers :()
|
|
||||||
if (!userAgent.match(/firefox|fxios/i)) {
|
|
||||||
attachAudio_modules(messageTextElement, buttonsContainer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rank > 0) {
|
|
||||||
thumbUpBadge.innerText = `${rank}`
|
|
||||||
thumbDownBadge.innerText = ``
|
|
||||||
thumbUpBadge.display = `block`
|
|
||||||
thumbDownBadge.display = 'none'
|
|
||||||
}
|
|
||||||
else if (rank < 0) {
|
|
||||||
thumbUpBadge.innerText = ``
|
|
||||||
thumbDownBadge.innerText = `${rank}`
|
|
||||||
thumbUpBadge.display = `none`
|
|
||||||
thumbDownBadge.display = 'block'
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
thumbUpBadge.innerText = ``
|
|
||||||
thumbDownBadge.innerText = ``
|
|
||||||
thumbUpBadge.display = `none`
|
|
||||||
thumbDownBadge.display = 'none'
|
|
||||||
}
|
|
||||||
chatWindow.buttonsContainer = buttonsContainer
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
chatWindow.buttonsContainer = undefined
|
|
||||||
}
|
|
||||||
chatWindow.appendChild(messageElement);
|
|
||||||
chatWindow.appendChild(hiddenElement);
|
|
||||||
|
|
||||||
|
|
||||||
// scroll to bottom of chat window
|
|
||||||
chatWindow.scrollTop = chatWindow.scrollHeight;
|
|
||||||
|
|
||||||
messageElement.messageTextElement = messageTextElement
|
|
||||||
messageElement.hiddenElement = hiddenElement
|
|
||||||
messageElement.senderElement = senderElement
|
|
||||||
messageElement.messageTextElement = messageTextElement
|
|
||||||
messageElement.id = id
|
|
||||||
|
|
||||||
messageElement.setID=(id)=>{
|
|
||||||
messageElement.id = id
|
|
||||||
}
|
|
||||||
messageElement.setSender=(sender)=>{
|
|
||||||
messageElement.senderElement.innerHTML = sender
|
|
||||||
}
|
|
||||||
messageElement.setMessage=(message)=>{
|
|
||||||
messageElement.messageTextElement.innerHTML = message
|
|
||||||
}
|
|
||||||
// Return all needed stuff
|
|
||||||
return messageElement
|
|
||||||
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
function db_export(){
|
|
||||||
const chatWindow = document.getElementById('chat-window');
|
|
||||||
const exportButton = document.getElementById('export-button');
|
|
||||||
exportButton.title = "Export database";
|
|
||||||
exportButton.addEventListener('click', () => {
|
|
||||||
const messages = Array.from(chatWindow.querySelectorAll('.message')).map(messageElement => {
|
|
||||||
const senderElement = messageElement.querySelector('.sender');
|
|
||||||
const messageTextElement= messageElement.querySelector('.message-text');
|
|
||||||
const sender = senderElement.textContent;
|
|
||||||
const messageText = messageTextElement.textContent;
|
|
||||||
return { sender, messageText };
|
|
||||||
});
|
|
||||||
const exportFormat = 'json'; // replace with desired export format
|
|
||||||
|
|
||||||
if (exportFormat === 'text') {
|
|
||||||
const exportText = messages.map(({ sender, messageText }) => `${sender}: ${messageText}`).join('\n');
|
|
||||||
downloadTextFile(exportText);
|
|
||||||
} else if (exportFormat === 'json') {
|
|
||||||
fetch('/export')
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(data => {
|
|
||||||
db_data = JSON.stringify(data)
|
|
||||||
// Do something with the data, such as displaying it on the page
|
|
||||||
console.log(db_data);
|
|
||||||
downloadJsonFile(db_data);
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
// Handle any errors that occur
|
|
||||||
console.error(error);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
console.error(`Unsupported export format: ${exportFormat}`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function downloadTextFile(text) {
|
|
||||||
const blob = new Blob([text], { type: 'text/plain' });
|
|
||||||
const url = URL.createObjectURL(blob);
|
|
||||||
downloadUrl(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
function downloadJsonFile(json) {
|
|
||||||
const blob = new Blob([json], { type: 'application/json' });
|
|
||||||
const url = URL.createObjectURL(blob);
|
|
||||||
downloadUrl(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
function downloadUrl(url) {
|
|
||||||
const link = document.createElement('a');
|
|
||||||
link.href = url;
|
|
||||||
link.download = 'discussions.json';
|
|
||||||
link.click();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,270 +0,0 @@
|
|||||||
|
|
||||||
function load_discussion(discussion=0){
|
|
||||||
var chatWindow = document.getElementById('chat-window');
|
|
||||||
|
|
||||||
if(discussion)
|
|
||||||
{
|
|
||||||
console.log(discussion.id)
|
|
||||||
body = { id: discussion.id }
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
body = { }
|
|
||||||
}
|
|
||||||
// send query with discussion id to reveal discussion messages
|
|
||||||
fetch('/load_discussion', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
},
|
|
||||||
body: JSON.stringify(body)
|
|
||||||
})
|
|
||||||
.then(response => {
|
|
||||||
if (response.ok) {
|
|
||||||
response.text().then(data => {
|
|
||||||
const messages = JSON.parse(data);
|
|
||||||
console.log(messages)
|
|
||||||
// process messages
|
|
||||||
chatWindow.innerHTML = '';
|
|
||||||
messages.forEach(message => {
|
|
||||||
console.log(`Adding message ${message.type}`)
|
|
||||||
if(message.type==0){
|
|
||||||
console.log("Showing message")
|
|
||||||
addMessage(message.sender, message.content, message.id, message.rank, true);
|
|
||||||
// scroll to bottom of chat window
|
|
||||||
chatWindow.scrollTop = chatWindow.scrollHeight;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
alert('Failed to query the discussion');
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('Failed to get messages:', error);
|
|
||||||
alert('Failed to get messages');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function populate_discussions_list()
|
|
||||||
{
|
|
||||||
// Populate discussions list
|
|
||||||
const discussionsList = document.getElementById('discussions-list');
|
|
||||||
discussionsList.innerHTML = "";
|
|
||||||
fetch('/list_discussions')
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(discussions => {
|
|
||||||
discussions.forEach(discussion => {
|
|
||||||
const buttonWrapper = document.createElement('div');
|
|
||||||
//buttonWrapper.classList.add('flex', 'space-x-2', 'mt-2');
|
|
||||||
buttonWrapper.classList.add('drop-shadow-sm', 'p-1', 'mx-2', 'my-2', 'flex', 'flex-row', 'space-x-2', 'rounded-lg', 'shadow-lg', 'bg-gray-200', 'dark:bg-gray-800', 'transition-colors', 'duration-300', 'text-left');
|
|
||||||
|
|
||||||
const renameButton = document.createElement('button');
|
|
||||||
renameButton.classList.add('bg-gray-400', 'hover:bg-gray-800', 'dark:hover:bg-gray-700', 'text-white', 'dark:text-white', 'font-bold', 'py-0', 'px-0', 'rounded',"w-10","h-10");
|
|
||||||
const renameImg = document.createElement('img');
|
|
||||||
renameImg.src = "/static/images/edit_discussion.png";
|
|
||||||
renameButton.title = "Rename discussion";
|
|
||||||
renameImg.classList.add('py-2', 'px-2', 'rounded', 'w-15', 'h-15');
|
|
||||||
renameButton.appendChild(renameImg);
|
|
||||||
|
|
||||||
//renameButton.style.backgroundImage = "/rename_discussion.svg"; //.textContent = 'Rename';
|
|
||||||
renameButton.addEventListener('click', () => {
|
|
||||||
const dialog = document.createElement('dialog');
|
|
||||||
dialog.classList.add('bg-gray-500', 'text-white', 'rounded', 'p-4');
|
|
||||||
|
|
||||||
const inputLabel = document.createElement('label');
|
|
||||||
inputLabel.textContent = 'New name: ';
|
|
||||||
const inputField = document.createElement('input');
|
|
||||||
inputField.classList.add('border', "px-2", "mx-2", 'bg-gray-800', 'border-gray-400', 'rounded', 'py-1', 'px-2');
|
|
||||||
inputField.setAttribute('type', 'text');
|
|
||||||
inputField.setAttribute('name', 'title');
|
|
||||||
inputField.setAttribute('value', discussion.title);
|
|
||||||
inputLabel.appendChild(inputField);
|
|
||||||
dialog.appendChild(inputLabel);
|
|
||||||
|
|
||||||
const cancelButton = document.createElement('button');
|
|
||||||
cancelButton.textContent = 'Cancel';
|
|
||||||
cancelButton.addEventListener('click', () => {
|
|
||||||
dialog.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
const renameConfirmButton = document.createElement('button');
|
|
||||||
renameConfirmButton.classList.add('bg-gray-500', 'hover:bg-gray-700', 'text-white', 'dark:text-white', 'font-bold', 'py-1', 'px-0', 'rounded', 'ml-2');
|
|
||||||
renameConfirmButton.textContent = 'Rename';
|
|
||||||
renameConfirmButton.addEventListener('click', () => {
|
|
||||||
const newTitle = inputField.value;
|
|
||||||
if (newTitle === '') {
|
|
||||||
alert('New name cannot be empty');
|
|
||||||
} else {
|
|
||||||
fetch('/rename', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
},
|
|
||||||
body: JSON.stringify({ id: discussion.id, title: newTitle })
|
|
||||||
})
|
|
||||||
.then(response => {
|
|
||||||
if (response.ok) {
|
|
||||||
discussion.title = newTitle;
|
|
||||||
discussionButton.textContent = newTitle;
|
|
||||||
dialog.close();
|
|
||||||
} else {
|
|
||||||
alert('Failed to rename discussion');
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('Failed to rename discussion:', error);
|
|
||||||
alert('Failed to rename discussion');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
dialog.appendChild(cancelButton);
|
|
||||||
dialog.appendChild(renameConfirmButton);
|
|
||||||
document.body.appendChild(dialog);
|
|
||||||
dialog.showModal();
|
|
||||||
});
|
|
||||||
const deleteButton = document.createElement('button');
|
|
||||||
deleteButton.classList.add('bg-gray-400', 'hover:bg-gray-800', 'dark:hover:bg-gray-700', 'text-black', 'dark:text-white', 'font-bold', 'py-0', 'px-0', 'rounded',"w-10","h-10");
|
|
||||||
const deleteImg = document.createElement('img');
|
|
||||||
deleteImg.src = "/static/images/delete_discussion.png";
|
|
||||||
deleteButton.title = "Delete discussion";
|
|
||||||
deleteImg.classList.add('py-2', 'px-2', 'rounded', 'w-15', 'h-15');
|
|
||||||
|
|
||||||
deleteButton.addEventListener('click', () => {
|
|
||||||
fetch('/delete_discussion', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
},
|
|
||||||
body: JSON.stringify({ id: discussion.id})
|
|
||||||
})
|
|
||||||
.then(response => {
|
|
||||||
if (response.ok) {
|
|
||||||
buttonWrapper.remove();
|
|
||||||
} else {
|
|
||||||
alert('Failed to delete discussion');
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('Failed to delete discussion:', error);
|
|
||||||
alert('Failed to delete discussion');
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
deleteButton.appendChild(deleteImg);
|
|
||||||
|
|
||||||
const discussionButton = document.createElement('button');
|
|
||||||
discussionButton.id = discussion.id;
|
|
||||||
discussionButton.classList.add('isButton', 'hover:bg-gray-800', 'dark:hover:bg-gray-700', 'text-black', 'dark:text-white', 'font-bold', 'py-2', 'px-4', 'rounded', 'ml-2', 'w-full');
|
|
||||||
discussionButton.textContent = discussion.title;
|
|
||||||
discussionButton.title = "Open discussion";
|
|
||||||
|
|
||||||
//Indicates currently selected (Active) discussion
|
|
||||||
discussionButton.addEventListener('click', () => {
|
|
||||||
console.log(`Showing messages for discussion ${discussion.id}`);
|
|
||||||
load_discussion(discussion);
|
|
||||||
const btnElList = document.querySelectorAll('.isButton');
|
|
||||||
btnElList.forEach(element => {
|
|
||||||
if (element.classList.contains('activeDiscussion')) {
|
|
||||||
element.classList.remove('activeDiscussion');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
discussionButton.classList.add('activeDiscussion');
|
|
||||||
});
|
|
||||||
|
|
||||||
const btnElList = document.querySelectorAll('.isButton');
|
|
||||||
|
|
||||||
btnElList.forEach(btnEl => {
|
|
||||||
btnEl.addEventListener('click', () => {
|
|
||||||
btnEl.querySelector('activeDiscussion')?.classList.remove('activeDiscussion');
|
|
||||||
});
|
|
||||||
})
|
|
||||||
|
|
||||||
buttonWrapper.appendChild(renameButton);
|
|
||||||
buttonWrapper.appendChild(deleteButton);
|
|
||||||
buttonWrapper.appendChild(discussionButton);
|
|
||||||
discussionsList.appendChild(buttonWrapper);
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('Failed to get discussions:', error);
|
|
||||||
alert('Failed to get discussions');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function populate_menu(){
|
|
||||||
// adding export discussion button
|
|
||||||
const exportDiscussionButton = document.querySelector('#export-discussion-button');
|
|
||||||
exportDiscussionButton.title = "Export discussion to a file";
|
|
||||||
exportDiscussionButton.addEventListener('click', () => {
|
|
||||||
fetch(`/export_discussion`)
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(data => {
|
|
||||||
discussion_text = data["discussion_text"]
|
|
||||||
copyToClipboard(discussion_text)
|
|
||||||
const filename = window.prompt('Please enter a filename:', 'discussion.txt');
|
|
||||||
if (filename !== null) {
|
|
||||||
const text = discussion_text;
|
|
||||||
const blob = new Blob([text], { type: 'text/plain' });
|
|
||||||
const url = URL.createObjectURL(blob);
|
|
||||||
const link = document.createElement('a');
|
|
||||||
link.href = url;
|
|
||||||
link.download = filename;
|
|
||||||
link.click();
|
|
||||||
URL.revokeObjectURL(url);
|
|
||||||
}
|
|
||||||
}).catch(function(error){
|
|
||||||
|
|
||||||
});
|
|
||||||
});
|
|
||||||
const actionBtns = document.querySelector('#action-buttons');
|
|
||||||
actionBtns.appendChild(exportDiscussionButton);
|
|
||||||
|
|
||||||
const newDiscussionBtn = document.querySelector('#new-discussion-btn');
|
|
||||||
newDiscussionBtn.title = "Create new discussion";
|
|
||||||
const resetDBButton = document.querySelector('#reset-discussions-btn');
|
|
||||||
resetDBButton.title = "Reset all discussions/database";
|
|
||||||
resetDBButton.addEventListener('click', () => {
|
|
||||||
|
|
||||||
});
|
|
||||||
newDiscussionBtn.addEventListener('click', () => {
|
|
||||||
const chatWindow = document.getElementById('chat-window');
|
|
||||||
|
|
||||||
const discussionName = prompt('Enter a name for the new discussion:');
|
|
||||||
if (discussionName) {
|
|
||||||
const sendbtn = document.querySelector("#submit-input")
|
|
||||||
const waitAnimation = document.querySelector("#wait-animation")
|
|
||||||
const stopGeneration = document.querySelector("#stop-generation")
|
|
||||||
sendbtn.style.display="none";
|
|
||||||
waitAnimation.style.display="block";
|
|
||||||
stopGeneration.style.display="block";
|
|
||||||
|
|
||||||
|
|
||||||
// Add the discussion to the discussion list
|
|
||||||
const discussionItem = document.createElement('li');
|
|
||||||
discussionItem.textContent = discussionName;
|
|
||||||
fetch(`/new_discussion?title=${discussionName}`)
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(data => {
|
|
||||||
console.log(`New chat ${data.welcome_message}`)
|
|
||||||
// Select the new discussion
|
|
||||||
//selectDiscussion(discussionId);
|
|
||||||
chatWindow.innerHTML=""
|
|
||||||
addMessage(data.sender, data.welcome_message,0);
|
|
||||||
|
|
||||||
populate_discussions_list()
|
|
||||||
sendbtn.style.display="block";
|
|
||||||
waitAnimation.style.display="none";
|
|
||||||
stopGeneration.style.display="none";
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
// Handle any errors that occur
|
|
||||||
console.error(error);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
document.getElementById('extensions-link').addEventListener('click', loadExtensionsPage);
|
|
||||||
|
|
||||||
|
|
||||||
function loadExtensionsPage(event) {
|
|
||||||
event.preventDefault(); // Prevent the default link behavior
|
|
||||||
|
|
||||||
fetch('/extensions')
|
|
||||||
.then(response => response.text())
|
|
||||||
.then(html => {
|
|
||||||
document.getElementById('extensions').innerHTML = html;
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('Error loading extensions page:', error);
|
|
||||||
});
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
document.getElementById('help-link').addEventListener('click', loadHelpPage);
|
|
||||||
|
|
||||||
|
|
||||||
function loadHelpPage(event) {
|
|
||||||
event.preventDefault(); // Prevent the default link behavior
|
|
||||||
|
|
||||||
fetch('/help')
|
|
||||||
.then(response => response.text())
|
|
||||||
.then(html => {
|
|
||||||
document.getElementById('help').innerHTML = html;
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('Error loading help page:', error);
|
|
||||||
});
|
|
||||||
}
|
|
@ -1,58 +0,0 @@
|
|||||||
function update_main(){
|
|
||||||
globals.chatWindow = document.getElementById('chat-window');
|
|
||||||
globals.chatForm = document.getElementById('chat-form');
|
|
||||||
globals.userInput = document.getElementById('user-input');
|
|
||||||
globals.stopGeneration = document.getElementById("stop-generation")
|
|
||||||
globals.sendbtn = document.querySelector("#submit-input")
|
|
||||||
globals.waitAnimation = document.querySelector("#wait-animation")
|
|
||||||
|
|
||||||
globals.stopGeneration.addEventListener('click', (event) =>{
|
|
||||||
event.preventDefault();
|
|
||||||
console.log("Stop clicked");
|
|
||||||
fetch('/stop_gen')
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(data => {
|
|
||||||
console.log(data);
|
|
||||||
globals.is_generating = true
|
|
||||||
});
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
function submit_form(){
|
|
||||||
console.log("Submitting")
|
|
||||||
|
|
||||||
// get user input and clear input field
|
|
||||||
message = globals.userInput.value;
|
|
||||||
globals.userInput.value = '';
|
|
||||||
globals.sendbtn.style.display="none";
|
|
||||||
globals.waitAnimation.style.display="block";
|
|
||||||
globals.stopGeneration.style.display = "block";
|
|
||||||
console.log("Sending message to bot")
|
|
||||||
|
|
||||||
globals.user_msg = addMessage('',message, 0, 0, can_edit=true);
|
|
||||||
globals.bot_msg = addMessage('', '', 0, 0, can_edit=true);
|
|
||||||
// scroll to bottom of chat window
|
|
||||||
globals.chatWindow.scrollTop = globals.chatWindow.scrollHeight;
|
|
||||||
|
|
||||||
send_message('generate_msg',{prompt: message})
|
|
||||||
|
|
||||||
|
|
||||||
//socket.emit('stream-text', {text: text});
|
|
||||||
}
|
|
||||||
globals.chatForm.addEventListener('submit', event => {
|
|
||||||
event.preventDefault();
|
|
||||||
submit_form();
|
|
||||||
});
|
|
||||||
globals.userInput.addEventListener("keyup", function(event) {
|
|
||||||
// Check if Enter key was pressed while holding Shift
|
|
||||||
// Also check if Shift + Ctrl keys were pressed while typing
|
|
||||||
// These combinations override the submit action
|
|
||||||
const shiftPressed = event.shiftKey;
|
|
||||||
const ctrlPressed = event.ctrlKey && !event.metaKey;
|
|
||||||
|
|
||||||
if ((!shiftPressed) && event.key === "Enter") {
|
|
||||||
submit_form();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
6
static/js/marked.min.js
vendored
@ -1,391 +0,0 @@
|
|||||||
function selectOptionByText(selectElement, optionText) {
|
|
||||||
for (let i = 0; i < selectElement.options.length; i++) {
|
|
||||||
if (selectElement.options[i].text === optionText) {
|
|
||||||
selectElement.selectedIndex = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fetch('/settings')
|
|
||||||
.then(response => response.text())
|
|
||||||
.then(html => {
|
|
||||||
document.getElementById('settings').innerHTML = html;
|
|
||||||
bindingInput = document.getElementById('binding');
|
|
||||||
modelInput = document.getElementById('model');
|
|
||||||
personalityLanguageInput = document.getElementById('personalities_language');
|
|
||||||
personalityCategoryInput = document.getElementById('personalities_category');
|
|
||||||
personalityInput = document.getElementById('personalities');
|
|
||||||
languageInput = document.getElementById('language');
|
|
||||||
voiceInput = document.getElementById('voice');
|
|
||||||
seedInput = document.getElementById('seed');
|
|
||||||
tempInput = document.getElementById('temperature');
|
|
||||||
nPredictInput = document.getElementById('n-predict');
|
|
||||||
topKInput = document.getElementById('top-k');
|
|
||||||
topPInput = document.getElementById('top-p');
|
|
||||||
repeatPenaltyInput = document.getElementById('repeat-penalty');
|
|
||||||
repeatLastNInput = document.getElementById('repeat-last-n');
|
|
||||||
|
|
||||||
temperatureValue = document.getElementById('temperature-value');
|
|
||||||
n_predictValue = document.getElementById('n-predict-value');
|
|
||||||
topkValue = document.getElementById('top-k-value');
|
|
||||||
toppValue = document.getElementById('top-p-value');
|
|
||||||
|
|
||||||
repeatPenaltyValue = document.getElementById('repeat-penalty-value');
|
|
||||||
repeatLastNValue = document.getElementById('repeat-last-n');
|
|
||||||
|
|
||||||
|
|
||||||
function update_config(){
|
|
||||||
fetch('/get_config')
|
|
||||||
.then((response) => response.json())
|
|
||||||
.then((data) => {
|
|
||||||
console.log("Received config")
|
|
||||||
console.log(data);
|
|
||||||
selectOptionByText(bindingInput, data["binding"])
|
|
||||||
selectOptionByText(modelInput, data["model"])
|
|
||||||
selectOptionByText(personalityLanguageInput, data["personality_language"])
|
|
||||||
selectOptionByText(personalityCategoryInput, data["personality_category"])
|
|
||||||
selectOptionByText(personalityInput, data["personality"])
|
|
||||||
languageInput.value = data["language"]
|
|
||||||
voiceInput.value = data["voice"]
|
|
||||||
seedInput.value = data["seed"]
|
|
||||||
tempInput.value = data["temperature"]
|
|
||||||
nPredictInput.value = data["n_predict"]
|
|
||||||
topKInput.value = data["top_k"]
|
|
||||||
topPInput.value = data["top_p"]
|
|
||||||
|
|
||||||
repeatPenaltyInput.textContent = data["repeat_penalty"]
|
|
||||||
repeatLastNInput.textContent = data["repeat_last_n"]
|
|
||||||
|
|
||||||
temperatureValue.textContent =`Temperature(${data["temperature"]})`
|
|
||||||
n_predictValue.textContent =`N Predict(${data["n_predict"]})`
|
|
||||||
|
|
||||||
topkValue.textContent =`Top-K(${data["top_k"]})`
|
|
||||||
toppValue.textContent =`Top-P(${data["top_p"]})`
|
|
||||||
|
|
||||||
repeatPenaltyValue.textContent =`Repeat penalty(${data["repeat_penalty"]})`
|
|
||||||
repeatLastNValue.textContent =`Repeat last N(${data["repeat_last_n"]})`
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.error('Error:', error);
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bindingInput.addEventListener('input',() => {
|
|
||||||
console.log(`Binding (${bindingInput.value})`)
|
|
||||||
// Use fetch to send form values to Flask endpoint
|
|
||||||
fetch('/set_binding', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify({"binding":bindingInput.value}),
|
|
||||||
})
|
|
||||||
.then((response) => response.json())
|
|
||||||
.then((data) => {
|
|
||||||
console.log(data);
|
|
||||||
if(data["status"]==="no_models_found"){
|
|
||||||
alert("No models found for this binding. Make sure you select a binding that you have models for or download models from links in our repository")
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
populate_settings();
|
|
||||||
alert("Binding set successfully")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.error('Error:', error);
|
|
||||||
alert("Error setting configuration")
|
|
||||||
});
|
|
||||||
})
|
|
||||||
|
|
||||||
modelInput.addEventListener('input',() => {
|
|
||||||
console.log(`Model (${modelInput.value})`)
|
|
||||||
// Use fetch to send form values to Flask endpoint
|
|
||||||
fetch('/set_model', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify({"model":modelInput.value}),
|
|
||||||
})
|
|
||||||
.then((response) => response.json())
|
|
||||||
.then((data) => {
|
|
||||||
console.log(data);
|
|
||||||
populate_settings();
|
|
||||||
alert("Binding set successfully")
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.error('Error:', error);
|
|
||||||
alert("Error setting configuration")
|
|
||||||
});
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
tempInput.addEventListener('input',() => {
|
|
||||||
temperatureValue.textContent =`Temperature(${tempInput.value})`
|
|
||||||
})
|
|
||||||
|
|
||||||
nPredictInput.addEventListener('input',() => {
|
|
||||||
n_predictValue.textContent =`N Predict(${nPredictInput.value})`
|
|
||||||
})
|
|
||||||
|
|
||||||
topKInput.addEventListener('input',() => {
|
|
||||||
topkValue.textContent =`Top-K(${topKInput.value})`
|
|
||||||
})
|
|
||||||
|
|
||||||
topPInput.addEventListener('input',() => {
|
|
||||||
toppValue.textContent =`Top-P(${topPInput.value})`
|
|
||||||
})
|
|
||||||
|
|
||||||
repeatPenaltyInput.addEventListener('input',() => {
|
|
||||||
repeatPenaltyValue.textContent =`Repeat penalty(${repeatPenaltyInput.value})`
|
|
||||||
})
|
|
||||||
|
|
||||||
repeatLastNInput.addEventListener('input',() => {
|
|
||||||
repeatLastNValue.textContent =`Repeat last N(${repeatLastNInput.value})`
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const submitButton = document.getElementById('submit-model-params');
|
|
||||||
submitButton.addEventListener('click', (event) => {
|
|
||||||
// Prevent default form submission
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
// Get form values and put them in an object
|
|
||||||
const formValues = {
|
|
||||||
seed: seedInput.value,
|
|
||||||
binding: bindingInput.value,
|
|
||||||
model: modelInput.value,
|
|
||||||
personality_language:personalityLanguageInput.value,
|
|
||||||
personality_category:personalityCategoryInput.value,
|
|
||||||
personality: personalityInput.value,
|
|
||||||
language: languageInput.value,
|
|
||||||
voice: voiceInput.value,
|
|
||||||
temperature: tempInput.value,
|
|
||||||
nPredict: nPredictInput.value,
|
|
||||||
topK: topKInput.value,
|
|
||||||
topP: topPInput.value,
|
|
||||||
repeatPenalty: repeatPenaltyInput.value,
|
|
||||||
repeatLastN: repeatLastNInput.value
|
|
||||||
};
|
|
||||||
console.log(formValues);
|
|
||||||
// Use fetch to send form values to Flask endpoint
|
|
||||||
fetch('/update_model_params', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
body: JSON.stringify(formValues),
|
|
||||||
})
|
|
||||||
.then((response) => response.json())
|
|
||||||
.then((data) => {
|
|
||||||
console.log(data);
|
|
||||||
alert("Configuration set successfully")
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.error('Error:', error);
|
|
||||||
alert("Error setting configuration")
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
populate_settings();
|
|
||||||
|
|
||||||
function populate_settings(){
|
|
||||||
// Get a reference to the <select> element
|
|
||||||
const selectBinding = document.getElementById('binding');
|
|
||||||
const selectModel = document.getElementById('model');
|
|
||||||
|
|
||||||
const selectPersonalityLanguage = document.getElementById('personalities_language');
|
|
||||||
const selectPersonalityCategory = document.getElementById('personalities_category');
|
|
||||||
const selectPersonality = document.getElementById('personalities');
|
|
||||||
|
|
||||||
function populate_bindings(){
|
|
||||||
selectBinding.innerHTML = "";
|
|
||||||
// Fetch the list of .bin files from the models subfolder
|
|
||||||
fetch('/list_bindings')
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(data => {
|
|
||||||
if (Array.isArray(data)) {
|
|
||||||
// data is an array
|
|
||||||
data.forEach(filename => {
|
|
||||||
const optionElement = document.createElement('option');
|
|
||||||
optionElement.value = filename;
|
|
||||||
optionElement.textContent = filename;
|
|
||||||
selectBinding.appendChild(optionElement);
|
|
||||||
});
|
|
||||||
|
|
||||||
// fetch('/get_args')
|
|
||||||
// .then(response=> response.json())
|
|
||||||
// .then(data=>{
|
|
||||||
|
|
||||||
// })
|
|
||||||
} else {
|
|
||||||
console.error('Expected an array, but received:', data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function populate_models(){
|
|
||||||
selectModel.innerHTML=""
|
|
||||||
// Fetch the list of .bin files from the models subfolder
|
|
||||||
fetch('/list_models')
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(data => {
|
|
||||||
if (Array.isArray(data)) {
|
|
||||||
// data is an array
|
|
||||||
data.forEach(filename => {
|
|
||||||
const optionElement = document.createElement('option');
|
|
||||||
optionElement.value = filename;
|
|
||||||
optionElement.textContent = filename;
|
|
||||||
selectModel.appendChild(optionElement);
|
|
||||||
});
|
|
||||||
|
|
||||||
// fetch('/get_args')
|
|
||||||
// .then(response=> response.json())
|
|
||||||
// .then(data=>{
|
|
||||||
|
|
||||||
// })
|
|
||||||
} else {
|
|
||||||
console.error('Expected an array, but received:', data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
function populate_personalities_languages(){
|
|
||||||
const selectPersonalityLanguage = document.getElementById('personalities_language');
|
|
||||||
selectPersonalityLanguage.innerHTML=""
|
|
||||||
// Fetch the list of .yaml files from the models subfolder
|
|
||||||
fetch('/list_personalities_languages')
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(data => {
|
|
||||||
if (Array.isArray(data)) {
|
|
||||||
// data is an array
|
|
||||||
data.forEach(filename => {
|
|
||||||
const optionElement = document.createElement('option');
|
|
||||||
optionElement.value = filename;
|
|
||||||
optionElement.textContent = filename;
|
|
||||||
selectPersonalityLanguage.appendChild(optionElement);
|
|
||||||
});
|
|
||||||
|
|
||||||
// fetch('/get_args')
|
|
||||||
// .then(response=> response.json())
|
|
||||||
// .then(data=>{
|
|
||||||
|
|
||||||
// })
|
|
||||||
} else {
|
|
||||||
console.error('Expected an array, but received:', data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
function populate_personalities_categories(){
|
|
||||||
const selectPersonalityCategory = document.getElementById('personalities_category');
|
|
||||||
selectPersonalityCategory.innerHTML=""
|
|
||||||
// Fetch the list of .yaml files from the models subfolder
|
|
||||||
fetch('/list_personalities_categories')
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(data => {
|
|
||||||
if (Array.isArray(data)) {
|
|
||||||
// data is an array
|
|
||||||
data.forEach(filename => {
|
|
||||||
const optionElement = document.createElement('option');
|
|
||||||
optionElement.value = filename;
|
|
||||||
optionElement.textContent = filename;
|
|
||||||
selectPersonalityCategory.appendChild(optionElement);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
console.error('Expected an array, but received:', data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
function populate_personalities(){
|
|
||||||
const selectPersonalityLanguage = document.getElementById('personalities_language');
|
|
||||||
|
|
||||||
selectPersonality.innerHTML=""
|
|
||||||
// Fetch the list of .yaml files from the models subfolder
|
|
||||||
fetch('/list_personalities')
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(data => {
|
|
||||||
if (Array.isArray(data)) {
|
|
||||||
// data is an array
|
|
||||||
data.forEach(filename => {
|
|
||||||
const optionElement = document.createElement('option');
|
|
||||||
optionElement.value = filename;
|
|
||||||
optionElement.textContent = filename;
|
|
||||||
selectPersonality.appendChild(optionElement);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
console.error('Expected an array, but received:', data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function set_personality_language(lang, callback) {
|
|
||||||
fetch(`/set_personality_language?language=${lang}`)
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(data => {
|
|
||||||
callback(data);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Example usage: call another function after set_personality_language returns
|
|
||||||
selectPersonalityLanguage.addEventListener('click', function() {
|
|
||||||
set_personality_language(selectPersonalityLanguage.value, function(data) {
|
|
||||||
console.log('Response received:', data);
|
|
||||||
populate_personalities_categories();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
function set_personality_category(category, callback) {
|
|
||||||
fetch(`/set_personality_category?category=${category}`)
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(data => {
|
|
||||||
callback()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Example usage: call another function after set_personality_category returns
|
|
||||||
selectPersonalityCategory.addEventListener('click', function() {
|
|
||||||
set_personality_category(selectPersonalityCategory.value, function(data) {
|
|
||||||
console.log('Response received:', data);
|
|
||||||
populate_personalities();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
populate_bindings()
|
|
||||||
populate_models()
|
|
||||||
populate_personalities_languages()
|
|
||||||
populate_personalities_categories()
|
|
||||||
populate_personalities()
|
|
||||||
setTimeout(update_config,100);
|
|
||||||
|
|
||||||
// Fetch the list of .yaml files from the models subfolder
|
|
||||||
fetch('/list_languages')
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(data => {
|
|
||||||
if (Array.isArray(data)) {
|
|
||||||
// data is an array
|
|
||||||
const selectLanguage = document.getElementById('language');
|
|
||||||
data.forEach(row => {
|
|
||||||
const optionElement = document.createElement('option');
|
|
||||||
optionElement.value = row.value;
|
|
||||||
optionElement.innerHTML = row.label;
|
|
||||||
selectLanguage.appendChild(optionElement);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
console.error('Expected an array, but received:', data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('Error loading settings page:', error);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
|||||||
function showTab(tabId) {
|
|
||||||
// hide all tabs
|
|
||||||
var tabs = document.getElementsByClassName('tab-pane');
|
|
||||||
for (var i = 0; i < tabs.length; i++) {
|
|
||||||
tabs[i].style.display = 'none';
|
|
||||||
}
|
|
||||||
// show the selected tab
|
|
||||||
console.log(tabId)
|
|
||||||
var tab = document.getElementById(tabId);
|
|
||||||
tab.style.display = 'block';
|
|
||||||
}
|
|
||||||
|
|
||||||
// show the main tab by default
|
|
||||||
showTab('main');
|
|
||||||
// add event listeners to the tab links
|
|
||||||
var tabLinks = document.getElementsByTagName('a');
|
|
||||||
for (var i = 0; i < tabLinks.length; i++) {
|
|
||||||
tabLinks[i].addEventListener('click', function (event) {
|
|
||||||
event.preventDefault();
|
|
||||||
var tabId = this.getAttribute('href').substring(1);
|
|
||||||
showTab(tabId);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fetch('/main')
|
|
||||||
.then(response => response.text())
|
|
||||||
.then(html => {
|
|
||||||
document.getElementById('main').innerHTML = html;
|
|
||||||
// First time we populate the discussions list
|
|
||||||
populate_discussions_list()
|
|
||||||
populate_menu();
|
|
||||||
load_discussion();
|
|
||||||
update_main();
|
|
||||||
db_export();
|
|
||||||
|
|
||||||
// Dirty fix for disabling speech synth for firefox browsers :()
|
|
||||||
if (!userAgent.match(/firefox|fxios/i)) {
|
|
||||||
prepre_audio();
|
|
||||||
add_audio_in_ui();
|
|
||||||
populateVoicesList();
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('Error loading main page:', error);
|
|
||||||
});
|
|
@ -1,8 +0,0 @@
|
|||||||
// Default starts with dark mode.
|
|
||||||
document.documentElement.classList.add('dark');
|
|
||||||
// Changes theme based on user's device preference when page is loaded.
|
|
||||||
if (localStorage.getItem('color-theme') === 'dark' || (!('color-theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
|
|
||||||
document.documentElement.classList.add('dark');
|
|
||||||
} else {
|
|
||||||
document.documentElement.classList.remove('dark')
|
|
||||||
}
|
|
@ -1,46 +0,0 @@
|
|||||||
var themeToggleDarkIcon = document.getElementById(
|
|
||||||
"theme-toggle-dark-icon"
|
|
||||||
);
|
|
||||||
var themeToggleLightIcon = document.getElementById(
|
|
||||||
"theme-toggle-light-icon"
|
|
||||||
);
|
|
||||||
|
|
||||||
// Change the icons inside the button based on previous settings
|
|
||||||
if (
|
|
||||||
localStorage.getItem("color-theme") === "dark" ||
|
|
||||||
(!("color-theme" in localStorage) &&
|
|
||||||
window.matchMedia("(prefers-color-scheme: dark)").matches)
|
|
||||||
) {
|
|
||||||
themeToggleLightIcon.classList.remove("hidden");
|
|
||||||
} else {
|
|
||||||
themeToggleDarkIcon.classList.remove("hidden");
|
|
||||||
}
|
|
||||||
|
|
||||||
var themeToggleBtn = document.getElementById("theme-toggle");
|
|
||||||
|
|
||||||
themeToggleBtn.addEventListener("click", function () {
|
|
||||||
// toggle icons inside button
|
|
||||||
themeToggleDarkIcon.classList.toggle("hidden");
|
|
||||||
themeToggleLightIcon.classList.toggle("hidden");
|
|
||||||
|
|
||||||
// if set via local storage previously
|
|
||||||
if (localStorage.getItem("color-theme")) {
|
|
||||||
if (localStorage.getItem("color-theme") === "light") {
|
|
||||||
document.documentElement.classList.add("dark");
|
|
||||||
localStorage.setItem("color-theme", "dark");
|
|
||||||
} else {
|
|
||||||
document.documentElement.classList.remove("dark");
|
|
||||||
localStorage.setItem("color-theme", "light");
|
|
||||||
}
|
|
||||||
|
|
||||||
// if NOT set via local storage previously
|
|
||||||
} else {
|
|
||||||
if (document.documentElement.classList.contains("dark")) {
|
|
||||||
document.documentElement.classList.remove("dark");
|
|
||||||
localStorage.setItem("color-theme", "light");
|
|
||||||
} else {
|
|
||||||
document.documentElement.classList.add("dark");
|
|
||||||
localStorage.setItem("color-theme", "dark");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,15 +0,0 @@
|
|||||||
document.getElementById('training-link').addEventListener('click', loadHelpPage);
|
|
||||||
|
|
||||||
|
|
||||||
function loadHelpPage(event) {
|
|
||||||
event.preventDefault(); // Prevent the default link behavior
|
|
||||||
|
|
||||||
fetch('/training')
|
|
||||||
.then(response => response.text())
|
|
||||||
.then(html => {
|
|
||||||
document.getElementById('training').innerHTML = html;
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('Error loading help page:', error);
|
|
||||||
});
|
|
||||||
}
|
|
@ -1,89 +0,0 @@
|
|||||||
// Project : lollms-webui
|
|
||||||
// Author : ParisNeo
|
|
||||||
// Description :
|
|
||||||
// All websocket stuff can be found here.
|
|
||||||
|
|
||||||
|
|
||||||
var globals={
|
|
||||||
is_generating:false,
|
|
||||||
chatWindow:undefined,
|
|
||||||
chatForm:undefined,
|
|
||||||
userInput:undefined,
|
|
||||||
stopGeneration:undefined,
|
|
||||||
sendbtn:undefined,
|
|
||||||
waitAnimation:undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
var socket = io.connect(location.protocol + '//' + document.domain + ':' + location.port);
|
|
||||||
|
|
||||||
socket.on('connect', function() {
|
|
||||||
console.log("Disconnected")
|
|
||||||
});
|
|
||||||
// Handle reconnection attempt failure
|
|
||||||
socket.on('reconnect_failed', () => {
|
|
||||||
console.log('All reconnection attempts failed');
|
|
||||||
// You can perform any custom actions or error handling here
|
|
||||||
});
|
|
||||||
|
|
||||||
// Handle reconnection attempt
|
|
||||||
socket.on('reconnect_attempt', () => {
|
|
||||||
reconnectionAttempt++;
|
|
||||||
console.log(`Reconnection attempt ${reconnectionAttempt}...`);
|
|
||||||
// You can perform custom actions or error handling for each attempt here
|
|
||||||
});
|
|
||||||
socket.on('disconnect', function() {
|
|
||||||
console.log("Disconnected")
|
|
||||||
});
|
|
||||||
socket.on('infos', function(msg) {
|
|
||||||
console.log(msg)
|
|
||||||
if(msg["status"]=="generation_started"){
|
|
||||||
if(globals.user_msg){
|
|
||||||
globals.user_msg.setSender(msg.user);
|
|
||||||
globals.user_msg.setMessage(msg.message);
|
|
||||||
globals.user_msg.setID(msg.id);
|
|
||||||
}
|
|
||||||
globals.bot_msg.setSender(msg.bot);
|
|
||||||
globals.bot_msg.setID(msg.ai_message_id);
|
|
||||||
globals.bot_msg.messageTextElement.innerHTML = `Generating answer. Please stand by...`;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
globals.sendbtn.style.display="block";
|
|
||||||
globals.waitAnimation.style.display="none";
|
|
||||||
globals.stopGeneration.style.display = "none";
|
|
||||||
globals.is_generating = false
|
|
||||||
alert("It seems that no model has been loaded. Please download and install a model first, then try again.");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on('waiter', function(msg) {
|
|
||||||
globals.bot_msg.messageTextElement.innerHTML = `Generating answer. Please stand by...`;
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on('message', function(msg) {
|
|
||||||
text = msg.data;
|
|
||||||
// For the other enrtries, these are just the text of the chatbot
|
|
||||||
|
|
||||||
globals.bot_msg.messageTextElement.innerHTML = marked.marked(text);
|
|
||||||
// scroll to bottom of chat window
|
|
||||||
globals.chatWindow.scrollTop = globals.chatWindow.scrollHeight;
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on('final',function(msg){
|
|
||||||
text = msg.data;
|
|
||||||
globals.bot_msg.hiddenElement.innerHTML = text
|
|
||||||
globals.bot_msg.messageTextElement.innerHTML = marked.marked(text)
|
|
||||||
globals.sendbtn.style.display="block";
|
|
||||||
globals.waitAnimation.style.display="none";
|
|
||||||
globals.stopGeneration.style.display = "none";
|
|
||||||
globals.is_generating = false
|
|
||||||
});
|
|
||||||
|
|
||||||
globals.socket = socket
|
|
||||||
globals.is_generating = false
|
|
||||||
|
|
||||||
function send_message(service_name, parameters){
|
|
||||||
if(!globals.is_generating){
|
|
||||||
globals.socket.emit(service_name, parameters);
|
|
||||||
globals.is_generating = true
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
|
|
||||||
<form id="model-params-form" class="bg-gray-50 dark:bg-gray-700 shadow-md rounded px-8 py-8 pt-6 pb-8 mb-4 text-black dark:text-white">
|
|
||||||
<div></div>
|
|
||||||
<div class="mb-4">
|
|
||||||
<button type="submit" id="submit-model-params" class="my-1 mx-1 outline-none px-4 bg-accent rounded-md bg-gray-500 hover:bg-gray-300 transition-colors ease-in-out">save extensions settings</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<footer class="bottom-0 text-black dark:text-white">
|
|
||||||
This section is under development. Stay tuned.<br>
|
|
||||||
To have a glimpse of what extensions and options will be added, please look at my chatgpt-personality-selector google chrome extension:<br>
|
|
||||||
<br>
|
|
||||||
* <a href="https://chrome.google.com/webstore/detail/chatgpt-personality-selec/jdmpccdlifdkhniemenfmieffkdblahk?hl=en">https://chrome.google.com/webstore/detail/chatgpt-personality-selec/jdmpccdlifdkhniemenfmieffkdblahk?hl=en</a>
|
|
||||||
<br>
|
|
||||||
<br>
|
|
||||||
After installing the extension, go to <a href="chat.openai.com/chat"/> and the extension popup will apear.<br>
|
|
||||||
All personalities will be implemented to gpt4All and can be used with any llamacpp or gpt-j model.
|
|
||||||
</footer>
|
|
@ -1,119 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Help | lollms-webui</title>
|
|
||||||
<!-- Include Tailwind CSS -->
|
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/utilities.min.css') }}">
|
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/tailwind.min.css') }}">
|
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/tailwindcss.min.css') }}">
|
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/tailwind-dark.min.css') }}">
|
|
||||||
<!-- Include custom CSS -->
|
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/help.css') }}">
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<!-- Navbar -->
|
|
||||||
<nav class="flex justify-between items-center bg-gray-200 dark:bg-gray-900 text-black dark:text-white p-4">
|
|
||||||
<a href="/" class="text-lg font-bold">lollms-webui</a>
|
|
||||||
<!-- Dropdown menu -->
|
|
||||||
<div class="relative">
|
|
||||||
<button class="flex items-center text-lg font-bold">
|
|
||||||
Help
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor"
|
|
||||||
class="ml-2 h-5 w-5 transform transition-transform duration-300">
|
|
||||||
<path fill-rule="evenodd"
|
|
||||||
d="M6.293 6.293a1 1 0 0 0-1.414 1.414L8.586 12l-3.707 3.293a1 1 0 1 0 1.414 1.414l4-4a1 1 0 0 0 0-1.414l-4-4a1 1 0 0 0-.707-.293zm7.414 0a1 1 0 0 1 1.414 0l4 4a1 1 0 0 1 0 1.414l-4 4a1 1 0 1 1-1.414-1.414L11.414 12l3.293-3.293a1 1 0 0 1 1.414 0z" />
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<ul class="absolute right-0 w-40 mt-2 py-2 bg-white rounded-md shadow-xl z-10 hidden">
|
|
||||||
<li><a href="#credits" class="block px-4 py-2 text-gray-800 hover:bg-gray-100">Credits</a></li>
|
|
||||||
<li><a href="#how-to-use" class="block px-4 py-2 text-gray-800 hover:bg-gray-100">How to use</a></li>
|
|
||||||
<li><a href="#faq" class="block px-4 py-2 text-gray-800 hover:bg-gray-100">FAQ</a></li>
|
|
||||||
<li><a href="#examples" class="block px-4 py-2 text-gray-800 hover:bg-gray-100">Examples</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<!-- Credits section -->
|
|
||||||
<section id="credits" class="mb-8 ml-4 text-black dark:text-white">
|
|
||||||
<h2 class="text-2xl font-bold mb-4">Credits</h2>
|
|
||||||
<p class="mb-4">Here are the developers who worked on this website:</p>
|
|
||||||
<ul class="list-disc list-inside mb-4">
|
|
||||||
<li>@ParisNeo : Creator of the project and Lead developer</li>
|
|
||||||
<li>@AndriyMulyar : CEO of Nomic-ai who offered to link the project as their official ui for LoLLMs</li>
|
|
||||||
<li><a href="https://github.com/ParisNeo/lollms-webui/graphs/contributors" target="_blank" class="text-blue-900 dark:text-blue-600">A number of very talented open-source developers without whom this project wouldn't be as awesome as it is.</a></li>
|
|
||||||
<li> We also appreciate the support of the users of this tool who have helped us in various ways.</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<p class="mb-4">We would also like to acknowledge the following open-source projects that we used:</p>
|
|
||||||
<ul class="list-disc list-inside mb-4">
|
|
||||||
<li>pyllamacpp</li>
|
|
||||||
<li>llamacpp</li>
|
|
||||||
<li>llama</li>
|
|
||||||
<li>tailwindcss</li>
|
|
||||||
</ul>
|
|
||||||
<p>Thank you to everyone who contributed to the development of this project!</p>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- How to use section -->
|
|
||||||
<section id="how-to-use" class="mb-8 ml-4 text-black dark:text-white">
|
|
||||||
<h2 class="text-2xl font-bold mb-4">How to use</h2>
|
|
||||||
<ol class="list-decimal list-inside mb-4">
|
|
||||||
<li>Step 1: Write your prompt.</li>
|
|
||||||
<li>Step 2: Press enter or click the send button.</li>
|
|
||||||
<li>Step 3: Read the output.</li>
|
|
||||||
<li>Step 4: Rank the output if you want or edit it.</li>
|
|
||||||
<li>Step 5: Continue the discussion untill you have no more queries.</li>
|
|
||||||
</ol>
|
|
||||||
<p class="mb-4">Here are some tips and tricks to help you get the most out of this website:</p>
|
|
||||||
<ul class="list-disc list-inside">
|
|
||||||
<li>Tip 1: Be specific with your questions.</li>
|
|
||||||
<li>Tip 2: The model needs to be tamed. So try to put it in the mood to answer your question.</li>
|
|
||||||
<li>Tip 3: The model can give helarious, false or completely made up responses. So be vigilant not to use the model for sensitive subjects like medication or financial advice</li>
|
|
||||||
</ul>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- FAQ section -->
|
|
||||||
<section id="faq">
|
|
||||||
<h2 class="text-2xl font-bold mb-4 ml-4 text-black dark:text-white">Frequently Asked Questions (FAQ)</h2>
|
|
||||||
<dl class="mb-8 ml-4 text-black dark:text-white">
|
|
||||||
<div class="mb-4">
|
|
||||||
<dt class="font-bold">How to install?</dt>
|
|
||||||
<dd>Download the model from the github then use install.bat for windows and install.sh for linux/macOsX.</dd>
|
|
||||||
</div>
|
|
||||||
</dl>
|
|
||||||
</section>
|
|
||||||
<section id="examples">
|
|
||||||
<h2 class="text-2xl font-bold mb-4 ml-4 text-black dark:text-white">Usage examples</h2>
|
|
||||||
<dl class="mb-8 ml-4 text-black dark:text-white">
|
|
||||||
<div class="mb-4">
|
|
||||||
<dt class="font-bold">Casual discussion</dt>
|
|
||||||
<dd>Hello, my name is (put your name here).</dd>
|
|
||||||
<dt class="font-bold">Color picker for css</dt>
|
|
||||||
<dd>What is the hex code for the color pink.</dd>
|
|
||||||
<dt class="font-bold">Movie plot</dt>
|
|
||||||
<dd>Come up with an interesting idea for a new movie plot. Your plot should be described with a title and a summary.</dd>
|
|
||||||
<dt class="font-bold">Programming questions</dt>
|
|
||||||
<dd>Write a python function that reverses a string.</dd>
|
|
||||||
<dt class="font-bold">Ask about dogs</dt>
|
|
||||||
<dd>List 10 dogs.</dd>
|
|
||||||
<dt class="font-bold">Weird stuff</dt>
|
|
||||||
<dd>Write me a poem about the fall of Julius Ceasar into a ceasar salad in iambic pentameter.</dd>
|
|
||||||
<dt class="font-bold">Culinary help</dt>
|
|
||||||
<dd>Act as ChefAI an AI that has the ability to create recipes for any occasion. Instruction: Give me a recipe for my next anniversary.</dd>
|
|
||||||
<dt class="font-bold">General culture</dt>
|
|
||||||
<dd>Who is Abraham Lincoln?</dd>
|
|
||||||
<dt class="font-bold">Writing a letter</dt>
|
|
||||||
<dd>write a letter to my collegue and tell him I can't make it to work today. Make it humorous.</dd>
|
|
||||||
<dt class="font-bold">Love poem</dt>
|
|
||||||
<dd>write a poem about love between two AIs.</dd>
|
|
||||||
</div>
|
|
||||||
</dl>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,76 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>LoLLMs - WEBUI</title>
|
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/utilities.min.css') }}">
|
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/tailwind.min.css') }}">
|
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/tailwindcss.min.css') }}">
|
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/tailwind-dark.min.css') }}">
|
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/chat.css') }}">
|
|
||||||
<link rel="shortcut icon" href="{{ url_for('static', filename='images/favicon.ico') }}" type="image/x-icon">
|
|
||||||
</head>
|
|
||||||
<body class="w-screen h-500 bg-primary text-gray-400 flex flex-col bg-gray-200 dark:bg-gray-900 h-screen overflow-hidden">
|
|
||||||
<div class="w-full h-50 border-b-4 border-black dark:border-gray-600 text-2xl font-bold flex justify-between items-center px-6 py-6">
|
|
||||||
<div class="flex">
|
|
||||||
<div class="w-12 h-12"><a href="#main"><img src="{{ url_for('static', filename='images/icon.png') }}"></a></div>
|
|
||||||
<div class="contents">
|
|
||||||
<button id="theme-toggle" type="button" class="ml-5 bg-gray-200 dark:bg-gray-900 hover:bg-gray-300 dark:hover:bg-gray-500 rounded-lg text-sm p-2.5">
|
|
||||||
<img id="theme-toggle-dark-icon" class="hidden w-5 h-5" fill="currentColor" viewBox="0 0 20 20" src="{{ url_for('static', filename='images/dark.svg') }}"></img>
|
|
||||||
<img id="theme-toggle-light-icon" class="hidden w-5 h-5" fill="currentColor" viewBox="0 0 20 20" src="{{ url_for('static', filename='images/light.svg') }}"></img>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<h1 class="text-2xl text-black dark:text-white">LOLLMS - WEBUI</h1>
|
|
||||||
</div>
|
|
||||||
<div class="content-center items-center mt-4">
|
|
||||||
<ul class="flex
|
|
||||||
content-center items-center">
|
|
||||||
<li class="mr-1">
|
|
||||||
<a href="#main" class="bg-gray-50 dark:bg-gray-700 text-black dark:text-gray-200 py-2 px-4 rounded-t-md font-medium hover:bg-gray-800 hover:text-white dark:hover:bg-gray-200 dark:hover:text-black" id="main-link">Main</a>
|
|
||||||
</li>
|
|
||||||
<li class="mr-1">
|
|
||||||
<a href="#settings" class="bg-gray-50 dark:bg-gray-700 text-black dark:text-gray-200 py-2 px-4 rounded-t-md font-medium hover:bg-gray-800 hover:text-white dark:hover:bg-gray-200 dark:hover:text-black" id="settings-link">Settings</a>
|
|
||||||
</li>
|
|
||||||
<li class="mr-1">
|
|
||||||
<a href="#extensions" class="bg-gray-50 dark:bg-gray-700 text-black dark:text-gray-200 py-2 px-4 rounded-t-md font-medium hover:bg-gray-800 hover:text-white dark:hover:bg-gray-200 dark:hover:text-black" id="extensions-link">Extensions</a>
|
|
||||||
</li>
|
|
||||||
<li class="mr-1">
|
|
||||||
<a href="#training" class="bg-gray-50 dark:bg-gray-700 text-black dark:text-gray-200 py-2 px-4 rounded-t-md font-medium hover:bg-gray-800 hover:text-white dark:hover:bg-gray-200 dark:hover:text-black" id="training-link">Training</a>
|
|
||||||
</li>
|
|
||||||
<li class="mr-1">
|
|
||||||
<a href="#help" class="bg-gray-50 dark:bg-gray-700 text-black dark:text-gray-200 py-2 px-4 rounded-t-md font-medium hover:bg-gray-800 hover:text-white dark:hover:bg-gray-200 dark:hover:text-black" id="help-link">Help</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div id="main" class="tab-pane flex flex-row flex-1">
|
|
||||||
</div>
|
|
||||||
<div class="tab-pane flex-1 overflow-auto" id="settings" style="display: none;">
|
|
||||||
</div>
|
|
||||||
<div class="tab-pane flex-1 overflow-auto" id="extensions" style="display: none;">
|
|
||||||
</div>
|
|
||||||
<div class="tab-pane flex-1 overflow-auto" id="training" style="display: none;">
|
|
||||||
</div>
|
|
||||||
<div class="tab-pane flex-1 overflow-auto" id="help" style="display: none;">
|
|
||||||
</div>
|
|
||||||
<footer class="border-t border-accent flex">
|
|
||||||
</footer>
|
|
||||||
<script src="{{ url_for('static', filename='js/socket.io.js') }}"></script>
|
|
||||||
<script src="{{ url_for('static', filename='js/websocket.js') }}"></script>
|
|
||||||
<script src="{{ url_for('static', filename='js/chat.js') }}"></script>
|
|
||||||
<script src="{{ url_for('static', filename='js/marked.min.js') }}"></script>
|
|
||||||
<script src="{{ url_for('static', filename='js/discussions.js') }}"></script>
|
|
||||||
<script src="{{ url_for('static', filename='js/main.js') }}"></script>
|
|
||||||
<script src="{{ url_for('static', filename='js/extensions.js') }}"></script>
|
|
||||||
<script src="{{ url_for('static', filename='js/training.js') }}"></script>
|
|
||||||
<script src="{{ url_for('static', filename='js/help.js') }}"></script>
|
|
||||||
|
|
||||||
<script src="{{ url_for('static', filename='js/settings.js') }}"></script>
|
|
||||||
<script src="{{ url_for('static', filename='js/db_export.js') }}"></script>
|
|
||||||
<script src="{{ url_for('static', filename='js/audio.js') }}"></script>
|
|
||||||
<script src="{{ url_for('static', filename='js/tabs.js') }}"></script>
|
|
||||||
|
|
||||||
<script src="{{ url_for('static', filename='js/themechecker.js') }}"></script>
|
|
||||||
<script src="{{ url_for('static', filename='js/themetoggle.js') }}"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,45 +0,0 @@
|
|||||||
<div class="flex h-screen w-screen">
|
|
||||||
<div class="w-1/4 flex flex-col rounded bg-gray-50 dark:bg-gray-700 text-white h-full overflow-hidden">
|
|
||||||
<div id="action-buttons" class="flex-shrink-0 h-10 ml-1.5 mt-2 mb-4">
|
|
||||||
<button id="new-discussion-btn" class="px-4 py-4 rounded bg-gray-400 dark:bg-gray-700 hover:bg-gray-600 dark:hover:bg-gray-600">
|
|
||||||
<img src="/static/images/new_message.png" class="w-5 h-5">
|
|
||||||
</button>
|
|
||||||
<button id="reset-discussions-btn" class="px-4 py-4 rounded bg-gray-400 dark:bg-gray-700 hover:bg-gray-600 dark:hover:bg-gray-600">
|
|
||||||
<img src="/static/images/reset_db.png" class="w-5 h-5">
|
|
||||||
</button>
|
|
||||||
<button value="Export" id="export-button" class="px-4 py-4 rounded bg-gray-400 dark:bg-gray-700 hover:bg-gray-600 dark:hover:bg-gray-600">
|
|
||||||
<img src="/static/images/export_database.png" class="w-5 h-5">
|
|
||||||
</button>
|
|
||||||
<button value="Export-discussion" id="export-discussion-button" class="px-4 py-4 rounded bg-gray-400 dark:bg-gray-700 hover:bg-gray-600 dark:hover:bg-gray-600">
|
|
||||||
<img src="/static/images/export_discussion.png" class="w-5 h-5">
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="flex-shrink-0 p-0 ml-1.5">
|
|
||||||
<h1 class="font-bold font-large text-black dark:text-white">Discussions</h1>
|
|
||||||
</div>
|
|
||||||
<div class="flex-1 overflow-y-auto p-0">
|
|
||||||
<div id="discussions-list" class="pb-96" >
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="flex-1 flex flex-col overflow-hidden">
|
|
||||||
<div class="flex-shrink-0 p-4 bg-gray-50 dark:bg-gray-700 pl-7 text-black dark:text-white">
|
|
||||||
<h1 class="font-bold font-large">Chat box</h1>
|
|
||||||
</div>
|
|
||||||
<div class="flex-grow overflow-y-auto p-0 bg-gray-50 dark:bg-gray-700 rounded">
|
|
||||||
<div id="chat-window" class="pb-96">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="w-full flex justify-center">
|
|
||||||
<div class="w-full flex bottom-0 fixed rounded-sm shadow shadow-white bg-gray-300 p-1 dark:bg-gray-500 flex-wrap">
|
|
||||||
<form id="chat-form" class="w-full flex-row text-white mr-15 p-15">
|
|
||||||
<textarea type="text" id="user-input" placeholder="Type your message..." class="dark:bg-gray-600 pl-1 pr-1 py-1 my-1 mr-2 text-black dark:text-white outline-none drop-shadow-sm w-full rounded-md flex-1"></textarea>
|
|
||||||
<div id="wait-animation" style="display: none;" class="lds-facebook bg-secondary my-1 mx-1 outline-none drop-shadow-sm w-full rounded-md p-2"><div></div><div></div><div></div></div>
|
|
||||||
<button id="stop-generation" style="display: none;" class="my-1 mx-1 outline-none px-4 dark:bg-gray-900 text-black dark:text-white rounded-md hover:bg-[#7ba0ea] active:bg-[#3d73e1] transition-colors ease-in-out">Stop generating</button>
|
|
||||||
<input type="submit" value="Send" id="submit-input" class="my-1 mx-1 outline-none px-4 dark:bg-gray-900 text-black dark:text-white rounded-md hover:bg-[#7ba0ea] active:bg-[#3d73e1] transition-colors ease-in-out">
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,71 +0,0 @@
|
|||||||
<div class="h-full overflow-y-auto">
|
|
||||||
<form id="model-params-form" class="bg-gray-50 dark:bg-gray-700 shadow-md rounded px-8 py-8 pt-6 pb-8 mb-4 text-black dark:text-white">
|
|
||||||
<div class="mb-4 flex-row">
|
|
||||||
<label class="font-bold" for="model">Binding</label>
|
|
||||||
<select class="bg-gray-200 dark:bg-gray-700 w-96 shadow appearance-none border rounded py-2 px-3 leading-tight focus:outline-none focus:shadow-outline" id="binding" name="binding">
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="mb-4 flex-row">
|
|
||||||
<label class="font-bold" for="model">Model</label>
|
|
||||||
<select class="bg-gray-200 dark:bg-gray-700 w-96 shadow appearance-none border rounded py-2 px-3 leading-tight focus:outline-none focus:shadow-outline" id="model" name="model">
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="mb-4 flex-row">
|
|
||||||
<label class="font-bold mb-2" for="model">Personalities Languages</label>
|
|
||||||
<select class="bg-gray-200 dark:bg-gray-700 shadow appearance-none border rounded py-2 px-3 leading-tight focus:outline-none focus:shadow-outline" id="personalities_language" name="personalities_language" value="English">
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="mb-4 flex-row">
|
|
||||||
<label class="font-bold mb-2" for="model">Personalities Category</label>
|
|
||||||
<select class="bg-gray-200 dark:bg-gray-700 shadow appearance-none border rounded py-2 px-3 leading-tight focus:outline-none focus:shadow-outline" id="personalities_category" name="personalities_category" value="general">
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="mb-4 flex-row">
|
|
||||||
<label class="font-bold mb-2" for="model">Personalities</label>
|
|
||||||
<select class="bg-gray-200 dark:bg-gray-700 shadow appearance-none border rounded py-2 px-3 leading-tight focus:outline-none focus:shadow-outline" id="personalities" name="personalities" value="lollms_chatbot.yaml">
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="mb-4 flex-row">
|
|
||||||
<label class="font-bold mb-2" for="model">Audio in Language</label>
|
|
||||||
<select class="bg-gray-200 dark:bg-gray-700 shadow appearance-none border rounded py-2 px-3 leading-tight focus:outline-none focus:shadow-outline" id="language" name="language" value="english">
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="mb-4 flex-row">
|
|
||||||
<label class="font-bold mb-2" for="model">audio out Voice</label>
|
|
||||||
<select class="bg-gray-200 dark:bg-gray-700 shadow appearance-none border rounded py-2 px-3 leading-tight focus:outline-none focus:shadow-outline" id="voice" name="voice" value="english">
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mb-4 flex-row">
|
|
||||||
<label class="font-bold mb-2" for="seed">Seed</label>
|
|
||||||
<input class="bg-gray-200 dark:bg-gray-700 shadow appearance-none border rounded py-2 px-3 leading-tight focus:outline-none focus:shadow-outline" id="seed" type="text" name="seed" value="0">
|
|
||||||
</div>
|
|
||||||
<div class="mb-4 flex-row">
|
|
||||||
<label class="font-bold mb-2" for="temperature" id="temperature-value">Temperature (0.1)</label>
|
|
||||||
<input class="slider-value" id="temperature" type="range" min="0" max="5" step="0.1" value="0.01" name="temperature">
|
|
||||||
</div>
|
|
||||||
<div class="mb-4 flex-row">
|
|
||||||
<label class="font-bold mb-2" for="n-predict" id="n-predict-value">N Predict (256)</label>
|
|
||||||
<input class="slider-value" id="n-predict" type="range" min="0" max="2048" step="1" value="256" name="n-predict">
|
|
||||||
</div>
|
|
||||||
<div class="mb-4 flex-row">
|
|
||||||
<label class="font-bold mb-2" for="top-k" id="top-k-value">Top K</label>
|
|
||||||
<input class="slider-value" id="top-k" type="range" min="0" max="100" step="1" value="40" name="top-k">
|
|
||||||
</div>
|
|
||||||
<div class="mb-4 flex-row">
|
|
||||||
<label class="font-bold mb-2" for="top-p" id="top-p-value">Top P</label>
|
|
||||||
<input class="slider-value" id="top-p" type="range" min="0" max="1" step="0.01" value="0.95" name="top-p">
|
|
||||||
</div>
|
|
||||||
<div class="mb-4 flex-row">
|
|
||||||
<label class="font-bold mb-2" for="repeat-penalty" id="repeat-penalty-value">Repeat penalty</label>
|
|
||||||
<input class="slider-value" id="repeat-penalty" type="range" min="0" max="2" step="0.01" value="1.3" name="repeat-penalty">
|
|
||||||
</div>
|
|
||||||
<div class="mb-4 flex-row">
|
|
||||||
<label class="font-bold mb-2" for="repeat-last-n" id="repeat-last-n-value">Repeat last N</label>
|
|
||||||
<input class="slider-value" id="repeat-last-n" type="range" min="0" max="100" step="1" value="40" name="repeat-last-n">
|
|
||||||
</div>
|
|
||||||
<div class="mb-4">
|
|
||||||
<button type="submit" id="submit-model-params" class="my-1 mx-1 outline-none px-4 bg-accent rounded-md bg-gray-200 hover:bg-gray-300 py-1 dark:bg-gray-500 dark:hover:bg-gray-300 transition-colors ease-in-out">Update parameters</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
@ -1 +0,0 @@
|
|||||||
This section is under development. Stay tuned.
|
|
@ -35,6 +35,8 @@ def run_git_pull():
|
|||||||
def install_requirements():
|
def install_requirements():
|
||||||
try:
|
try:
|
||||||
subprocess.check_call(["pip", "install", "--upgrade", "-r", "requirements.txt"])
|
subprocess.check_call(["pip", "install", "--upgrade", "-r", "requirements.txt"])
|
||||||
|
subprocess.check_call(["pip", "install", "--upgrade", "-e", "lollms_core"])
|
||||||
|
subprocess.check_call(["pip", "install", "--upgrade", "-r", "utilities/safe_store"])
|
||||||
except subprocess.CalledProcessError as e:
|
except subprocess.CalledProcessError as e:
|
||||||
print(f"Error during pip install: {e}")
|
print(f"Error during pip install: {e}")
|
||||||
|
|
||||||
|
@ -76,4 +76,4 @@ li {
|
|||||||
ol {
|
ol {
|
||||||
list-style-type: decimal;
|
list-style-type: decimal;
|
||||||
margin-left: 20px;
|
margin-left: 20px;
|
||||||
}
|
}
|
||||||
|
@ -1,42 +1,226 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="break-all">
|
<div class="break-all">
|
||||||
<div v-html="renderedMarkdown" class="markdown-content"></div>
|
<div ref="mdRender" class="markdown-content">
|
||||||
|
<div v-for="(item, index) in markdownItems" :key="index">
|
||||||
|
<code-block
|
||||||
|
v-if="item.type === 'code'"
|
||||||
|
:language="item.language"
|
||||||
|
:code="item.code"
|
||||||
|
:discussion_id="discussion_id"
|
||||||
|
:message_id="message_id"
|
||||||
|
></code-block>
|
||||||
|
<div v-else v-html="item.html"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { nextTick } from 'vue';
|
import {nextTick, ref, onMounted, watch } from 'vue';
|
||||||
import feather from 'feather-icons';
|
import feather from 'feather-icons';
|
||||||
import MarkdownIt from 'markdown-it';
|
import MarkdownIt from 'markdown-it';
|
||||||
import emoji from 'markdown-it-emoji';
|
import emoji from 'markdown-it-emoji';
|
||||||
import anchor from 'markdown-it-anchor';
|
import anchor from 'markdown-it-anchor';
|
||||||
import implicitFigures from 'markdown-it-implicit-figures';
|
import implicitFigures from 'markdown-it-implicit-figures';
|
||||||
//import hljs from 'highlight.js/lib/core';
|
|
||||||
import 'highlight.js/styles/tomorrow-night-blue.css';
|
|
||||||
import 'highlight.js/styles/tokyo-night-dark.css';
|
|
||||||
import hljs from 'highlight.js/lib/common';
|
|
||||||
|
|
||||||
|
|
||||||
import 'highlight.js/styles/tomorrow-night-blue.css';
|
import 'highlight.js/styles/tomorrow-night-blue.css';
|
||||||
import 'highlight.js/styles/tokyo-night-dark.css';
|
import 'highlight.js/styles/tokyo-night-dark.css';
|
||||||
import attrs from 'markdown-it-attrs';
|
import attrs from 'markdown-it-attrs';
|
||||||
|
import CodeBlock from './CodeBlock.vue';
|
||||||
function generateUniqueId() {
|
import hljs from 'highlight.js';
|
||||||
const timestamp = Date.now().toString();
|
function escapeHtml(unsafe) {
|
||||||
const randomSuffix = Math.floor(Math.random() * 1000).toString();
|
return unsafe
|
||||||
return timestamp + randomSuffix;
|
.replace(/&/g, "&")
|
||||||
|
.replace(/</g, "<")
|
||||||
|
.replace(/>/g, ">")
|
||||||
|
.replace(/"/g, """)
|
||||||
|
.replace(/'/g, "'");
|
||||||
}
|
}
|
||||||
|
export default {
|
||||||
|
name: 'MarkdownRenderer',
|
||||||
|
props: {
|
||||||
|
markdownText: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
discussion_id: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
message_id: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
CodeBlock,
|
||||||
|
},
|
||||||
|
setup(props) {
|
||||||
|
const md = new MarkdownIt({
|
||||||
|
html: true,
|
||||||
|
highlight: (code, language) => {
|
||||||
|
const validLanguage = language && hljs.getLanguage(language) ? language : 'plaintext';
|
||||||
|
return hljs.highlight(validLanguage, code).value;
|
||||||
|
},
|
||||||
|
renderInline: true,
|
||||||
|
breaks: true,
|
||||||
|
})
|
||||||
|
.use(emoji)
|
||||||
|
.use(anchor)
|
||||||
|
.use(implicitFigures, {
|
||||||
|
figcaption: true,
|
||||||
|
})
|
||||||
|
.use(attrs);
|
||||||
|
const markdownItems = ref([]);
|
||||||
|
const updateMarkdown = () => {
|
||||||
|
if (props.markdownText) {
|
||||||
|
let tokens = md.parse(props.markdownText, {});
|
||||||
|
markdownItems.value = tokens.map(token => {
|
||||||
|
if (token.type === 'fence') {
|
||||||
|
return {
|
||||||
|
type: 'code',
|
||||||
|
language: escapeHtml(token.info),
|
||||||
|
code: token.content,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
type: 'html',
|
||||||
|
html: md.renderer.render([token], md.options, {}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
markdownItems.value = [];
|
||||||
|
}
|
||||||
|
nextTick(() => {
|
||||||
|
feather.replace();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
watch(() => props.markdownText, updateMarkdown);
|
||||||
|
onMounted(updateMarkdown);
|
||||||
|
return { markdownItems };
|
||||||
|
},
|
||||||
|
};
|
||||||
|
/*
|
||||||
|
const script = document.createElement('script');
|
||||||
|
script.textContent = `
|
||||||
|
|
||||||
|
// Your inline script code here
|
||||||
|
function copyContentToClipboard(id) {
|
||||||
|
console.log("copied");
|
||||||
|
const codeElement = document.getElementById('code_' + id);
|
||||||
|
const copybtnElement = document.getElementById('copy-btn_' + id);
|
||||||
|
const copyedbtnElement = document.getElementById('copyed-btn_' + id);
|
||||||
|
copybtnElement.classList.add('hidden');
|
||||||
|
copyedbtnElement.classList.remove('hidden');
|
||||||
|
const range = document.createRange();
|
||||||
|
range.selectNode(codeElement);
|
||||||
|
window.getSelection().removeAllRanges();
|
||||||
|
window.getSelection().addRange(range);
|
||||||
|
document.execCommand('copy');
|
||||||
|
window.getSelection().removeAllRanges();
|
||||||
|
}
|
||||||
|
function executeCode(id, discussion_id, message_id, lang) {
|
||||||
|
const codeElement = document.getElementById('code_' + id);
|
||||||
|
const codeExecElement = document.getElementById('code_exec_' + id);
|
||||||
|
const preExecElement = document.getElementById('pre_exec_' + id);
|
||||||
|
|
||||||
|
const code = codeElement.innerText
|
||||||
|
const json = JSON.stringify({ 'code': code, 'discussion_id': discussion_id, 'message_id':message_id, 'language': lang})
|
||||||
|
console.log(json)
|
||||||
|
fetch('http://localhost:9600/execute_code', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: json
|
||||||
|
}).then(response=>{
|
||||||
|
// Parse the JSON data from the response body
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then(jsonData => {
|
||||||
|
// Now you can work with the JSON data
|
||||||
|
console.log(jsonData);
|
||||||
|
preExecElement.classList.remove('hidden');
|
||||||
|
codeExecElement.innerHTML = jsonData.output
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
// Handle any errors that occurred during the fetch process
|
||||||
|
console.error('Fetch error:', error);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
function openInVsCode(id, discussion_id, message_id, lang) {
|
||||||
|
const codeElement = document.getElementById('code_' + id);
|
||||||
|
const codeExecElement = document.getElementById('code_exec_' + id);
|
||||||
|
const preExecElement = document.getElementById('pre_exec_' + id);
|
||||||
|
|
||||||
|
const code = codeElement.innerText
|
||||||
|
const json = JSON.stringify({ 'code': code, 'discussion_id': discussion_id, 'message_id':message_id, 'language': lang})
|
||||||
|
console.log(json)
|
||||||
|
fetch('http://localhost:9600/open_in_vs_code', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: json
|
||||||
|
}).then(response=>{
|
||||||
|
// Parse the JSON data from the response body
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then(jsonData => {
|
||||||
|
// Now you can work with the JSON data
|
||||||
|
console.log(jsonData);
|
||||||
|
preExecElement.classList.remove('hidden');
|
||||||
|
codeExecElement.innerHTML = jsonData.output
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
// Handle any errors that occurred during the fetch process
|
||||||
|
console.error('Fetch error:', error);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
function openFolder(id, discussion_id, message_id, lang) {
|
||||||
|
const codeElement = document.getElementById('code_' + id);
|
||||||
|
const codeExecElement = document.getElementById('code_exec_' + id);
|
||||||
|
const preExecElement = document.getElementById('pre_exec_' + id);
|
||||||
|
|
||||||
|
const code = codeElement.innerText
|
||||||
|
const json = JSON.stringify({ 'code': code, 'discussion_id': discussion_id, 'message_id':message_id, 'language': lang})
|
||||||
|
console.log(json)
|
||||||
|
fetch('http://localhost:9600/open_folder', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: json
|
||||||
|
}).then(response=>{
|
||||||
|
// Parse the JSON data from the response body
|
||||||
|
return response.json();
|
||||||
|
})
|
||||||
|
.then(jsonData => {
|
||||||
|
// Now you can work with the JSON data
|
||||||
|
console.log(jsonData);
|
||||||
|
preExecElement.classList.remove('hidden');
|
||||||
|
codeExecElement.innerHTML = jsonData.output
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
// Handle any errors that occurred during the fetch process
|
||||||
|
console.error('Fetch error:', error);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
`;
|
||||||
|
script.async = true; // Set to true if the script should be loaded asynchronously
|
||||||
|
document.body.appendChild(script);
|
||||||
|
|
||||||
|
|
||||||
|
markdownIt.renderer.rules.link_open = (tokens, idx, options, env, self) => {
|
||||||
|
const token = tokens[idx];
|
||||||
|
const hrefIndex = token.attrIndex('href');
|
||||||
|
if (hrefIndex >= 0) {
|
||||||
|
const hrefValue = token.attrs[hrefIndex][1];
|
||||||
|
token.attrs[hrefIndex][1] = hrefValue;
|
||||||
|
token.attrPush(['style', 'color: blue; font-weight: bold; text-decoration: underline;']);
|
||||||
|
}
|
||||||
|
return self.renderToken(tokens, idx, options);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
const markdownIt = new MarkdownIt('commonmark', {
|
|
||||||
html: true,
|
|
||||||
xhtmlOut: true,
|
|
||||||
breaks: true,
|
|
||||||
linkify: true,
|
|
||||||
typographer: true,
|
|
||||||
highlight: (str, lang) => {
|
|
||||||
let id = generateUniqueId();
|
|
||||||
let discussion_id = 0
|
|
||||||
let message_id = 0
|
|
||||||
|
|
||||||
let btn_exec_txt = (lang=='python' || lang=='bash' || lang=='shell' || lang=='cmd' || lang=='powershell') ?'<button class="px-2 py-1 ml-10 mb-2 text-left p-2 text-sm font-medium bg-bg-dark-tone-panel dark:bg-bg-dark-tone rounded-lg hover:bg-primary dark:hover:bg-primary text-white text-xs transition-colors duration-200">' +
|
let btn_exec_txt = (lang=='python' || lang=='bash' || lang=='shell' || lang=='cmd' || lang=='powershell') ?'<button class="px-2 py-1 ml-10 mb-2 text-left p-2 text-sm font-medium bg-bg-dark-tone-panel dark:bg-bg-dark-tone rounded-lg hover:bg-primary dark:hover:bg-primary text-white text-xs transition-colors duration-200">' +
|
||||||
'<span class="mr-1" id="exec-btn_' +
|
'<span class="mr-1" id="exec-btn_' +
|
||||||
@ -145,171 +329,11 @@ const markdownIt = new MarkdownIt('commonmark', {
|
|||||||
'</code>' +
|
'</code>' +
|
||||||
'</pre>' +
|
'</pre>' +
|
||||||
'</div>';
|
'</div>';
|
||||||
return codeString;
|
|
||||||
},
|
|
||||||
bulletListMarker: '-',
|
|
||||||
}).use(attrs).use(anchor).use(implicitFigures).use(emoji); // Add attrs plugin for adding attributes to elements
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
// ... register other languages
|
|
||||||
|
|
||||||
|
|
||||||
hljs.configure({ languages: [] }); // Reset languages
|
|
||||||
hljs.configure({ languages: ['bash'] }); // Set bash as the default language
|
|
||||||
|
|
||||||
markdownIt.renderer.rules.link_open = (tokens, idx, options, env, self) => {
|
|
||||||
const token = tokens[idx];
|
|
||||||
const hrefIndex = token.attrIndex('href');
|
|
||||||
if (hrefIndex >= 0) {
|
|
||||||
const hrefValue = token.attrs[hrefIndex][1];
|
|
||||||
token.attrs[hrefIndex][1] = hrefValue;
|
|
||||||
token.attrPush(['style', 'color: blue; font-weight: bold; text-decoration: underline;']);
|
|
||||||
}
|
|
||||||
return self.renderToken(tokens, idx, options);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'MarkdownRenderer',
|
|
||||||
props: {
|
|
||||||
markdownText: {
|
|
||||||
type: String,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
renderedMarkdown: '',
|
|
||||||
isCopied: false,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
mounted() {
|
|
||||||
const script = document.createElement('script');
|
|
||||||
script.textContent = `
|
|
||||||
|
|
||||||
// Your inline script code here
|
|
||||||
function copyContentToClipboard(id) {
|
|
||||||
console.log("copied");
|
|
||||||
const codeElement = document.getElementById('code_' + id);
|
|
||||||
const copybtnElement = document.getElementById('copy-btn_' + id);
|
|
||||||
const copyedbtnElement = document.getElementById('copyed-btn_' + id);
|
|
||||||
copybtnElement.classList.add('hidden');
|
|
||||||
copyedbtnElement.classList.remove('hidden');
|
|
||||||
const range = document.createRange();
|
|
||||||
range.selectNode(codeElement);
|
|
||||||
window.getSelection().removeAllRanges();
|
|
||||||
window.getSelection().addRange(range);
|
|
||||||
document.execCommand('copy');
|
|
||||||
window.getSelection().removeAllRanges();
|
|
||||||
}
|
|
||||||
function executeCode(id, discussion_id, message_id, lang) {
|
|
||||||
const codeElement = document.getElementById('code_' + id);
|
|
||||||
const codeExecElement = document.getElementById('code_exec_' + id);
|
|
||||||
const preExecElement = document.getElementById('pre_exec_' + id);
|
|
||||||
|
|
||||||
const code = codeElement.innerText
|
|
||||||
const json = JSON.stringify({ 'code': code, 'discussion_id': discussion_id, 'message_id':message_id, 'language': lang})
|
|
||||||
console.log(json)
|
|
||||||
fetch('http://localhost:9600/execute_code', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
body: json
|
|
||||||
}).then(response=>{
|
|
||||||
// Parse the JSON data from the response body
|
|
||||||
return response.json();
|
|
||||||
})
|
|
||||||
.then(jsonData => {
|
|
||||||
// Now you can work with the JSON data
|
|
||||||
console.log(jsonData);
|
|
||||||
preExecElement.classList.remove('hidden');
|
|
||||||
codeExecElement.innerHTML = jsonData.output
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
// Handle any errors that occurred during the fetch process
|
|
||||||
console.error('Fetch error:', error);
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
function openInVsCode(id, discussion_id, message_id, lang) {
|
|
||||||
const codeElement = document.getElementById('code_' + id);
|
|
||||||
const codeExecElement = document.getElementById('code_exec_' + id);
|
|
||||||
const preExecElement = document.getElementById('pre_exec_' + id);
|
|
||||||
|
|
||||||
const code = codeElement.innerText
|
|
||||||
const json = JSON.stringify({ 'code': code, 'discussion_id': discussion_id, 'message_id':message_id, 'language': lang})
|
|
||||||
console.log(json)
|
|
||||||
fetch('http://localhost:9600/open_in_vs_code', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
body: json
|
|
||||||
}).then(response=>{
|
|
||||||
// Parse the JSON data from the response body
|
|
||||||
return response.json();
|
|
||||||
})
|
|
||||||
.then(jsonData => {
|
|
||||||
// Now you can work with the JSON data
|
|
||||||
console.log(jsonData);
|
|
||||||
preExecElement.classList.remove('hidden');
|
|
||||||
codeExecElement.innerHTML = jsonData.output
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
// Handle any errors that occurred during the fetch process
|
|
||||||
console.error('Fetch error:', error);
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
function openFolder(id, discussion_id, message_id, lang) {
|
|
||||||
const codeElement = document.getElementById('code_' + id);
|
|
||||||
const codeExecElement = document.getElementById('code_exec_' + id);
|
|
||||||
const preExecElement = document.getElementById('pre_exec_' + id);
|
|
||||||
|
|
||||||
const code = codeElement.innerText
|
|
||||||
const json = JSON.stringify({ 'code': code, 'discussion_id': discussion_id, 'message_id':message_id, 'language': lang})
|
|
||||||
console.log(json)
|
|
||||||
fetch('http://localhost:9600/open_folder', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
body: json
|
|
||||||
}).then(response=>{
|
|
||||||
// Parse the JSON data from the response body
|
|
||||||
return response.json();
|
|
||||||
})
|
|
||||||
.then(jsonData => {
|
|
||||||
// Now you can work with the JSON data
|
|
||||||
console.log(jsonData);
|
|
||||||
preExecElement.classList.remove('hidden');
|
|
||||||
codeExecElement.innerHTML = jsonData.output
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
// Handle any errors that occurred during the fetch process
|
|
||||||
console.error('Fetch error:', error);
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
`;
|
|
||||||
script.async = true; // Set to true if the script should be loaded asynchronously
|
|
||||||
document.body.appendChild(script);
|
|
||||||
if(this.markdownText){
|
|
||||||
this.renderedMarkdown = markdownIt.render(this.markdownText);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
this.renderedMarkdown = "";
|
|
||||||
}
|
|
||||||
nextTick(() => {
|
|
||||||
feather.replace();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
methods: {},
|
|
||||||
watch: {
|
|
||||||
markdownText(newText) {
|
|
||||||
this.renderedMarkdown = markdownIt.render(newText);
|
|
||||||
nextTick(() => {
|
|
||||||
feather.replace();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
<style>
|
||||||
|
/* Your existing styles */
|
||||||
|
</style>
|
||||||
|
|
||||||
|
122
webui.sh
@ -1,122 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
echo "\u001b[34m"
|
|
||||||
echo " ___ ___ ___ ___ ___ ___ "
|
|
||||||
echo " /\__\ /\ \ /\__\ /\__\ /\__\ /\ \ "
|
|
||||||
echo " /:/ / /::\ \ /:/ / /:/ / /::| | /::\ \ "
|
|
||||||
echo " /:/ / /:/\:\ \ /:/ / /:/ / /:|:| | /:/\ \ \ "
|
|
||||||
echo " /:/ / /:/ \:\ \ /:/ / /:/ / /:/|:|__|__ _\:\~\ \ \ "
|
|
||||||
echo " /:/__/ /:/__/ \:\__\ /:/__/ /:/__/ /:/ |::::\__\ /\ \:\ \ \__\ "
|
|
||||||
echo " \:\ \ \:\ \ /:/ / \:\ \ \:\ \ \/__/~~/:/ / \:\ \:\ \/__/ "
|
|
||||||
echo " \:\ \ \:\ /:/ / \:\ \ \:\ \ /:/ / \:\ \:\__\ "
|
|
||||||
echo " \:\ \ \:\/:/ / \:\ \ \:\ \ /:/ / \:\/:/ / "
|
|
||||||
echo " \:\__\ \::/ / \:\__\ \:\__\ /:/ / \::/ / "
|
|
||||||
echo " \/__/ \/__/ \/__/ \/__/ \/__/ \/__/ "
|
|
||||||
echo " By ParisNeo"
|
|
||||||
echo "\u001b[0m"
|
|
||||||
|
|
||||||
if ping -q -c 1 google.com >/dev/null 2>&1; then
|
|
||||||
echo -e "\e[32mInternet Connection working fine\e[0m"
|
|
||||||
# Install git
|
|
||||||
echo -n "Checking for Git..."
|
|
||||||
if command -v git > /dev/null 2>&1; then
|
|
||||||
echo "is installed"
|
|
||||||
else
|
|
||||||
read -p "Git is not installed. Would you like to install Git? [Y/N] " choice
|
|
||||||
if [ "$choice" = "Y" ] || [ "$choice" = "y" ]; then
|
|
||||||
echo "Installing Git..."
|
|
||||||
sudo apt update
|
|
||||||
sudo apt install -y git
|
|
||||||
else
|
|
||||||
echo "Please install Git and try again."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check if repository exists
|
|
||||||
if [[ -d .git ]] ;then
|
|
||||||
echo Pulling latest changes
|
|
||||||
git pull
|
|
||||||
else
|
|
||||||
if [[ -d lollms-webui ]] ;then
|
|
||||||
cd lollms-webui
|
|
||||||
else
|
|
||||||
echo Cloning repository...
|
|
||||||
rem Clone the Git repository into a temporary directory
|
|
||||||
git clone https://github.com/ParisNeo/lollms-webui.git ./lollms-webui
|
|
||||||
cd lollms-webui
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
echo Pulling latest version...
|
|
||||||
git pull
|
|
||||||
|
|
||||||
# Install Python 3.10 and pip
|
|
||||||
echo -n "Checking for python3..."
|
|
||||||
if command -v python3 > /dev/null 2>&1; then
|
|
||||||
echo "is installed"
|
|
||||||
else
|
|
||||||
read -p "python3 is not installed. Would you like to install python3? [Y/N] " choice
|
|
||||||
if [ "$choice" = "Y" ] || [ "$choice" = "y" ]; then
|
|
||||||
echo "Installing python3..."
|
|
||||||
sudo apt update
|
|
||||||
sudo apt install -y python3 python3-venv
|
|
||||||
else
|
|
||||||
echo "Please install python3 and try again."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Install venv module
|
|
||||||
echo -n "Checking for venv module..."
|
|
||||||
if python3 -m venv env > /dev/null 2>&1; then
|
|
||||||
echo "is installed"
|
|
||||||
else
|
|
||||||
read -p "venv module is not available. Would you like to install it? [Y/N] " choice
|
|
||||||
if [ "$choice" = "Y" ] || [ "$choice" = "y" ]; then
|
|
||||||
echo "Installing venv module..."
|
|
||||||
sudo apt update
|
|
||||||
sudo apt install -y python3-venv
|
|
||||||
else
|
|
||||||
echo "Please install venv module and try again."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Create a new virtual environment
|
|
||||||
echo -n "Creating virtual environment..."
|
|
||||||
python3 -m venv env
|
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
echo "Failed to create virtual environment. Please check your Python installation and try again."
|
|
||||||
exit 1
|
|
||||||
else
|
|
||||||
echo "is created"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
# Activate the virtual environment
|
|
||||||
echo -n "Activating virtual environment..."
|
|
||||||
source env/bin/activate
|
|
||||||
echo "is active"
|
|
||||||
|
|
||||||
# Install the required packages
|
|
||||||
echo "Installing requirements..."
|
|
||||||
python3 -m pip install pip --upgrade
|
|
||||||
python3 -m pip install --upgrade -r requirements.txt
|
|
||||||
|
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
echo "Failed to install required packages. Please check your internet connection and try again."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Cleanup
|
|
||||||
|
|
||||||
if [ -d "./tmp" ]; then
|
|
||||||
rm -rf "./tmp"
|
|
||||||
echo "Cleaning tmp folder"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Launch the Python application
|
|
||||||
python app.py "$@"
|
|
@ -1 +1 @@
|
|||||||
Subproject commit ecec471d269ff305b7fb1700d506ce8a63ba53cd
|
Subproject commit 7d397574d4de60b37beff4474184664ae7ce40ec
|