mirror of
https://github.com/ParisNeo/lollms-webui.git
synced 2024-12-18 20:17:50 +00:00
upgraded ui + file vectorization
This commit is contained in:
parent
c81a2b4ba7
commit
c93b7c12e2
@ -459,8 +459,7 @@ class LoLLMsAPPI(LollmsApplication):
|
||||
jsons,
|
||||
room=client_id
|
||||
)
|
||||
|
||||
|
||||
|
||||
@socketio.on('upload_file')
|
||||
def upload_file(data):
|
||||
file = data['file']
|
||||
@ -493,6 +492,16 @@ class LoLLMsAPPI(LollmsApplication):
|
||||
ASCIIColors.error(f'Client {request.sid} canceled generation')
|
||||
self.cancel_gen = False
|
||||
self.busy=False
|
||||
@socketio.on('get_personality_files')
|
||||
def get_personality_files(data):
|
||||
client_id = request.sid
|
||||
self.connections[client_id]["generated_text"] = ""
|
||||
self.connections[client_id]["cancel_generation"] = False
|
||||
|
||||
try:
|
||||
self.personality.setCallback(partial(self.process_chunk,client_id = client_id))
|
||||
except Exception as ex:
|
||||
trace_exception(ex)
|
||||
|
||||
@socketio.on('send_file')
|
||||
def send_file(data):
|
||||
@ -509,23 +518,36 @@ class LoLLMsAPPI(LollmsApplication):
|
||||
file_path = path / data["filename"]
|
||||
File64BitsManager.b642file(data["fileData"],file_path)
|
||||
if self.personality.processor:
|
||||
self.personality.processor.add_file(file_path, partial(self.process_chunk, client_id=client_id))
|
||||
result = self.personality.processor.add_file(file_path, partial(self.process_chunk, client_id=client_id))
|
||||
else:
|
||||
self.personality.add_file(file_path, partial(self.process_chunk, client_id=client_id))
|
||||
self.socketio.emit('file_received',
|
||||
{
|
||||
"status":True,
|
||||
}, room=client_id
|
||||
)
|
||||
result = self.personality.add_file(file_path, partial(self.process_chunk, client_id=client_id))
|
||||
if result:
|
||||
self.socketio.emit('file_received',
|
||||
{
|
||||
"status":True,
|
||||
"filename":data["filename"],
|
||||
}, room=client_id
|
||||
)
|
||||
else:
|
||||
self.socketio.emit('file_received',
|
||||
{
|
||||
"status":False,
|
||||
"filename":data["filename"],
|
||||
"error":"Couldn't receive file: Verify that file type is compatible with the personality"
|
||||
}, room=client_id
|
||||
)
|
||||
|
||||
except Exception as ex:
|
||||
ASCIIColors.error(ex)
|
||||
trace_exception(ex)
|
||||
self.socketio.emit('file_received',
|
||||
{
|
||||
"status":False,
|
||||
"filename":data["filename"],
|
||||
"error":"Couldn't receive file: "+str(ex)
|
||||
}, room=client_id
|
||||
)
|
||||
)
|
||||
self.close_message(client_id)
|
||||
|
||||
|
||||
@self.socketio.on('cancel_text_generation')
|
||||
@ -978,11 +1000,14 @@ class LoLLMsAPPI(LollmsApplication):
|
||||
|
||||
|
||||
if len(self.personality.files)>0 and self.personality.vectorizer:
|
||||
pr = PromptReshaper("!@>Document chunks:\n{{doc}}\n{{conditionning}}\n{{content}}")
|
||||
pr = PromptReshaper("!@>document chunks:\n{{doc}}\n{{conditionning}}\n{{content}}")
|
||||
emb = self.personality.vectorizer.embed_query(message.content)
|
||||
docs, sorted_similarities = self.personality.vectorizer.recover_text(emb, top_k=self.config.data_vectorization_nb_chunks)
|
||||
str_docs = ""
|
||||
for doc, infos in zip(docs, sorted_similarities):
|
||||
str_docs+=f"document chunk:\nchunk path: {infos[0]}\nchunk content:{doc}"
|
||||
discussion_messages = pr.build({
|
||||
"doc":"\n".join(docs),
|
||||
"doc":str_docs,
|
||||
"conditionning":self.personality.personality_conditioning,
|
||||
"content":discussion_messages
|
||||
}, self.model.tokenize, self.model.detokenize, self.config.ctx_size, place_holders_to_sacrifice=["content"])
|
||||
|
82
app.py
82
app.py
@ -275,6 +275,10 @@ class LoLLMsWebUI(LoLLMsAPPI):
|
||||
self.add_endpoint(
|
||||
"/list_models", "list_models", self.list_models, methods=["GET"]
|
||||
)
|
||||
self.add_endpoint(
|
||||
"/get_active_model", "get_active_model", self.get_active_model, methods=["GET"]
|
||||
)
|
||||
|
||||
self.add_endpoint(
|
||||
"/list_personalities_categories", "list_personalities_categories", self.list_personalities_categories, methods=["GET"]
|
||||
)
|
||||
@ -408,9 +412,13 @@ class LoLLMsWebUI(LoLLMsAPPI):
|
||||
)
|
||||
|
||||
self.add_endpoint(
|
||||
"/presets.json", "presets.json", self.get_presets, methods=["GET"]
|
||||
"/get_presets", "get_presets", self.get_presets, methods=["GET"]
|
||||
)
|
||||
|
||||
self.add_endpoint(
|
||||
"/add_preset", "add_preset", self.add_preset, methods=["POST"]
|
||||
)
|
||||
|
||||
self.add_endpoint(
|
||||
"/save_presets", "save_presets", self.save_presets, methods=["POST"]
|
||||
)
|
||||
@ -471,14 +479,55 @@ class LoLLMsWebUI(LoLLMsAPPI):
|
||||
return json.dumps(output_json)
|
||||
return spawn_process(code)
|
||||
|
||||
|
||||
def copy_files(self, src, dest):
|
||||
for item in os.listdir(src):
|
||||
src_file = os.path.join(src, item)
|
||||
dest_file = os.path.join(dest, item)
|
||||
|
||||
if os.path.isfile(src_file):
|
||||
shutil.copy2(src_file, dest_file)
|
||||
|
||||
def get_presets(self):
|
||||
presets_file = self.lollms_paths.personal_databases_path/"presets.json"
|
||||
if not presets_file.exists():
|
||||
shutil.copy("presets/presets.json",presets_file)
|
||||
with open(presets_file) as f:
|
||||
data = json.loads(f.read())
|
||||
return jsonify(data)
|
||||
presets_folder = self.lollms_paths.personal_databases_path/"lollms_playground_presets"
|
||||
if not presets_folder.exists():
|
||||
presets_folder.mkdir(exist_ok=True, parents=True)
|
||||
self.copy_files("presets",presets_folder)
|
||||
presets = []
|
||||
for filename in presets_folder.glob('*.yaml'):
|
||||
print(filename)
|
||||
with open(filename, 'r') as file:
|
||||
preset = yaml.safe_load(file)
|
||||
if preset is not None:
|
||||
presets.append(preset)
|
||||
return jsonify(presets)
|
||||
|
||||
def add_preset(self):
|
||||
# Get the JSON data from the POST request.
|
||||
preset_data = request.get_json()
|
||||
presets_folder = self.lollms_paths.personal_databases_path/"lollms_playground_presets"
|
||||
if not presets_folder.exists():
|
||||
presets_folder.mkdir(exist_ok=True, parents=True)
|
||||
self.copy_files("presets",presets_folder)
|
||||
fn = preset_data.name.lower().replace(" ","_")
|
||||
filename = presets_folder/f"{fn}.yaml"
|
||||
with open(filename, 'r') as file:
|
||||
yaml.dump(preset_data)
|
||||
return jsonify({"status": True})
|
||||
|
||||
def del_preset(self):
|
||||
presets_folder = self.lollms_paths.personal_databases_path/"lollms_playground_presets"
|
||||
if not presets_folder.exists():
|
||||
presets_folder.mkdir(exist_ok=True, parents=True)
|
||||
self.copy_files("presets",presets_folder)
|
||||
presets = []
|
||||
for filename in presets_folder.glob('*.yaml'):
|
||||
print(filename)
|
||||
with open(filename, 'r') as file:
|
||||
preset = yaml.safe_load(file)
|
||||
if preset is not None:
|
||||
presets.append(preset)
|
||||
return jsonify(presets)
|
||||
|
||||
|
||||
def save_presets(self):
|
||||
"""Saves a preset to a file.
|
||||
@ -498,7 +547,7 @@ class LoLLMsWebUI(LoLLMsAPPI):
|
||||
with open(presets_file, "w") as f:
|
||||
json.dump(preset_data, f, indent=4)
|
||||
|
||||
return "Preset saved successfully!"
|
||||
return jsonify({"status":True,"message":"Preset saved successfully!"})
|
||||
|
||||
def export_multiple_discussions(self):
|
||||
data = request.get_json()
|
||||
@ -696,17 +745,18 @@ class LoLLMsWebUI(LoLLMsAPPI):
|
||||
self.config["model_name"]=data['setting_value']
|
||||
if self.config["model_name"] is not None:
|
||||
try:
|
||||
self.model = None
|
||||
if self.binding:
|
||||
self.binding.destroy_model()
|
||||
del self.binding
|
||||
|
||||
self.binding = None
|
||||
self.model = None
|
||||
for per in self.mounted_personalities:
|
||||
per.model = None
|
||||
gc.collect()
|
||||
self.binding = BindingBuilder().build_binding(self.config, self.lollms_paths)
|
||||
self.model = self.binding.build_model()
|
||||
self.rebuild_personalities(reload_all=True)
|
||||
for per in self.mounted_personalities:
|
||||
per.model = self.model
|
||||
except Exception as ex:
|
||||
# Catch the exception and get the traceback as a list of strings
|
||||
traceback_lines = traceback.format_exception(type(ex), ex, ex.__traceback__)
|
||||
@ -870,6 +920,14 @@ class LoLLMsWebUI(LoLLMsAPPI):
|
||||
else:
|
||||
return jsonify([])
|
||||
|
||||
def get_active_model(self):
|
||||
if self.binding is not None:
|
||||
models = self.binding.list_models(self.config)
|
||||
index = models.index(self.config.model_name)
|
||||
ASCIIColors.yellow("Listing models")
|
||||
return jsonify({"model":models[index],"index":index})
|
||||
else:
|
||||
return jsonify(None)
|
||||
|
||||
def list_personalities_categories(self):
|
||||
personalities_categories_dir = self.lollms_paths.personalities_zoo_path # replace with the actual path to the models folder
|
||||
|
5
presets/alpaca_instruct_mode.yaml
Normal file
5
presets/alpaca_instruct_mode.yaml
Normal file
@ -0,0 +1,5 @@
|
||||
name: Alpaca Instruct mode
|
||||
content: |
|
||||
### Instructions:
|
||||
@<Give instructions to the AI>@
|
||||
### Answer:@<generation_placeholder>@
|
16
presets/build_latex_book.yaml
Normal file
16
presets/build_latex_book.yaml
Normal file
@ -0,0 +1,16 @@
|
||||
name: Build a Latex Book
|
||||
content: |
|
||||
@<Add some context information to give the AI some context about the book or leave blank if you have no specific idea>@
|
||||
```latex
|
||||
\documentclass[12pt]{book}
|
||||
\usepackage{url}
|
||||
\begin{document}
|
||||
\title{@<Title of the book>@}
|
||||
\author{@<Author name>@} % Author
|
||||
\date{\today} % Date
|
||||
\maketitle
|
||||
\tableofcontents
|
||||
\chapter{Introduction}
|
||||
@<generation_placeholder>@
|
||||
\end{document}
|
||||
```
|
6
presets/explain_code.yaml
Normal file
6
presets/explain_code.yaml
Normal file
@ -0,0 +1,6 @@
|
||||
name: Explain code
|
||||
content: |
|
||||
```@<Language:all_programming_language_options>@
|
||||
@<put your code here>@
|
||||
```
|
||||
Here is an explanation of the previous method:@<generation_placeholder>@
|
11
presets/fix_a_code.yaml
Normal file
11
presets/fix_a_code.yaml
Normal file
@ -0,0 +1,11 @@
|
||||
name: Fix a code
|
||||
content: |
|
||||
Code fixer is a code fixing AI that fixes any code in any language.
|
||||
Here is a @<Language:all_programming_language_options>@ code:
|
||||
```@<Language:all_programming_language_options>@
|
||||
@<Input your code>@
|
||||
```
|
||||
Instruction:Check this code and fix any errors if there are any.
|
||||
Code fixer:
|
||||
```@<Language:all_programming_language_options>@
|
||||
@<generation_placeholder>@",
|
5
presets/instruct_mode.yaml
Normal file
5
presets/instruct_mode.yaml
Normal file
@ -0,0 +1,5 @@
|
||||
name: Instruct mode
|
||||
content: |
|
||||
Instructions:
|
||||
@<Give instructions to the AI>@
|
||||
Answer:@<generation_placeholder>@
|
@ -7,7 +7,7 @@
|
||||
"Make a function": "Here is a @<Language:all_programming_language_options>@ function that @<describe the function you want lollms to build>@:\n```@<Language:all_programming_language_options>@\n@<generation_placeholder>@",
|
||||
"Fix a code": "Here is a @<Language:all_programming_language_options>@ code:\n```@<Language:all_programming_language_options>@\n@<Input your code>@\n```\nInstruction:Check this code and fix any errors if there are any.\nAI:@<generation_placeholder>@",
|
||||
"Make programming project": "```@<Language:all_programming_language_options>@\n# project: @<Project name>@ \n# author: @<Author name>@\n# description: @<The description of the code>@\n\n@<generation_placeholder>@\n```\n---------\nExtra information:\nLicence: apache 2.0\nProgram type: Stand alone.\nDocumentation:\nMake README.md with the following table of contents:\n## Description\n## Installation\n## Usage\n## Licence\n## Contribute\n## Ethical guidelines\nInstructions:\nWrite a user side README.md\nStick to the provided code content and do not invent extra information.\nMake sure all sections of the table of contents are present in the file.\n----\nREADME.md:\n```markdown\n@<generation_placeholder>@\n```",
|
||||
"Explain code": "```@<Language:all_programming_language_options>@\n@<put your code here>@\n```\nHere is an explanation of the previous method:",
|
||||
"Translate code file strings": "Instruction: Translate the comments and values of the @<File type:yaml:json:all_programming_language_options>@ file from @<Source language:all_language_options>@ to @<Destination language:all_language_options>@.\nSession 1:\n```yaml language=english\n# This is a comment\nparameter_1: this is parameter 1\nparameter_2: this is parameter 2\nparameter_3: 25\nparameter_4: |\n This is a multi\n line parameter\n```\n```yaml language=french\n# Ceci est un commentaire\nparameter_1: ceci est le param\u00e8tre 1\nparameter_2: ceci est le param\u00e8tre 2\nparameter_3: 25\nparameter_4: |\n Ceci est une multiligne\n ligne de param\u00e8tre\n```\nSession 2:\n```yaml language=english\n@<Put your yaml data here>@\n```\n```yaml language=french",
|
||||
"Explain code": "```@<Language:all_programming_language_options>@\n@<put your code here>@\n```\nHere is an explanation of the previous method:@<generation_placeholder>@",
|
||||
"Translate code file strings": "Instruction: Translate the comments and values of the @<File type:yaml:json:all_programming_language_options>@ file from @<Source language:all_language_options>@ to @<Destination language:all_language_options>@.\nSession 1:\n```yaml language=english\n# This is a comment\nparameter_1: this is parameter 1\nparameter_2: this is parameter 2\nparameter_3: 25\nparameter_4: |\n This is a multi\n line parameter\n```\n```yaml language=french\n# Ceci est un commentaire\nparameter_1: ceci est le param\u00e8tre 1\nparameter_2: ceci est le param\u00e8tre 2\nparameter_3: 25\nparameter_4: |\n Ceci est une multiligne\n ligne de param\u00e8tre\n```\nSession 2:\n```yaml language=@<Source language:all_language_options>@\n@<Put your yaml data here>@\n```\n```yaml language=@<Destination language:all_language_options>@@<generation_placeholder>@",
|
||||
"Translate text": "```@<Source language:all_language_options>@\n@<Text to translate>@\n```\n```@<Destination language:all_language_options>@\n@<generation_placeholder>@\n```\n"
|
||||
}
|
5
presets/qna_with_conditionning.yaml
Normal file
5
presets/qna_with_conditionning.yaml
Normal file
@ -0,0 +1,5 @@
|
||||
name: Q&A with conditionning
|
||||
content: |
|
||||
Assistant is a highly developed AI capable of answering any question about any subject.
|
||||
User:@<What's your question?>@
|
||||
Assistant:@<generation_placeholder>@
|
2
presets/simple_book_writing.yaml
Normal file
2
presets/simple_book_writing.yaml
Normal file
@ -0,0 +1,2 @@
|
||||
name: Simple Book writing
|
||||
content: Once apon a time
|
4
presets/simple_question_nswer.yaml
Normal file
4
presets/simple_question_nswer.yaml
Normal file
@ -0,0 +1,4 @@
|
||||
name: Simple Question Answer
|
||||
content: |
|
||||
User:@<What is your question:Why is the earth blue?>@
|
||||
Assistant:@<generation_placeholder>@
|
8
web/dist/assets/index-3540572d.css
vendored
8
web/dist/assets/index-3540572d.css
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
8
web/dist/assets/index-d072d96d.css
vendored
Normal file
8
web/dist/assets/index-d072d96d.css
vendored
Normal file
File diff suppressed because one or more lines are too long
4
web/dist/index.html
vendored
4
web/dist/index.html
vendored
@ -6,8 +6,8 @@
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>LoLLMS WebUI - Welcome</title>
|
||||
<script type="module" crossorigin src="/assets/index-0d84a618.js"></script>
|
||||
<link rel="stylesheet" href="/assets/index-3540572d.css">
|
||||
<script type="module" crossorigin src="/assets/index-7262b344.js"></script>
|
||||
<link rel="stylesheet" href="/assets/index-d072d96d.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<div v-if="isActive" class="overlay" @click="toggleCard"></div>
|
||||
<div
|
||||
<div v-show="shrink===false"
|
||||
:class="[
|
||||
'bg-white dark:bg-gray-700 border-blue-300 rounded-lg shadow-lg p-6',
|
||||
'bg-white dark:bg-gray-700 border-blue-300 rounded-lg shadow-lg p-2',
|
||||
cardWidthClass,
|
||||
'm-2',
|
||||
{ hovered: !disableHoverAnimation && isHovered, active: isActive }
|
||||
@ -13,7 +13,7 @@
|
||||
:style="{ cursor:!this.disableFocus ? 'pointer' : ''}"
|
||||
>
|
||||
<!-- Title -->
|
||||
<div v-if="title" class="font-bold mb-2">{{ title }}</div>
|
||||
<div v-if="title" @click="shrink=true" class="font-bold mb-2 cursor-pointer">{{ title }}</div>
|
||||
|
||||
<div v-if="isHorizontal" class="flex flex-wrap">
|
||||
<!-- Card Content -->
|
||||
@ -25,11 +25,18 @@
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
<div v-show="shrink===true" @click="shrink=false" class="bg-white dark:bg-gray-700 border-blue-300 rounded-lg shadow-lg p-2 h-10 cursor-pointer">
|
||||
+
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
is_shrunk: {
|
||||
type:Boolean,
|
||||
default:false
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: "",
|
||||
@ -44,7 +51,7 @@ export default {
|
||||
},
|
||||
disableHoverAnimation: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
default: true,
|
||||
},
|
||||
disableFocus: {
|
||||
type: Boolean,
|
||||
@ -53,6 +60,7 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
shrink: this.is_shrunk,
|
||||
isHovered: false,
|
||||
isActive: false,
|
||||
};
|
||||
|
@ -25,13 +25,6 @@
|
||||
|
||||
<i data-feather="list"></i>
|
||||
</button>
|
||||
<button v-if="fileList.length > 0"
|
||||
class="mx-1 w-full text-2xl hover:text-secondary duration-75 flex justify-center hover:bg-bg-light-tone hover:dark:bg-bg-dark-tone rounded-lg "
|
||||
:title="showFileList ? 'Send files' : 'Show file list'" type="button"
|
||||
@click.stop="send_files">
|
||||
|
||||
<i data-feather="send"></i>
|
||||
</button>
|
||||
</div>
|
||||
<!-- FILES -->
|
||||
<div v-if="fileList.length > 0 && showFileList ==true">
|
||||
@ -45,6 +38,18 @@
|
||||
|
||||
<div
|
||||
class="flex flex-row items-center gap-1 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">
|
||||
<div v-if="!isFileSentList[index]" fileList role="status">
|
||||
<svg aria-hidden="true" class="w-6 h-6 animate-spin fill-secondary"
|
||||
viewBox="0 0 100 101" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z"
|
||||
fill="currentFill" />
|
||||
</svg>
|
||||
<span class="sr-only">Loading...</span>
|
||||
</div>
|
||||
<div>
|
||||
<i data-feather="file" class="w-5 h-5"></i>
|
||||
|
||||
@ -96,15 +101,15 @@
|
||||
|
||||
({{ fileList.length }})
|
||||
|
||||
|
||||
</div>
|
||||
<div class="grow">
|
||||
|
||||
</div>
|
||||
<button type="button" title="Clear all"
|
||||
class="flex items-center p-0.5 text-sm rounded-sm hover:text-red-600 active:scale-75"
|
||||
@click="fileList = []">
|
||||
@click="clear_files">
|
||||
<i data-feather="trash" class="w-5 h-5 "></i>
|
||||
|
||||
</button>
|
||||
</div>
|
||||
<div v-if="showPersonalities" class="mx-1">
|
||||
@ -250,6 +255,7 @@ export default {
|
||||
message: "",
|
||||
isLesteningToVoice:false,
|
||||
fileList: [],
|
||||
isFileSentList: [],
|
||||
totalSize: 0,
|
||||
showFileList: true,
|
||||
showPersonalities: false,
|
||||
@ -281,11 +287,14 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
clear_files(){
|
||||
fileList = []
|
||||
isFileSentList = []
|
||||
},
|
||||
send_file(file){
|
||||
const formData = new FormData();
|
||||
formData.append('file', file);
|
||||
console.log("Uploading file")
|
||||
//this.loading=true;
|
||||
// Read the file as a data URL and emit it to the server
|
||||
const reader = new FileReader();
|
||||
reader.onload = () => {
|
||||
@ -294,29 +303,28 @@ export default {
|
||||
fileData: reader.result,
|
||||
};
|
||||
socket.on('file_received',(resp)=>{
|
||||
if(resp.status){
|
||||
this.onShowToastMessage("File uploaded successfully",4,true)
|
||||
}
|
||||
else{
|
||||
this.onShowToastMessage("Couldn't upload file\n"+resp.error,4,false)
|
||||
}
|
||||
//this.loading = false;
|
||||
socket.off('file_received')
|
||||
if(resp.status){
|
||||
console.log(resp.filename)
|
||||
|
||||
let index = this.fileList.findIndex((file) => file.name === resp.filename);
|
||||
if(index>=0){
|
||||
this.isFileSentList[index]=true;
|
||||
console.log(this.isFileSentList)
|
||||
}
|
||||
else{
|
||||
console.log("Not found")
|
||||
}
|
||||
this.onShowToastMessage("File uploaded successfully",4,true);
|
||||
}
|
||||
else{
|
||||
this.onShowToastMessage("Couldn't upload file\n"+resp.error,4,false);
|
||||
}
|
||||
socket.off('file_received')
|
||||
})
|
||||
socket.emit('send_file', data);
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
},
|
||||
// vue.js method. The list of files are in this.fileList
|
||||
// This function will call this.send_file on each file from this.fileList
|
||||
send_files(event){
|
||||
event.preventDefault(); // Add this line to prevent form validation
|
||||
for(let i = 0; i < this.fileList.length; i++){
|
||||
let file = this.fileList[i];
|
||||
this.send_file(file);
|
||||
}
|
||||
this.fileList = [];
|
||||
},
|
||||
startSpeechRecognition() {
|
||||
if ('SpeechRecognition' in window || 'webkitSpeechRecognition' in window) {
|
||||
this.recognition = new (window.SpeechRecognition || window.webkitSpeechRecognition)();
|
||||
@ -420,8 +428,9 @@ export default {
|
||||
this.$emit('stopGenerating')
|
||||
},
|
||||
addFiles(event) {
|
||||
|
||||
this.fileList = this.fileList.concat([...event.target.files])
|
||||
this.isFileSentList = this.isFileSentList.concat([false] * this.fileList.length)
|
||||
this.send_file(this.fileList[this.fileList.length-1])
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
@ -3,22 +3,9 @@
|
||||
<div class="container flex flex-row m-2">
|
||||
<div class="flex-grow m-2">
|
||||
<div class="flex-grow m-2 p-2 border border-blue-300 rounded-md border-2 border-blue-300 m-2 p-4">
|
||||
<label class="mt-2">Presets</label>
|
||||
<select v-model="selectedPreset" class="m-2 border-2 rounded-md shadow-sm w-full">
|
||||
<option v-for="preset in Object.keys(presets)" :key="preset" :value="preset">
|
||||
{{ preset }}
|
||||
</option>
|
||||
</select>
|
||||
<button class="w-6 ml-2 hover:text-secondary duration-75 active:scale-90 cursor-pointer" @click="setPreset" title="Use preset"><i data-feather="check"></i></button>
|
||||
<button class="w-6 ml-2 hover:text-secondary duration-75 active:scale-90 cursor-pointer" @click="addPreset" title="Add this text as a preset"><i data-feather="plus"></i></button>
|
||||
<button class="w-6 ml-2 hover:text-secondary duration-75 active:scale-90 cursor-pointer" @click="removePreset" title="Remove preset"><i data-feather="x"></i></button>
|
||||
<button class="w-6 ml-2 hover:text-secondary duration-75 active:scale-90 cursor-pointer" @click="savePreset" title="Save presets list"><i data-feather="save"></i></button>
|
||||
<button class="w-6 ml-2 hover:text-secondary duration-75 active:scale-90 cursor-pointer" @click="reloadPresets" title="Reload presets list"><i data-feather="refresh-ccw"></i></button>
|
||||
|
||||
</div>
|
||||
<div class="flex-grow m-2 p-2 border border-blue-300 rounded-md border-2 border-blue-300 m-2 p-4">
|
||||
<div class="m-0">
|
||||
<button v-show="!generating" id="generate-button" @click="generate" class="w-6 ml-2 hover:text-secondary duration-75 active:scale-90 cursor-pointer"><i data-feather="pen-tool"></i></button>
|
||||
<button v-show="!generating" id="generate-next-button" @click="generate_in_placeholder" class="w-6 ml-2 hover:text-secondary duration-75 active:scale-90 cursor-pointer"><i data-feather="archive"></i></button>
|
||||
<span class="w-80"></span>
|
||||
<button v-show="generating" id="stop-button" @click="stopGeneration" class="w-6 ml-2 hover:text-secondary duration-75 active:scale-90 cursor-pointer"><i data-feather="x"></i></button>
|
||||
<button
|
||||
type="button"
|
||||
@ -39,61 +26,109 @@
|
||||
<button v-show="!generating" id="import-button" @click="importText" class="w-6 ml-2 hover:text-secondary duration-75 active:scale-90 cursor-pointer"><i data-feather="download"></i></button>
|
||||
|
||||
<input type="file" id="import-input" class="hidden">
|
||||
</div>
|
||||
<textarea v-model="text" id="text_element" class="mt-4 h-64 overflow-y-scroll w-full dark:bg-bg-dark scrollbar-thin scrollbar-track-bg-light-tone scrollbar-thumb-bg-light-tone-panel hover:scrollbar-thumb-primary dark:scrollbar-track-bg-dark-tone dark:scrollbar-thumb-bg-dark-tone-panel dark:hover:scrollbar-thumb-primary active:scrollbar-thumb-secondary" type="text"></textarea>
|
||||
<span>Cursor position {{ cursorPosition }}</span>
|
||||
|
||||
</div>
|
||||
<div class="flex-grow m-2 p-2 border border-blue-300 rounded-md border-2 border-blue-300 m-2 p-4">
|
||||
<MarkdownRenderer ref="mdRender" :markdown-text="text" class="dark:bg-bg-dark">
|
||||
</MarkdownRenderer>
|
||||
</div>
|
||||
</div>
|
||||
<div id="settings" class="border border-blue-300 bg-blue-200 mt-4 w-25 mr-2 h-full mb-10 min-w-500" style="align-items: center; height: fit-content; margin: 10px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); border-radius: 4px;">
|
||||
<div id="title" class="border border-blue-600 bg-blue-300 m-0 flex justify-center items-center box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1) border-radius: 4px;">
|
||||
<h3 class="text-gray-600 mb-4 text-center m-0">Settings</h3>
|
||||
</div>
|
||||
<div class="slider-container ml-2 mr-2">
|
||||
<h3 class="text-gray-600">Temperature</h3>
|
||||
<input type="range" v-model="temperature" min="0" max="5" step="0.1" class="w-full">
|
||||
<span class="slider-value text-gray-500">Current value: {{ temperature }}</span>
|
||||
</div>
|
||||
<div class="slider-container ml-2 mr-2">
|
||||
<h3 class="text-gray-600">Top K</h3>
|
||||
<input type="range" v-model="top_k" min="1" max="100" step="1" class="w-full">
|
||||
<span class="slider-value text-gray-500">Current value: {{ top_k }}</span>
|
||||
</div>
|
||||
<div class="slider-container ml-2 mr-2">
|
||||
<h3 class="text-gray-600">Top P</h3>
|
||||
<input type="range" v-model="top_p" min="0" max="1" step="0.1" class="w-full">
|
||||
<span class="slider-value text-gray-500">Current value: {{ top_p }}</span>
|
||||
</div>
|
||||
<div class="slider-container ml-2 mr-2">
|
||||
<h3 class="text-gray-600">Repeat Penalty</h3>
|
||||
<input type="range" v-model="repeat_penalty" min="0" max="5" step="0.1" class="w-full">
|
||||
<span class="slider-value text-gray-500">Current value: {{ repeat_penalty }}</span>
|
||||
</div>
|
||||
<div class="slider-container ml-2 mr-2">
|
||||
<h3 class="text-gray-600">Repeat Last N</h3>
|
||||
<input type="range" v-model="repeat_last_n" min="0" max="100" step="1" class="w-full">
|
||||
<span class="slider-value text-gray-500">Current value: {{ repeat_last_n }}</span>
|
||||
</div>
|
||||
<div class="slider-container ml-2 mr-2">
|
||||
<h3 class="text-gray-600">Number of tokens to crop the text to</h3>
|
||||
<input type="number" v-model="n_crop" class="w-full">
|
||||
<span class="slider-value text-gray-500">Current value: {{ n_crop }}</span>
|
||||
</div>
|
||||
<div class="slider-container ml-2 mr-2">
|
||||
<h3 class="text-gray-600">Number of tokens to generate</h3>
|
||||
<input type="number" v-model="n_predicts" class="w-full">
|
||||
<span class="slider-value text-gray-500">Current value: {{ n_predicts }}</span>
|
||||
</div>
|
||||
<div class="slider-container ml-2 mr-2">
|
||||
<h3 class="text-gray-600">Seed</h3>
|
||||
<input type="number" v-model="seed" class="w-full">
|
||||
<span class="slider-value text-gray-500">Current value: {{ seed }}</span>
|
||||
<div class="flex-grow m-2 p-2 border border-blue-300 rounded-md border-2 border-blue-300 m-2 p-4">
|
||||
<div class="flex flex-row m-2 p-0">
|
||||
<div class="border-2 text-blue-600 border-blue-300 p-2 rounded shadow-lg hover:border-gray-600 dark:link-item-dark cursor-pointer" @click="tab_id='source'" :class="{'bg-blue-200':tab_id=='source'}">
|
||||
Source
|
||||
</div>
|
||||
<div class="border-2 text-blue-600 border-blue-300 p-2 rounded shadow-lg hover:border-gray-600 dark:link-item-dark cursor-pointer" @click="tab_id='render'" :class="{'bg-blue-200':tab_id=='render'}">
|
||||
Render
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<div v-if="tab_id === 'source'">
|
||||
<textarea v-model="text" id="text_element" class="mt-4 h-64 p-2 rounded shadow-lg overflow-y-scroll w-full dark:bg-bg-dark scrollbar-thin scrollbar-track-bg-light-tone scrollbar-thumb-bg-light-tone-panel hover:scrollbar-thumb-primary dark:scrollbar-track-bg-dark-tone dark:scrollbar-thumb-bg-dark-tone-panel dark:hover:scrollbar-thumb-primary active:scrollbar-thumb-secondary" type="text"></textarea>
|
||||
<span>Cursor position {{ cursorPosition }}</span>
|
||||
</div>
|
||||
<div v-else>
|
||||
<MarkdownRenderer ref="mdRender" :markdown-text="text" class="mt-4 p-2 rounded shadow-lg dark:bg-bg-dark">
|
||||
</MarkdownRenderer>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Card title="settings" class="slider-container ml-0 mr-0" :isHorizontal="false" :disableHoverAnimation="true" :disableFocus="true">
|
||||
<Card title="Model" class="slider-container ml-0 mr-0" :isHorizontal="false" :disableHoverAnimation="true" :disableFocus="true">
|
||||
<select v-model="selectedModel" @change="setModel" class="m-0 border-2 rounded-md shadow-sm w-full">
|
||||
<option v-for="model in models" :key="model" :value="model">
|
||||
{{ model }}
|
||||
</option>
|
||||
</select>
|
||||
<div v-if="selecting_model" title="Selecting model" class="flex flex-row flex-grow justify-end">
|
||||
<!-- SPINNER -->
|
||||
<div role="status">
|
||||
<svg aria-hidden="true" class="w-6 h-6 animate-spin fill-secondary" viewBox="0 0 100 101"
|
||||
fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z"
|
||||
fill="currentColor" />
|
||||
<path
|
||||
d="M93.9676 39.0409C96.393 38.4038 97.8624 35.9116 97.0079 33.5539C95.2932 28.8227 92.871 24.3692 89.8167 20.348C85.8452 15.1192 80.8826 10.7238 75.2124 7.41289C69.5422 4.10194 63.2754 1.94025 56.7698 1.05124C51.7666 0.367541 46.6976 0.446843 41.7345 1.27873C39.2613 1.69328 37.813 4.19778 38.4501 6.62326C39.0873 9.04874 41.5694 10.4717 44.0505 10.1071C47.8511 9.54855 51.7191 9.52689 55.5402 10.0491C60.8642 10.7766 65.9928 12.5457 70.6331 15.2552C75.2735 17.9648 79.3347 21.5619 82.5849 25.841C84.9175 28.9121 86.7997 32.2913 88.1811 35.8758C89.083 38.2158 91.5421 39.6781 93.9676 39.0409Z"
|
||||
fill="currentFill" />
|
||||
</svg>
|
||||
<span class="sr-only">Selecting model...</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</Card>
|
||||
<Card title="Presets" class="slider-container ml-0 mr-0" :isHorizontal="false" :disableHoverAnimation="true" :disableFocus="true">
|
||||
<select v-model="selectedPreset" class="m-0 border-2 rounded-md shadow-sm w-full">
|
||||
<option v-for="preset in presets" :key="preset" :value="preset">
|
||||
{{ preset.name }}
|
||||
</option>
|
||||
</select>
|
||||
<br>
|
||||
<button class="w-6 ml-2 hover:text-secondary duration-75 active:scale-90 cursor-pointer" @click="setPreset" title="Use preset"><i data-feather="check"></i></button>
|
||||
<button class="w-6 ml-2 hover:text-secondary duration-75 active:scale-90 cursor-pointer" @click="addPreset" title="Add this text as a preset"><i data-feather="plus"></i></button>
|
||||
<button class="w-6 ml-2 hover:text-secondary duration-75 active:scale-90 cursor-pointer" @click="removePreset" title="Remove preset"><i data-feather="x"></i></button>
|
||||
<button class="w-6 ml-2 hover:text-secondary duration-75 active:scale-90 cursor-pointer" @click="reloadPresets" title="Reload presets list"><i data-feather="refresh-ccw"></i></button>
|
||||
|
||||
</Card>
|
||||
<Card title="Generation params" class="slider-container ml-0 mr-0" :isHorizontal="false" :disableHoverAnimation="true" :disableFocus="true">
|
||||
|
||||
<div class="slider-container ml-2 mr-2">
|
||||
<h3 class="text-gray-600">Temperature</h3>
|
||||
<input type="range" v-model="temperature" min="0" max="5" step="0.1" class="w-full">
|
||||
<span class="slider-value text-gray-500">Current value: {{ temperature }}</span>
|
||||
</div>
|
||||
<div class="slider-container ml-2 mr-2">
|
||||
<h3 class="text-gray-600">Top K</h3>
|
||||
<input type="range" v-model="top_k" min="1" max="100" step="1" class="w-full">
|
||||
<span class="slider-value text-gray-500">Current value: {{ top_k }}</span>
|
||||
</div>
|
||||
<div class="slider-container ml-2 mr-2">
|
||||
<h3 class="text-gray-600">Top P</h3>
|
||||
<input type="range" v-model="top_p" min="0" max="1" step="0.1" class="w-full">
|
||||
<span class="slider-value text-gray-500">Current value: {{ top_p }}</span>
|
||||
</div>
|
||||
<div class="slider-container ml-2 mr-2">
|
||||
<h3 class="text-gray-600">Repeat Penalty</h3>
|
||||
<input type="range" v-model="repeat_penalty" min="0" max="5" step="0.1" class="w-full">
|
||||
<span class="slider-value text-gray-500">Current value: {{ repeat_penalty }}</span>
|
||||
</div>
|
||||
<div class="slider-container ml-2 mr-2">
|
||||
<h3 class="text-gray-600">Repeat Last N</h3>
|
||||
<input type="range" v-model="repeat_last_n" min="0" max="100" step="1" class="w-full">
|
||||
<span class="slider-value text-gray-500">Current value: {{ repeat_last_n }}</span>
|
||||
</div>
|
||||
<div class="slider-container ml-2 mr-2">
|
||||
<h3 class="text-gray-600">Number of tokens to crop the text to</h3>
|
||||
<input type="number" v-model="n_crop" class="w-full">
|
||||
<span class="slider-value text-gray-500">Current value: {{ n_crop }}</span>
|
||||
</div>
|
||||
<div class="slider-container ml-2 mr-2">
|
||||
<h3 class="text-gray-600">Number of tokens to generate</h3>
|
||||
<input type="number" v-model="n_predicts" class="w-full">
|
||||
<span class="slider-value text-gray-500">Current value: {{ n_predicts }}</span>
|
||||
</div>
|
||||
<div class="slider-container ml-2 mr-2">
|
||||
<h3 class="text-gray-600">Seed</h3>
|
||||
<input type="number" v-model="seed" class="w-full">
|
||||
<span class="slider-value text-gray-500">Current value: {{ seed }}</span>
|
||||
</div>
|
||||
</Card>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
<Toast ref="toast"/>
|
||||
@ -105,7 +140,8 @@ import axios from "axios";
|
||||
import socket from '@/services/websocket.js'
|
||||
import Toast from '../components/Toast.vue'
|
||||
import MarkdownRenderer from '../components/MarkdownRenderer.vue';
|
||||
|
||||
import ClipBoardTextInput from "@/components/ClipBoardTextInput.vue";
|
||||
import Card from "@/components/Card.vue"
|
||||
|
||||
|
||||
async function showInputPanel(name, default_value="", options=[]) {
|
||||
@ -250,22 +286,21 @@ function replaceInText(text, callback) {
|
||||
});
|
||||
}
|
||||
|
||||
// Get input value function
|
||||
function getInputValue() {
|
||||
const inputField = document.getElementById('input-field');
|
||||
return inputField ? inputField.value : '';
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'PlayGroundView',
|
||||
data() {
|
||||
return {
|
||||
selecting_model:false,
|
||||
tab_id:"source",
|
||||
generating:false,
|
||||
isSpeaking:false,
|
||||
voices: [],
|
||||
isLesteningToVoice:false,
|
||||
presets:{},
|
||||
selectedPreset: '',
|
||||
presets:[],
|
||||
selectedPreset: '',
|
||||
models:{},
|
||||
selectedModel: '',
|
||||
cursorPosition:0,
|
||||
text:"",
|
||||
pre_text:"",
|
||||
@ -282,7 +317,9 @@ export default {
|
||||
},
|
||||
components:{
|
||||
Toast,
|
||||
MarkdownRenderer
|
||||
MarkdownRenderer,
|
||||
ClipBoardTextInput,
|
||||
Card
|
||||
},
|
||||
mounted() {
|
||||
const text_element = document.getElementById('text_element');
|
||||
@ -301,18 +338,37 @@ export default {
|
||||
catch{
|
||||
|
||||
}
|
||||
});
|
||||
axios.get('./presets.json').then(response => {
|
||||
});
|
||||
|
||||
axios.get('list_models').then(response => {
|
||||
console.log("List models "+response.data)
|
||||
this.models=response.data
|
||||
axios.get('get_active_model').then(response => {
|
||||
console.log("Active model " + JSON.stringify(response.data))
|
||||
if(response.data!=undefined){
|
||||
this.selectedModel = response.data["model"]
|
||||
}
|
||||
|
||||
}).catch(ex=>{
|
||||
this.$refs.toast.showToast(`Error: ${ex}`,4,false)
|
||||
});
|
||||
|
||||
}).catch(ex=>{
|
||||
this.$refs.toast.showToast(`Error: ${ex}`,4,false)
|
||||
});
|
||||
|
||||
axios.get('./get_presets').then(response => {
|
||||
console.log(response.data)
|
||||
this.presets=response.data
|
||||
this.selectedPreset = this.presets[0]
|
||||
}).catch(ex=>{
|
||||
this.$refs.toast.showToast(`Error: ${ex}`,4,false)
|
||||
});
|
||||
// Event handler for receiving generated text chunks
|
||||
socket.on('text_chunk', data => {
|
||||
this.appendToOutput(data.chunk);
|
||||
const text_element = document.getElementById('text_element');
|
||||
text_element.scrollTo(0, text_element.scrollHeight);
|
||||
// const text_element = document.getElementById('text_element');
|
||||
// text_element.scrollTo(0, text_element.scrollHeight);
|
||||
});
|
||||
|
||||
// Event handler for receiving generated text chunks
|
||||
@ -388,6 +444,19 @@ export default {
|
||||
},
|
||||
},
|
||||
methods:{
|
||||
setModel(){
|
||||
this.selecting_model=true
|
||||
axios.post("/update_setting", {
|
||||
setting_name: "model_name",
|
||||
setting_value: this.selectedModel
|
||||
}).then((response) => {
|
||||
console.log(response);
|
||||
this.$refs.toast.showToast(`Model changed to this.selectedModel`,4,true)
|
||||
}).catch(err=>{
|
||||
this.$refs.toast.showToast(`Error ${err}`,4,true)
|
||||
});
|
||||
|
||||
},
|
||||
onVoicesChanged() {
|
||||
// This event will be triggered when the voices are loaded
|
||||
this.voices = this.speechSynthesis.getVoices();
|
||||
@ -467,6 +536,33 @@ export default {
|
||||
this.pre_text += chunk
|
||||
this.text = this.pre_text + this.post_text
|
||||
},
|
||||
generate_in_placeholder(){
|
||||
console.log("Finding cursor position")
|
||||
// Find next placeholder @<generation_placeholder>@
|
||||
let index = this.text.indexOf("@<generation_placeholder>@")
|
||||
if(index<0){
|
||||
this.$refs.toast.showToast(`No generation placeholder found`,4,false)
|
||||
return
|
||||
}
|
||||
this.text = this.text.substring(0,index) + this.text.substring(index+"@<generation_placeholder>@".length,this.text.length)
|
||||
this.pre_text = this.text.substring(0,index)
|
||||
this.post_text = this.text.substring(index, this.text.length)
|
||||
var prompt = this.text.substring(0, index)
|
||||
console.log(prompt)
|
||||
// Trigger the 'generate_text' event with the prompt
|
||||
socket.emit('generate_text', { prompt: prompt, personality: -1, n_predicts: this.n_predicts , n_crop: this.n_crop,
|
||||
parameters: {
|
||||
temperature: this.temperature,
|
||||
top_k: this.top_k,
|
||||
top_p: this.top_p,
|
||||
repeat_penalty: this.repeat_penalty, // Update with desired repeat penalty value
|
||||
repeat_last_n: this.repeat_last_n, // Update with desired repeat_last_n value
|
||||
seed: parseInt(this.seed)
|
||||
}});
|
||||
|
||||
// Toggle button visibility
|
||||
this.generating=true
|
||||
},
|
||||
generate(){
|
||||
console.log("Finding cursor position")
|
||||
this.pre_text = this.text.substring(0,this.getCursorPosition())
|
||||
@ -518,7 +614,9 @@ export default {
|
||||
inputFile.click();
|
||||
},
|
||||
setPreset() {
|
||||
this.text = replaceInText(this.presets[this.selectedPreset], (text)=>{
|
||||
console.log("Setting preset")
|
||||
console.log(this.selectedPreset)
|
||||
this.text = replaceInText(this.selectedPreset.content, (text)=>{
|
||||
console.log("Done")
|
||||
console.log(text);
|
||||
this.text= text
|
||||
@ -527,23 +625,26 @@ export default {
|
||||
|
||||
addPreset() {
|
||||
let title = prompt('Enter the title of the preset:');
|
||||
this.presets[title] = this.text
|
||||
this.presets[title] = {
|
||||
name:title,
|
||||
content:this.text
|
||||
}
|
||||
axios.post("./add_preset",this.presets[title]).then(response => {
|
||||
console.log(response.data)
|
||||
}).catch(ex=>{
|
||||
this.$refs.toast.showToast(`Error: ${ex}`,4,false)
|
||||
});
|
||||
},
|
||||
removePreset() {
|
||||
if (this.selectedPreset) {
|
||||
delete this.presets[this.selectedPreset];
|
||||
delete this.presets[this.selectedPreset.name];
|
||||
}
|
||||
},
|
||||
savePreset() {
|
||||
axios.post("/save_presets", this.presets).then((response) => {
|
||||
console.log(response);
|
||||
this.$refs.toast.showToast(`Presets saved`,4,true)
|
||||
});
|
||||
},
|
||||
reloadPresets() {
|
||||
axios.get('./presets.json').then(response => {
|
||||
axios.get('./get_presets').then(response => {
|
||||
console.log(response.data)
|
||||
this.presets=response.data
|
||||
this.selectedPreset = this.presets[0]
|
||||
}).catch(ex=>{
|
||||
this.$refs.toast.showToast(`Error: ${ex}`,4,false)
|
||||
});
|
||||
|
@ -80,7 +80,7 @@
|
||||
<div class="flex gap-2 items-center ">
|
||||
<div>
|
||||
|
||||
<div v-if="vramUsage.gpus && vramUsage.gpus.length == 1">
|
||||
<div v-if="vramUsage&&vramUsage.gpus && vramUsage.gpus.length == 1">
|
||||
|
||||
|
||||
<div class="flex gap-2 items-center " v-for="item in vramUsage.gpus">
|
||||
@ -221,7 +221,7 @@
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="vramUsage.gpus && vramUsage.gpus.length >1">
|
||||
<div v-if="vramUsage&& vramUsage.gpus && vramUsage.gpus.length >1">
|
||||
<div class="flex gap-2 items-center ">
|
||||
|
||||
<!-- GPU IMAGE -->
|
||||
@ -530,8 +530,8 @@
|
||||
</button>
|
||||
</div>
|
||||
<div :class="{ 'hidden': minconf_collapsed }" class="flex flex-col mb-2 px-3 pb-0">
|
||||
<div class="flex flex-col mb-2 px-3 pb-2">
|
||||
<div class="pb-2">
|
||||
<div class="flex flex-row mb-2 px-3 pb-2">
|
||||
<div class="pb-2 m-2 expand-to-fit">
|
||||
<table class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
|
||||
<th>Generic</th>
|
||||
<tr>
|
||||
@ -602,7 +602,7 @@
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="pb-2">
|
||||
<div class="pb-2 m-2">
|
||||
<table class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
|
||||
<th>User</th>
|
||||
<tr>
|
||||
@ -672,7 +672,7 @@
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div class="pb-2">
|
||||
<div class="pb-2 m-2">
|
||||
<table class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
|
||||
<th>Audio</th>
|
||||
<tr>
|
||||
@ -782,26 +782,22 @@
|
||||
|
||||
|
||||
<!-- Row 0 -->
|
||||
<div class="w-full">
|
||||
<div class="flex flex-row">
|
||||
<button
|
||||
class="hover:text-secondary dark:bg-gray-600 w-full bg-red-100 m-2 p-2 duration-75 flex justify-center w-full hover:bg-bg-light-tone hover:dark:bg-bg-dark-tone rounded-lg"
|
||||
class="text-2xl hover:text-secondary duration-75 active:scale-90"
|
||||
@click="api_get_req('clear_uploads').then((res)=>{if(res.status){this.$refs.toast.showToast('Success!', 4, true)}else{this.$refs.toast.showToast(['failed!'], 4, false)}})"
|
||||
>
|
||||
Clear uploads
|
||||
<i data-feather="trash-2">Clear uploads</i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="w-full">
|
||||
<button
|
||||
class="hover:text-secondary dark:bg-gray-600 w-full bg-red-100 m-2 p-2 duration-75 flex justify-center w-full hover:bg-bg-light-tone hover:dark:bg-bg-dark-tone rounded-lg"
|
||||
title="Restart program"
|
||||
class="text-2xl hover:text-secondary duration-75 active:scale-90"
|
||||
@click="api_get_req('restart_program').then((res)=>{if(res.status){this.$refs.toast.showToast('Success!', 4, true)}else{this.$refs.toast.showToast(['failed!'], 4, false)}})"
|
||||
>
|
||||
Restart program
|
||||
<i data-feather="arrow-down-circle">Res tart program</i>
|
||||
</button>
|
||||
</div>
|
||||
<!-- Row 0 -->
|
||||
<div class="w-full">
|
||||
<button
|
||||
class="hover:text-secondary dark:bg-gray-600 w-full bg-red-100 m-2 p-2 duration-75 flex justify-center w-full hover:bg-bg-light-tone hover:dark:bg-bg-dark-tone rounded-lg"
|
||||
class="text-2xl hover:text-secondary duration-75 active:scale-90"
|
||||
@click="api_get_req('update_software').then((res)=>{if(res.status){this.$refs.toast.showToast('Success!', 4, true)}else{this.$refs.toast.showToast('Success!', 4, true)}})"
|
||||
>
|
||||
Upgrade program
|
||||
@ -853,7 +849,7 @@
|
||||
</div>
|
||||
<div :class="{ 'hidden': bzc_collapsed }" class="flex flex-col mb-2 px-3 pb-0">
|
||||
|
||||
<div v-if="bindingsArr.length > 0" class="mb-2">
|
||||
<div v-if="bindingsArr&&bindingsArr.length > 0" class="mb-2">
|
||||
<label for="binding" class="block ml-2 mb-2 text-sm font-medium text-gray-900 dark:text-white">
|
||||
Bindings: ({{ bindingsArr.length }})
|
||||
</label>
|
||||
|
Loading…
Reference in New Issue
Block a user