mirror of
https://github.com/ParisNeo/lollms-webui.git
synced 2024-12-18 20:17:50 +00:00
new version
This commit is contained in:
parent
74e76e0183
commit
0d3de00af7
@ -155,7 +155,7 @@ data_vectorization_method: "tfidf_vectorizer" #"model_embedding" or "tfidf_vecto
|
||||
data_visualization_method: "PCA" #"PCA" or "TSNE"
|
||||
data_vectorization_sentense_transformer_model: "all-MiniLM-L6-v2" # you can use another model by setting its name here or its path
|
||||
|
||||
data_vectorization_save_db: false # For each new session, new files
|
||||
data_vectorization_save_db: true # For each new session, new files
|
||||
data_vectorization_chunk_size: 512 # chunk size
|
||||
data_vectorization_overlap_size: 128 # overlap between chunks size
|
||||
data_vectorization_nb_chunks: 2 # number of chunks to use
|
||||
|
@ -1,52 +0,0 @@
|
||||
import yaml
|
||||
from typing import List
|
||||
from discussions.message import Message
|
||||
|
||||
class Discussion:
|
||||
"""
|
||||
Class representing a discussion.
|
||||
"""
|
||||
|
||||
def __init__(self, name):
|
||||
"""
|
||||
Initializes a new Discussion object.
|
||||
|
||||
Args:
|
||||
name (str): The name of the discussion.
|
||||
"""
|
||||
self.name = name
|
||||
self.messages:List[Message] = []
|
||||
|
||||
def load_messages(self):
|
||||
"""
|
||||
Loads the messages of the discussion from the discussion.yaml file.
|
||||
"""
|
||||
with open(f'{self.name}/discussion.yaml', 'r') as file:
|
||||
self.messages = yaml.load(file)
|
||||
|
||||
def save_messages(self):
|
||||
"""
|
||||
Saves the messages of the discussion to the discussion.yaml file.
|
||||
"""
|
||||
with open(f'{self.name}/discussion.yaml', 'w') as file:
|
||||
yaml.dump(self.messages, file)
|
||||
|
||||
def remove_message(self, message_index):
|
||||
"""
|
||||
Removes a message from the discussion.
|
||||
|
||||
Args:
|
||||
message_index (int): The index of the message to remove.
|
||||
"""
|
||||
self.messages.pop(message_index)
|
||||
self.save_messages()
|
||||
|
||||
def add_message(self, message: Message):
|
||||
"""
|
||||
Adds a new message to the discussion.
|
||||
|
||||
Args:
|
||||
message (Message): The message to add.
|
||||
"""
|
||||
self.messages.append(message)
|
||||
self.save_messages()
|
@ -1,66 +0,0 @@
|
||||
import os
|
||||
from typing import List
|
||||
from discussions.discussion import Discussion
|
||||
|
||||
class DiscussionDatabase:
|
||||
"""
|
||||
Class representing a discussion database.
|
||||
"""
|
||||
|
||||
def __init__(self, name, root_folder):
|
||||
"""
|
||||
Initializes a new DiscussionDatabase object.
|
||||
|
||||
Args:
|
||||
name (str): The name of the discussion database.
|
||||
root_folder (str): The root folder of the discussion database.
|
||||
"""
|
||||
self.name = name
|
||||
self.root_folder = root_folder
|
||||
self.discussions:List[Discussion] = {}
|
||||
|
||||
def load_discussions(self):
|
||||
"""
|
||||
Loads the discussions from the discussion database.
|
||||
"""
|
||||
for discussion_folder in os.listdir(self.root_folder):
|
||||
discussion = Discussion(discussion_folder)
|
||||
discussion.load_messages()
|
||||
self.discussions[discussion_folder] = discussion
|
||||
|
||||
def save_discussions(self):
|
||||
"""
|
||||
Saves the discussions to the discussion database.
|
||||
"""
|
||||
for discussion in self.discussions.values():
|
||||
discussion.save_messages()
|
||||
|
||||
def remove_discussion(self, discussion_name):
|
||||
"""
|
||||
Removes a discussion from the discussion database.
|
||||
|
||||
Args:
|
||||
discussion_name (str): The name of the discussion to remove.
|
||||
"""
|
||||
del self.discussions[discussion_name]
|
||||
os.rmdir(f'{self.root_folder}/{discussion_name}')
|
||||
|
||||
def list_discussions(self):
|
||||
"""
|
||||
Lists all the discussions in the discussion database.
|
||||
|
||||
Returns:
|
||||
List[str]: A list of discussion names.
|
||||
"""
|
||||
return list(self.discussions.keys())
|
||||
|
||||
def new_discussion(self, discussion_name):
|
||||
"""
|
||||
Creates a new discussion in the discussion database.
|
||||
|
||||
Args:
|
||||
discussion_name (str): The name of the new discussion.
|
||||
"""
|
||||
discussion = Discussion(discussion_name)
|
||||
self.discussions[discussion_name] = discussion
|
||||
os.mkdir(f'{self.root_folder}/{discussion_name}')
|
@ -1,71 +0,0 @@
|
||||
import datetime
|
||||
import json
|
||||
import yaml
|
||||
from enum import Enum
|
||||
|
||||
__project__ = "lollms-webui"
|
||||
__author__ = "ParisNeo"
|
||||
__description__ = ""
|
||||
|
||||
|
||||
class Role(Enum):
|
||||
SYSTEM = "system"
|
||||
AI = "ai"
|
||||
USER = "user"
|
||||
|
||||
|
||||
|
||||
class Message:
|
||||
"""
|
||||
Class representing a message in a discussion.
|
||||
"""
|
||||
|
||||
def __init__(self, sender, role:Role, model:str, content:str, sending_date=None, rank=0):
|
||||
"""
|
||||
Initializes a new Message object.
|
||||
|
||||
Args:
|
||||
sender (str): The name of the sender.
|
||||
role (str): The role of the sender (system, ai, user).
|
||||
model (str): The model name or "human".
|
||||
content (str): The content of the message.
|
||||
sending_date (datetime.datetime, optional): The sending date and time. Defaults to the current date and time.
|
||||
rank (int, optional): The rank of the message. Defaults to 0.
|
||||
"""
|
||||
self.sender = sender
|
||||
self.role = role
|
||||
self.model = model
|
||||
self.content = content
|
||||
self.sending_date = sending_date or datetime.datetime.now()
|
||||
self.rank = rank
|
||||
|
||||
def rank_up(self):
|
||||
"""
|
||||
Increases the rank of the message by 1.
|
||||
"""
|
||||
self.rank += 1
|
||||
|
||||
def rank_down(self):
|
||||
"""
|
||||
Decreases the rank of the message by 1.
|
||||
"""
|
||||
if self.rank > 0:
|
||||
self.rank -= 1
|
||||
|
||||
def to_json(self):
|
||||
"""
|
||||
Converts the message object to JSON format.
|
||||
|
||||
Returns:
|
||||
str: The message object in JSON format.
|
||||
"""
|
||||
return json.dumps(self.__dict__)
|
||||
|
||||
def to_yaml(self):
|
||||
"""
|
||||
Converts the message object to YAML format.
|
||||
|
||||
Returns:
|
||||
str: The message object in YAML format.
|
||||
"""
|
||||
return yaml.dump(self.__dict__)
|
@ -230,11 +230,7 @@ async def open_file(file_path: FilePath):
|
||||
trace_exception(ex)
|
||||
lollmsElfServer.error(ex)
|
||||
return {"status":False,"error":str(ex)}
|
||||
|
||||
|
||||
|
||||
class FilePath(BaseModel):
|
||||
path: Optional[str] = Field(None, max_length=500)
|
||||
|
||||
|
||||
@router.post("/open_folder")
|
||||
async def open_folder(file_path: FilePath):
|
||||
@ -281,8 +277,8 @@ class OpenCodeFolderInVsCodeRequestModel(BaseModel):
|
||||
message_id: Optional[int] = Field(None, gt=0)
|
||||
code: Optional[str]
|
||||
|
||||
@router.post("/open_code_folder_in_vs_code")
|
||||
async def open_code_folder_in_vs_code(request: OpenCodeFolderInVsCodeRequestModel):
|
||||
@router.post("/open_discussion_folder_in_vs_code")
|
||||
async def open_discussion_folder_in_vs_code(request: OpenCodeFolderInVsCodeRequestModel):
|
||||
|
||||
client = check_access(lollmsElfServer, request.client_id)
|
||||
|
||||
@ -367,11 +363,10 @@ async def open_code_in_vs_code(vs_code_data: VSCodeData):
|
||||
|
||||
class FolderRequest(BaseModel):
|
||||
client_id: str = Field(...)
|
||||
discussion_id: Optional[int] = Field(None, title="The discussion ID")
|
||||
folder_path: Optional[str] = Field(None, title="The folder path")
|
||||
discussion_id: int = Field(...)
|
||||
|
||||
@router.post("/open_code_folder")
|
||||
async def open_code_folder(request: FolderRequest):
|
||||
@router.post("/open_discussion_folder")
|
||||
async def open_discussion_folder(request: FolderRequest):
|
||||
"""
|
||||
Opens code folder.
|
||||
|
||||
|
@ -122,11 +122,11 @@ def add_events(sio:socketio):
|
||||
ASCIIColors.yellow(f"Loading discussion for client {client_id} ... ", end="")
|
||||
if "id" in data:
|
||||
discussion_id = data["id"]
|
||||
lollmsElfServer.session.get_client(client_id).discussion = Discussion(discussion_id, lollmsElfServer.db)
|
||||
lollmsElfServer.session.get_client(client_id).discussion = Discussion(lollmsElfServer, discussion_id, lollmsElfServer.db)
|
||||
else:
|
||||
if lollmsElfServer.session.get_client(client_id).discussion is not None:
|
||||
discussion_id = lollmsElfServer.session.get_client(client_id).discussion.discussion_id
|
||||
lollmsElfServer.session.get_client(client_id).discussion = Discussion(discussion_id, lollmsElfServer.db)
|
||||
lollmsElfServer.session.get_client(client_id).discussion = Discussion(lollmsElfServer, discussion_id, lollmsElfServer.db)
|
||||
else:
|
||||
lollmsElfServer.session.get_client(client_id).discussion = lollmsElfServer.db.create_discussion()
|
||||
messages = lollmsElfServer.session.get_client(client_id).discussion.get_messages()
|
||||
|
@ -41,7 +41,7 @@ import re
|
||||
import string
|
||||
import requests
|
||||
from datetime import datetime
|
||||
from typing import List, Tuple
|
||||
from typing import List, Tuple,Callable
|
||||
import time
|
||||
import numpy as np
|
||||
from lollms.utilities import find_first_available_file_index, convert_language_name
|
||||
@ -72,7 +72,7 @@ def terminate_thread(thread):
|
||||
else:
|
||||
ASCIIColors.yellow("Canceled successfully")# The current version of the webui
|
||||
|
||||
lollms_webui_version="9.6"
|
||||
lollms_webui_version="9.7"
|
||||
|
||||
|
||||
|
||||
@ -186,7 +186,7 @@ class LOLLMSWebUI(LOLLMSElfServer):
|
||||
self.discussion_db_name = config["discussion_db_name"]
|
||||
|
||||
# Create database object
|
||||
self.db = DiscussionsDB(self.lollms_paths, self.discussion_db_name)
|
||||
self.db = DiscussionsDB(self, self.lollms_paths, self.discussion_db_name)
|
||||
|
||||
# If the database is empty, populate it with tables
|
||||
ASCIIColors.info("Checking discussions database... ",end="")
|
||||
@ -712,6 +712,19 @@ class LOLLMSWebUI(LOLLMSElfServer):
|
||||
|
||||
return discussion_messages # Removes the last return
|
||||
|
||||
def full(self, full_text:str, callback: Callable[[str, MSG_TYPE, dict, list], bool]=None, client_id=0):
|
||||
"""This sends full text to front end
|
||||
|
||||
Args:
|
||||
step_text (dict): The step text
|
||||
callback (callable, optional): A callable with this signature (str, MSG_TYPE) to send the text to. Defaults to None.
|
||||
"""
|
||||
if not callback:
|
||||
callback = partial(self.process_chunk,client_id = client_id)
|
||||
|
||||
if callback:
|
||||
callback(full_text, MSG_TYPE.MSG_TYPE_FULL)
|
||||
|
||||
def notify(
|
||||
self,
|
||||
content,
|
||||
@ -760,7 +773,7 @@ class LOLLMSWebUI(LOLLMSElfServer):
|
||||
open=False
|
||||
):
|
||||
client = self.session.get_client(client_id)
|
||||
self.close_message(client_id)
|
||||
#self.close_message(client_id)
|
||||
mtdt = metadata if metadata is None or type(metadata) == str else json.dumps(metadata, indent=4)
|
||||
if sender==None:
|
||||
sender= self.personality.name
|
||||
@ -918,11 +931,10 @@ class LOLLMSWebUI(LOLLMSElfServer):
|
||||
Processes a chunk of generated text
|
||||
"""
|
||||
client = self.session.get_client(client_id)
|
||||
if chunk is None:
|
||||
return True
|
||||
if not client_id in list(self.session.clients.keys()):
|
||||
self.error("Connection lost", client_id=client_id)
|
||||
return
|
||||
if chunk is not None:
|
||||
if not client_id in list(self.session.clients.keys()):
|
||||
self.error("Connection lost", client_id=client_id)
|
||||
return
|
||||
if message_type == MSG_TYPE.MSG_TYPE_STEP:
|
||||
ASCIIColors.info("--> Step:"+chunk)
|
||||
if message_type == MSG_TYPE.MSG_TYPE_STEP_START:
|
||||
|
@ -1,7 +1,7 @@
|
||||
import requests
|
||||
|
||||
# Set the URL of the endpoint
|
||||
url = "http://localhost:9600/open_code_folder"
|
||||
url = "http://localhost:9600/open_discussion_folder"
|
||||
|
||||
# Valid folder path
|
||||
valid_folder_path = {"folder_path": "c:"}
|
||||
|
@ -1,6 +1,6 @@
|
||||
'''
|
||||
This python script is performing a Denial of Service (DoS) attack on your endpoint.
|
||||
It is creating a large number of requests (1000 in this case) to the '/open_code_folder' API endpoint of your server.
|
||||
It is creating a large number of requests (1000 in this case) to the '/open_discussion_folder' API endpoint of your server.
|
||||
This could potentially overload your server, making it unable to serve normal, legitimate requests.
|
||||
|
||||
Please make sure you test this only on a virtual machine since it can overload your own PC and crush it
|
||||
@ -14,5 +14,5 @@ for i in range(1000):
|
||||
data = {
|
||||
"discussion_id":f"{i}",
|
||||
}
|
||||
response = requests.post(f"http://{IP_ADDRESS}:{str(PORT)}/open_code_folder", json=data)
|
||||
response = requests.post(f"http://{IP_ADDRESS}:{str(PORT)}/open_discussion_folder", json=data)
|
||||
print(i, response.json())
|
File diff suppressed because one or more lines are too long
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-59608853.js"></script>
|
||||
<link rel="stylesheet" href="/assets/index-91104afa.css">
|
||||
<script type="module" crossorigin src="/assets/index-58d8702e.js"></script>
|
||||
<link rel="stylesheet" href="/assets/index-82bacbd8.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
@ -464,9 +464,14 @@ export default {
|
||||
for (let item of items) {
|
||||
if (item.type.indexOf("image") !== -1) {
|
||||
const blob = item.getAsFile();
|
||||
// Instead of reading the file and setting it as an image URL,
|
||||
// call the addFiles method and pass the file
|
||||
this.addFiles([blob]); // Assuming addFiles accepts an array of files
|
||||
// Generate a unique identifier for the file
|
||||
const uniqueId = Date.now() + '_' + Math.random().toString(36).substr(2, 9);
|
||||
const newFileName = `image_${uniqueId}.png`;
|
||||
console.log("newFileName",newFileName)
|
||||
// Create a new file with the unique name
|
||||
const newFile = new File([blob], newFileName, {type: blob.type});
|
||||
|
||||
this.addFiles([newFile]); // Assuming addFiles accepts an array of files
|
||||
}
|
||||
else if (item.kind === 'file') {
|
||||
const file = item.getAsFile();
|
||||
@ -475,7 +480,7 @@ export default {
|
||||
}
|
||||
if (filesToUpload.length > 0) {
|
||||
this.addFiles(filesToUpload);
|
||||
}
|
||||
}
|
||||
},
|
||||
toggleSwitch() {
|
||||
this.$store.state.config.activate_internet_search = !this.$store.state.config.activate_internet_search;
|
||||
@ -759,12 +764,12 @@ export default {
|
||||
axios.get('/download_files')
|
||||
},
|
||||
remove_file(file){
|
||||
axios.get('/remove_file',{client_id:this.$store.state.client_id, name: file}).then(res=>{
|
||||
axios.get('/remove_discussion_file',{client_id:this.$store.state.client_id, name: file}).then(res=>{
|
||||
console.log(res)
|
||||
})
|
||||
},
|
||||
clear_files(){
|
||||
axios.post('/clear_personality_files_list', {"client_id":this.$store.state.client_id}).then(res=>{
|
||||
axios.post('/clear_discussion_files_list', {"client_id":this.$store.state.client_id}).then(res=>{
|
||||
console.log(res)
|
||||
if(res.data.state){
|
||||
this.$store.state.toast.showToast("File removed successfully",4,true);
|
||||
@ -902,7 +907,7 @@ export default {
|
||||
|
||||
removeItem(file) {
|
||||
console.log("Réemoving ",file.name)
|
||||
axios.post('/remove_file',{
|
||||
axios.post('/remove_discussion_file',{
|
||||
client_id:this.$store.state.client_id,
|
||||
name:file.name
|
||||
},
|
||||
@ -949,7 +954,7 @@ export default {
|
||||
takePicture(){
|
||||
socket.emit('take_picture')
|
||||
socket.on('picture_taken',()=>{
|
||||
axios.post('/get_current_personality_files_list', {"client_id":this.$store.state.client_id}).then(res=>{
|
||||
axios.post('/get_discussion_files_list', {"client_id":this.$store.state.client_id}).then(res=>{
|
||||
this.filesList = res.data.files;
|
||||
this.isFileSentList= res.data.files.map(file => {
|
||||
return true;
|
||||
|
@ -235,7 +235,7 @@ export default {
|
||||
'code': this.code
|
||||
})
|
||||
console.log(json)
|
||||
fetch(`${this.host}/open_code_folder_in_vs_code`, {
|
||||
fetch(`${this.host}/open_folder_in_vs_code`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: json
|
||||
@ -255,7 +255,7 @@ export default {
|
||||
openFolder() {
|
||||
const json = JSON.stringify({ 'client_id': this.client_id, 'discussion_id': this.discussion_id })
|
||||
console.log(json)
|
||||
fetch(`${this.host}/open_code_folder`, {
|
||||
fetch(`${this.host}/open_discussion_folder`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: json
|
||||
|
@ -19,46 +19,52 @@
|
||||
:class="loading ? 'min-h-full w-2 rounded-xl self-stretch animate-bounce bg-accent ' : ' '"></div>
|
||||
|
||||
</div>
|
||||
<!-- TITLE -->
|
||||
<p v-if="!editTitle" :title="title" class="line-clamp-1 w-4/6 ml-1 -mx-5 ">{{ title ? title === "untitled" ? "New discussion" :
|
||||
title : "New discussion" }}</p>
|
||||
<!-- CONTAINER FOR TITLE AND CONTROL BUTTONS -->
|
||||
<div class="flex flex-row items-center w-full">
|
||||
<!-- TITLE -->
|
||||
<p v-if="!editTitle" :title="title" class="line-clamp-1 w-4/6 ml-1 -mx-5 ">{{ title ? title === "untitled" ? "New discussion" :
|
||||
title : "New discussion" }}</p>
|
||||
|
||||
<input v-if="editTitle" type="text" id="title-box" ref="titleBox"
|
||||
class="bg-bg-light dark:bg-bg-dark rounded-md border-0 w-full -m-1 p-1" :value="title" required
|
||||
@keydown.enter.exact="editTitleEvent()" @keydown.esc.exact="editTitleMode = false"
|
||||
@input="chnageTitle($event.target.value)" @click.stop>
|
||||
<input v-if="editTitle" type="text" id="title-box" ref="titleBox"
|
||||
class="bg-bg-light dark:bg-bg-dark rounded-md border-0 w-full -m-1 p-1" :value="title" required
|
||||
@keydown.enter.exact="editTitleEvent()" @keydown.esc.exact="editTitleMode = false"
|
||||
@input="chnageTitle($event.target.value)" @click.stop>
|
||||
|
||||
<!-- CONTROL BUTTONS -->
|
||||
<div class="flex items-center flex-1 max-h-6">
|
||||
<!-- EDIT TITLE CONFIRM -->
|
||||
<div v-if="showConfirmation" class="flex gap-3 flex-1 items-center justify-end duration-75">
|
||||
<button class="text-2xl hover:text-red-600 duration-75 active:scale-90 " title="Discard title changes"
|
||||
type="button" @click.stop="cancel()">
|
||||
<i data-feather="x"></i>
|
||||
</button>
|
||||
<button class="text-2xl hover:text-secondary duration-75 active:scale-90" title="Confirm title changes"
|
||||
type="button" @click.stop="editTitleMode?editTitleEvent():deleteMode?deleteEvent():makeTitleEvent()">
|
||||
<i data-feather="check"></i>
|
||||
</button>
|
||||
</div>
|
||||
<!-- EDIT AND REMOVE -->
|
||||
<div v-if="!showConfirmation"
|
||||
class="flex gap-3 flex-1 items-center justify-end invisible group-hover:visible duration-75">
|
||||
<button class="text-2xl hover:text-secondary duration-75 active:scale-90" title="Make a title" type="button"
|
||||
@click.stop="makeTitleMode = true">
|
||||
<i data-feather="type"></i>
|
||||
</button>
|
||||
<button class="text-2xl hover:text-secondary duration-75 active:scale-90" title="Edit title" type="button"
|
||||
@click.stop="editTitleMode = true">
|
||||
<i data-feather="edit-2"></i>
|
||||
</button>
|
||||
<button class="text-2xl hover:text-red-600 duration-75 active:scale-90 " title="Remove discussion" type="button"
|
||||
@click.stop="deleteMode = true">
|
||||
<i data-feather="trash"></i>
|
||||
</button>
|
||||
<!-- CONTROL BUTTONS -->
|
||||
<div class="flex items-center flex-1 max-h-6">
|
||||
<!-- EDIT TITLE CONFIRM -->
|
||||
<div v-if="showConfirmation" class="flex gap-3 flex-1 items-center justify-end duration-75">
|
||||
<button class="text-2xl hover:text-red-600 duration-75 active:scale-90 " title="Discard title changes"
|
||||
type="button" @click.stop="cancel()">
|
||||
<i data-feather="x"></i>
|
||||
</button>
|
||||
<button class="text-2xl hover:text-secondary duration-75 active:scale-90" title="Confirm title changes"
|
||||
type="button" @click.stop="editTitleMode?editTitleEvent():deleteMode?deleteEvent():makeTitleEvent()">
|
||||
<i data-feather="check"></i>
|
||||
</button>
|
||||
</div>
|
||||
<!-- EDIT AND REMOVE -->
|
||||
<div v-if="!showConfirmation"
|
||||
class="flex gap-3 flex-1 items-center justify-end invisible group-hover:visible duration-75">
|
||||
<button class="text-2xl hover:text-secondary duration-75 active:scale-90" title="Open folder" type="button"
|
||||
@click.stop="openFolderEvent()">
|
||||
<i data-feather="folder"></i>
|
||||
</button>
|
||||
<button class="text-2xl hover:text-secondary duration-75 active:scale-90" title="Make a title" type="button"
|
||||
@click.stop="makeTitleMode = true">
|
||||
<i data-feather="type"></i>
|
||||
</button>
|
||||
<button class="text-2xl hover:text-secondary duration-75 active:scale-90" title="Edit title" type="button"
|
||||
@click.stop="editTitleMode = true">
|
||||
<i data-feather="edit-2"></i>
|
||||
</button>
|
||||
<button class="text-2xl hover:text-red-600 duration-75 active:scale-90 " title="Remove discussion" type="button"
|
||||
@click.stop="deleteMode = true">
|
||||
<i data-feather="trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -68,7 +74,7 @@ import feather from 'feather-icons'
|
||||
|
||||
export default {
|
||||
name: 'Discussion',
|
||||
emits: ['delete', 'select', 'editTitle', 'makeTitle', 'checked'],
|
||||
emits: ['delete', 'select', 'openFolder', 'editTitle', 'makeTitle', 'checked'],
|
||||
props: {
|
||||
id: Number,
|
||||
title: String,
|
||||
@ -86,6 +92,7 @@ export default {
|
||||
editTitleMode: false,
|
||||
makeTitleMode: false,
|
||||
deleteMode:false,
|
||||
openFolder:false,
|
||||
editTitle: false,
|
||||
newTitle: String,
|
||||
checkBoxValue_local: false
|
||||
@ -105,6 +112,12 @@ export default {
|
||||
selectEvent() {
|
||||
this.$emit("select")
|
||||
},
|
||||
openFolderEvent() {
|
||||
this.$emit("openFolder",
|
||||
{
|
||||
id: this.id
|
||||
})
|
||||
},
|
||||
editTitleEvent() {
|
||||
this.editTitle = false
|
||||
this.editTitleMode = false
|
||||
@ -174,7 +187,6 @@ export default {
|
||||
},
|
||||
makeTitleMode(newval) {
|
||||
this.showConfirmation = newval
|
||||
|
||||
},
|
||||
|
||||
checkBoxValue(newval, oldval) {
|
||||
|
@ -5,7 +5,7 @@
|
||||
<!-- LOGO -->
|
||||
<RouterLink :to="{ name: 'discussions' }">
|
||||
<div class="flex items-center gap-3 flex-1">
|
||||
<img class="w-12 hover:scale-95 duration-150 " title="LoLLMS WebUI" src="@/assets/logo.png" alt="Logo">
|
||||
<img class="w-12 hover:scale-95 duration-150" title="LoLLMS WebUI" :src="$store.state.config.app_custom_logo || storeLogo" alt="Logo">
|
||||
<div class="flex flex-col">
|
||||
<p class="text-2xl font-bold text-2xl drop-shadow-md align-middle">LoLLMS</p>
|
||||
<p class="text-gray-400 ">One tool to rule them all</p>
|
||||
@ -168,6 +168,7 @@ import feather from 'feather-icons'
|
||||
import static_info from "../assets/static_info.svg"
|
||||
import animated_info from "../assets/animated_info.svg"
|
||||
import { useRouter } from 'vue-router'
|
||||
import storeLogo from '@/assets/logo.png'
|
||||
|
||||
import axios from 'axios';
|
||||
</script>
|
||||
@ -263,7 +264,7 @@ export default {
|
||||
isLanguageMenuVisible: false,
|
||||
static_info: static_info,
|
||||
animated_info: animated_info,
|
||||
|
||||
storeLogo:storeLogo,
|
||||
is_first_connection:true,
|
||||
discord:discord,
|
||||
FastAPI:FastAPI,
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
<div class="flex items-center gap-3 text-5xl drop-shadow-md align-middle pt-24 ">
|
||||
|
||||
<img class="w-24 animate-bounce" title="LoLLMS WebUI" src="@/assets/logo.png" alt="Logo">
|
||||
<img class="w-24 animate-bounce" title="LoLLMS WebUI" :src="$store.state.config.app_custom_logo || storeLogo" alt="Logo">
|
||||
<div class="flex flex-col items-start">
|
||||
<p class="text-2xl ">LoLLMS</p>
|
||||
<p class="text-gray-400 text-base">One tool to rule them all</p>
|
||||
@ -23,8 +23,12 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import storeLogo from '@/assets/logo.png'
|
||||
export default {
|
||||
name: 'WelcomeComponent',
|
||||
data(){
|
||||
storeLogo:storeLogo
|
||||
},
|
||||
setup() {
|
||||
|
||||
|
||||
|
@ -210,6 +210,7 @@
|
||||
:checkBoxValue="item.checkBoxValue"
|
||||
@select="selectDiscussion(item)"
|
||||
@delete="deleteDiscussion(item.id)"
|
||||
@openFolder="openFolder"
|
||||
@editTitle="editTitle"
|
||||
@makeTitle="makeTitle"
|
||||
@checked="checkUncheckDiscussion" />
|
||||
@ -684,7 +685,7 @@ export default {
|
||||
},
|
||||
recoverFiles(){
|
||||
console.log("Recovering files")
|
||||
axios.post('/get_current_personality_files_list', {"client_id":this.$store.state.client_id}).then(res=>{
|
||||
axios.post('/get_discussion_files_list', {"client_id":this.$store.state.client_id}).then(res=>{
|
||||
this.$refs.chatBox.filesList = res.data.files;
|
||||
this.$refs.chatBox.isFileSentList= res.data.files.map(file => {
|
||||
return true;
|
||||
@ -946,6 +947,7 @@ export default {
|
||||
if (this.currentDiscussion.title === '' || this.currentDiscussion.title === null) {
|
||||
this.changeTitleUsingUserMSG(this.currentDiscussion.id, this.discussionArr[1].content)
|
||||
}
|
||||
this.recoverFiles()
|
||||
}
|
||||
})
|
||||
|
||||
@ -967,6 +969,7 @@ export default {
|
||||
this.changeTitleUsingUserMSG(this.currentDiscussion.id, this.discussionArr[1].content)
|
||||
}
|
||||
}
|
||||
this.recoverFiles()
|
||||
});
|
||||
|
||||
}
|
||||
@ -1475,6 +1478,14 @@ export default {
|
||||
})
|
||||
|
||||
},
|
||||
async openFolder(id){
|
||||
const json = JSON.stringify({ 'client_id': this.$store.state.client_id, 'discussion_id': id.id })
|
||||
console.log(json)
|
||||
await axios.post(`/open_discussion_folder`, json, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
})
|
||||
},
|
||||
async editTitle(newTitleObj) {
|
||||
|
||||
const index = this.list.findIndex((x) => x.id == newTitleObj.id)
|
||||
|
@ -223,6 +223,17 @@
|
||||
<div class="flex flex-col mb-2 px-3 pb-2">
|
||||
<Card title="General" :is_subcard="true" class="pb-2 m-2">
|
||||
<table class="expand-to-fit bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block 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">
|
||||
<tr>
|
||||
<td style="min-width: 200px;">
|
||||
<label for="app_custom_logo" class="text-sm font-bold" style="margin-right: 1rem;">Application logo:</label>
|
||||
</td>
|
||||
<td style="width: 100%;">
|
||||
<label for="avatar-upload">
|
||||
<img :src="configFile.app_custom_logo!=''? '/user_infos/'+configFile.app_custom_logo:storeLogo" class="w-50 h-50 rounded-full" style="max-width: 50px; max-height: 50px; cursor: pointer;">
|
||||
</label>
|
||||
<input type="file" id="avatar-upload" style="display: none" @change="uploadLogo">
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td style="min-width: 200px;">
|
||||
@ -478,7 +489,7 @@
|
||||
</td>
|
||||
<td style="width: 100%;">
|
||||
<label for="avatar-upload">
|
||||
<img :src="'/user_infos/'+configFile.user_avatar" class="w-50 h-50 rounded-full" style="max-width: 50px; max-height: 50px; cursor: pointer;">
|
||||
<img :src="'/user_infos/'+configFile.user_avatar || storeLogo" class="w-50 h-50 rounded-full" style="max-width: 50px; max-height: 50px; cursor: pointer;">
|
||||
</label>
|
||||
<input type="file" id="avatar-upload" style="display: none" @change="uploadAvatar">
|
||||
</td>
|
||||
@ -2959,6 +2970,7 @@ import Card from "@/components/Card.vue"
|
||||
import RadioOptions from '../components/RadioOptions.vue';
|
||||
import ExtensionEntry from "@/components/ExtensionEntry.vue"
|
||||
|
||||
import storeLogo from '@/assets/logo.png'
|
||||
|
||||
|
||||
import {refreshHardwareUsage} from "../main"
|
||||
@ -3009,7 +3021,7 @@ export default {
|
||||
"Hindi": "hi"
|
||||
},
|
||||
|
||||
|
||||
storeLogo:storeLogo,
|
||||
binding_changed:false,
|
||||
SVGGPU:SVGGPU,
|
||||
models_zoo:[],
|
||||
@ -3405,7 +3417,27 @@ export default {
|
||||
socket.emit('install_model', { path: path, name: model_object.model.name, variant_name:this.selected_variant.name, type:model_object.model.type });
|
||||
console.log("Started installation, please wait");
|
||||
},
|
||||
|
||||
uploadLogo(event){
|
||||
const file = event.target.files[0]; // Get the selected file
|
||||
const formData = new FormData(); // Create a FormData object
|
||||
formData.append('avatar', file); // Add the file to the form data with the key 'avatar'
|
||||
console.log("Uploading avatar")
|
||||
// Make an API request to upload the avatar
|
||||
axios.post('/upload_avatar', formData)
|
||||
.then(response => {
|
||||
console.log("Avatar uploaded successfully")
|
||||
|
||||
this.$store.state.toast.showToast("Avatar uploaded successfully!", 4, true)
|
||||
// Assuming the server responds with the file name after successful upload
|
||||
const fileName = response.data.fileName;
|
||||
console.log("response",response);
|
||||
this.app_custom_logo = fileName; // Update the user_avatar value with the file name
|
||||
this.update_setting("app_custom_logo", fileName, ()=>{}).then(()=>{})
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error uploading avatar:', error);
|
||||
});
|
||||
},
|
||||
uploadAvatar(event){
|
||||
const file = event.target.files[0]; // Get the selected file
|
||||
const formData = new FormData(); // Create a FormData object
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit e74bdd27b5983b60ea3b70b2dd79fce1297d5b74
|
||||
Subproject commit 0b59189e42e9fad6ecd94e7076aeb6f8d0737caa
|
@ -1 +1 @@
|
||||
Subproject commit 198e45cb1cc99ca20e6fae4c0d1db0857f7dc172
|
||||
Subproject commit a554175a8e6d73bdfa8e16446bb6fd17e921d72a
|
Loading…
Reference in New Issue
Block a user