fixed errors

This commit is contained in:
Saifeddine ALOUI 2024-02-18 00:14:52 +01:00
parent deaf87a0f7
commit 6a0bf65953
14 changed files with 388 additions and 317 deletions

70
app.py
View File

@ -24,6 +24,11 @@ import webbrowser
import threading import threading
import os import os
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
from pydantic import BaseModel, ValidationError
from fastapi.encoders import jsonable_encoder
app = FastAPI(title="LoLLMS", description="This is the LoLLMS-Webui API documentation") app = FastAPI(title="LoLLMS", description="This is the LoLLMS-Webui API documentation")
@ -106,39 +111,35 @@ if __name__ == "__main__":
from events.lollms_chatbox_events import add_events as lollms_chatbox_events_add from events.lollms_chatbox_events import add_events as lollms_chatbox_events_add
from events.lollms_interactive_events import add_events as lollms_interactive_events_add from events.lollms_interactive_events import add_events as lollms_interactive_events_add
app.include_router(lollms_infos_router) # endpoints for remote access
app.include_router(lollms_binding_files_server_router)
app.include_router(lollms_hardware_infos_router)
app.include_router(lollms_binding_infos_router)
app.include_router(lollms_models_infos_router)
app.include_router(lollms_personalities_infos_router)
app.include_router(lollms_extensions_infos_router)
app.include_router(lollms_webui_infos_router)
app.include_router(lollms_generator_router) app.include_router(lollms_generator_router)
app.include_router(lollms_discussion_router)
app.include_router(lollms_message_router)
app.include_router(lollms_user_router)
app.include_router(lollms_advanced_router)
app.include_router(chat_bar_router)
app.include_router(lollms_xtts_add_router)
app.include_router(lollms_sd_router)
app.include_router(lollms_ollama_router)
app.include_router(lollms_petals_router)
app.include_router(lollms_vllm_router)
app.include_router(lollms_playground_router)
# Endpoints reserved for local access
if (not config.headless_server_mode) or config.force_accept_remote_access:
app.include_router(lollms_configuration_infos_router) app.include_router(lollms_infos_router)
app.include_router(lollms_binding_files_server_router)
app.include_router(lollms_hardware_infos_router)
app.include_router(lollms_binding_infos_router)
app.include_router(lollms_models_infos_router)
app.include_router(lollms_personalities_infos_router)
app.include_router(lollms_extensions_infos_router)
app.include_router(lollms_webui_infos_router)
app.include_router(lollms_discussion_router)
app.include_router(lollms_message_router)
app.include_router(lollms_user_router)
app.include_router(lollms_advanced_router)
app.include_router(chat_bar_router)
app.include_router(lollms_xtts_add_router)
app.include_router(lollms_sd_router)
app.include_router(lollms_ollama_router)
app.include_router(lollms_petals_router)
app.include_router(lollms_vllm_router)
app.include_router(lollms_playground_router)
app.include_router(lollms_configuration_infos_router)
@ -171,9 +172,18 @@ if __name__ == "__main__":
app.mount("/", StaticFiles(directory=Path(__file__).parent/"web"/"dist", html=True), name="static") app.mount("/", StaticFiles(directory=Path(__file__).parent/"web"/"dist", html=True), name="static")
@app.exception_handler(ValidationError)
async def validation_exception_handler(request: Request, exc: ValidationError):
print(f"Error: {exc.errors()}") # Print the validation error details
return JSONResponse(
status_code=422,
content=jsonable_encoder({"detail": exc.errors(), "body": await exc.body}), # Send the error details and the original request body
)
app = ASGIApp(socketio_server=sio, other_asgi_app=app) app = ASGIApp(socketio_server=sio, other_asgi_app=app)
lollmsElfServer.app = app lollmsElfServer.app = app
try: try:

View File

@ -1,16 +1,18 @@
# =================== Lord Of Large Language Multimodal Systems Configuration file =========================== # =================== Lord Of Large Language Multimodal Systems Configuration file ===========================
version: 63 version: 65
binding_name: null binding_name: null
model_name: null model_name: null
show_news_panel: True show_news_panel: True
# Execution protection # Security measures
turn_on_code_execution: True turn_on_code_execution: True
turn_on_code_validation: True turn_on_code_validation: True
turn_on_open_file_validation: False turn_on_open_file_validation: False
turn_on_send_file_validation: False turn_on_send_file_validation: False
force_accept_remote_access: false
# Server information # Server information
headless_server_mode: False headless_server_mode: False
allowed_origins: [] allowed_origins: []

View File

@ -268,7 +268,7 @@ The Flask backend API exposes various endpoints to interact with the application
--- ---
### Endpoint: /delete_message (GET) ### Endpoint: /delete_message (post)
**Description**: Deletes a message. **Description**: Deletes a message.

View File

@ -7,7 +7,7 @@ description:
application. These routes allow users to manipulate the message elements. application. These routes allow users to manipulate the message elements.
""" """
from fastapi import APIRouter from fastapi import APIRouter, Body
from pydantic import Field from pydantic import Field
from lollms_webui import LOLLMSWebUI from lollms_webui import LOLLMSWebUI
from pydantic import BaseModel from pydantic import BaseModel
@ -19,7 +19,8 @@ from api.db import DiscussionsDB
from safe_store.text_vectorizer import TextVectorizer, VectorizationMethod, VisualizationMethod from safe_store.text_vectorizer import TextVectorizer, VectorizationMethod, VisualizationMethod
import tqdm import tqdm
from typing import Any, Optional
from pydantic import BaseModel, ValidationError
# ----------------------- Defining router and main class ------------------------------ # ----------------------- Defining router and main class ------------------------------
router = APIRouter() router = APIRouter()
@ -31,7 +32,7 @@ class EditMessageParameters(BaseModel):
message: str = Field(..., min_length=1) message: str = Field(..., min_length=1)
metadata: dict = Field(default={}) metadata: dict = Field(default={})
@router.get("/edit_message") @router.post("/edit_message")
async def edit_message(edit_params: EditMessageParameters): async def edit_message(edit_params: EditMessageParameters):
client_id = edit_params.client_id client_id = edit_params.client_id
message_id = edit_params.id message_id = edit_params.id
@ -50,25 +51,25 @@ class MessageRankParameters(BaseModel):
client_id: str = Field(..., min_length=1) client_id: str = Field(..., min_length=1)
id: int = Field(..., gt=0) id: int = Field(..., gt=0)
@router.get("/message_rank_up") @router.post("/message_rank_up")
async def message_rank_up(rank_params: MessageRankParameters): async def message_rank_up(rank_params: MessageRankParameters):
client_id = rank_params.client_id client_id = rank_params.client_id
discussion_id = rank_params.id message_id = rank_params.id
try: try:
new_rank = lollmsElfServer.connections[client_id]["current_discussion"].message_rank_up(discussion_id) new_rank = lollmsElfServer.connections[client_id]["current_discussion"].message_rank_up(message_id)
return {"status": True, "new_rank": new_rank} return {"status": True, "new_rank": new_rank}
except Exception as ex: except Exception as ex:
trace_exception(ex) # Assuming 'trace_exception' function logs the error trace_exception(ex) # Assuming 'trace_exception' function logs the error
return {"status": False, "error": "There was an error ranking up the message"} return {"status": False, "error": "There was an error ranking up the message"}
@router.get("/message_rank_down") @router.post("/message_rank_down")
def message_rank_down(rank_params: MessageRankParameters): def message_rank_down(rank_params: MessageRankParameters):
client_id = rank_params.client_id client_id = rank_params.client_id
discussion_id = rank_params.id message_id = rank_params.id
try: try:
new_rank = lollmsElfServer.connections[client_id]["current_discussion"].message_rank_down(discussion_id) new_rank = lollmsElfServer.connections[client_id]["current_discussion"].message_rank_down(message_id)
return {"status": True, "new_rank": new_rank} return {"status": True, "new_rank": new_rank}
except Exception as ex: except Exception as ex:
return {"status": False, "error":str(ex)} return {"status": False, "error":str(ex)}
@ -77,18 +78,20 @@ class MessageDeleteParameters(BaseModel):
client_id: str = Field(..., min_length=1) client_id: str = Field(..., min_length=1)
id: int = Field(..., gt=0) id: int = Field(..., gt=0)
@router.get("/delete_message") @router.post("/delete_message")
async def delete_message(delete_params: MessageDeleteParameters): async def delete_message(delete_params: MessageDeleteParameters):
client_id = delete_params.client_id client_id = delete_params.client_id
discussion_id = delete_params.id message_id = delete_params.id
if lollmsElfServer.connections[client_id]["current_discussion"] is None: if lollmsElfServer.connections[client_id]["current_discussion"] is None:
return {"status": False,"message":"No discussion is selected"} return {"status": False,"message":"No discussion is selected"}
else: else:
try: try:
new_rank = lollmsElfServer.connections[client_id]["current_discussion"].delete_message(discussion_id) new_rank = lollmsElfServer.connections[client_id]["current_discussion"].delete_message(message_id)
ASCIIColors.yellow("Message deleted") ASCIIColors.yellow("Message deleted")
return {"status":True,"new_rank": new_rank} return {"status":True,"new_rank": new_rank}
except Exception as ex: except Exception as ex:
trace_exception(ex) # Assuming 'trace_exception' function logs the error trace_exception(ex) # Assuming 'trace_exception' function logs the error
return {"status": False, "error": "There was an error deleting the message"} return {"status": False, "error": "There was an error deleting the message"}

View File

@ -35,6 +35,12 @@ async def get_lollms_webui_version():
@router.get("/restart_program") @router.get("/restart_program")
async def restart_program(): async def restart_program():
"""Restart the program.""" """Restart the program."""
if lollmsElfServer.config.headless_server_mode:
return {"status":False,"error":"Restarting app is blocked when in headless mode for obvious security reasons!"}
if lollmsElfServer.config.host=="0.0.0.0":
return {"status":False,"error":"Restarting app is blocked when the server is exposed outside for very obvious reasons!"}
lollmsElfServer.ShowBlockingMessage("Restarting program.\nPlease stand by...") lollmsElfServer.ShowBlockingMessage("Restarting program.\nPlease stand by...")
# Stop the socketIO server # Stop the socketIO server
run_async(lollmsElfServer.sio.shutdown) run_async(lollmsElfServer.sio.shutdown)
@ -56,6 +62,12 @@ async def restart_program():
@router.get("/update_software") @router.get("/update_software")
async def update_software(): async def update_software():
"""Update the software.""" """Update the software."""
if lollmsElfServer.config.headless_server_mode:
return {"status":False,"error":"Restarting app is blocked when in headless mode for obvious security reasons!"}
if lollmsElfServer.config.host=="0.0.0.0":
return {"status":False,"error":"Restarting app is blocked when the server is exposed outside for very obvious reasons!"}
# Display an informative message # Display an informative message
ASCIIColors.info("") ASCIIColors.info("")
ASCIIColors.info("") ASCIIColors.info("")
@ -80,6 +92,12 @@ async def update_software():
@router.get("/check_update") @router.get("/check_update")
def check_update(): def check_update():
"""Checks if an update is available""" """Checks if an update is available"""
if lollmsElfServer.config.headless_server_mode:
return {"status":False,"error":"Restarting app is blocked when in headless mode for obvious security reasons!"}
if lollmsElfServer.config.host=="0.0.0.0":
return {"status":False,"error":"Restarting app is blocked when the server is exposed outside for very obvious reasons!"}
if lollmsElfServer.config.auto_update: if lollmsElfServer.config.auto_update:
res = lollmsElfServer.check_update_() res = lollmsElfServer.check_update_()
return {'update_availability':res} return {'update_availability':res}

@ -1 +1 @@
Subproject commit 56980df6ec0931e92827dafc91d1494d53a3fffc Subproject commit d6532fbaf6e41911d1c951f4682ef4f329621996

View File

@ -0,0 +1,18 @@
import requests
import json
url = "http://localhost:9600/delete_message"
payload = {
"client_id": "test",
"id": 283
}
headers = {
'accept': 'application/json',
'Content-Type': 'application/json'
}
response = requests.post(url, headers=headers, data=json.dumps(payload))
print(response.text)

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
View File

@ -6,8 +6,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LoLLMS WebUI - Welcome</title> <title>LoLLMS WebUI - Welcome</title>
<script type="module" crossorigin src="/assets/index-458fe287.js"></script> <script type="module" crossorigin src="/assets/index-338e837b.js"></script>
<link rel="stylesheet" href="/assets/index-94163e69.css"> <link rel="stylesheet" href="/assets/index-67427921.css">
</head> </head>
<body> <body>
<div id="app"></div> <div id="app"></div>

12
web/package-lock.json generated
View File

@ -10,6 +10,7 @@
"dependencies": { "dependencies": {
"axios": "^1.3.6", "axios": "^1.3.6",
"baklavajs": "^2.3.0", "baklavajs": "^2.3.0",
"dompurify": "^3.0.8",
"feather-icons": "^4.29.0", "feather-icons": "^4.29.0",
"flowbite": "^1.6.5", "flowbite": "^1.6.5",
"flowbite-vue": "^0.0.10", "flowbite-vue": "^0.0.10",
@ -1849,9 +1850,9 @@
} }
}, },
"node_modules/dompurify": { "node_modules/dompurify": {
"version": "2.4.3", "version": "3.0.8",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.3.tgz", "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.8.tgz",
"integrity": "sha512-q6QaLcakcRjebxjg8/+NP+h0rPfatOgOzc46Fst9VAA3jF2ApfKBNKMzdP4DYTqtUMXSCd5pRS/8Po/OmoCHZQ==" "integrity": "sha512-b7uwreMYL2eZhrSCRC4ahLTeZcPZxSmYfmcQGXGkXiZSNW1X85v+SDM5KsWcpivIiUBH47Ji7NtyUdpLeF5JZQ=="
}, },
"node_modules/electron-to-chromium": { "node_modules/electron-to-chromium": {
"version": "1.4.544", "version": "1.4.544",
@ -2855,6 +2856,11 @@
"web-worker": "^1.2.0" "web-worker": "^1.2.0"
} }
}, },
"node_modules/mermaid/node_modules/dompurify": {
"version": "2.4.3",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.3.tgz",
"integrity": "sha512-q6QaLcakcRjebxjg8/+NP+h0rPfatOgOzc46Fst9VAA3jF2ApfKBNKMzdP4DYTqtUMXSCd5pRS/8Po/OmoCHZQ=="
},
"node_modules/micromatch": { "node_modules/micromatch": {
"version": "4.0.5", "version": "4.0.5",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",

View File

@ -12,6 +12,7 @@
"dependencies": { "dependencies": {
"axios": "^1.3.6", "axios": "^1.3.6",
"baklavajs": "^2.3.0", "baklavajs": "^2.3.0",
"dompurify": "^3.0.8",
"feather-icons": "^4.29.0", "feather-icons": "^4.29.0",
"flowbite": "^1.6.5", "flowbite": "^1.6.5",
"flowbite-vue": "^0.0.10", "flowbite-vue": "^0.0.10",

View File

@ -30,6 +30,9 @@ 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'; import CodeBlock from './CodeBlock.vue';
import hljs from 'highlight.js'; import hljs from 'highlight.js';
import DOMPurify from 'dompurify';
function escapeHtml(unsafe) { function escapeHtml(unsafe) {
return unsafe return unsafe
.replace(/&/g, "&amp;") .replace(/&/g, "&amp;")

View File

@ -369,6 +369,10 @@ export default {
data() { data() {
return { return {
posts_headers : {
'accept': 'application/json',
'Content-Type': 'application/json'
},
host:"", host:"",
progress_visibility_val : true, progress_visibility_val : true,
progress_value : 0, progress_value : 0,
@ -521,7 +525,7 @@ export default {
onclosedatabase_selectorDialog(){this.database_selectorDialogVisible=false;}, onclosedatabase_selectorDialog(){this.database_selectorDialogVisible=false;},
async onvalidatedatabase_selectorChoice(choice){ async onvalidatedatabase_selectorChoice(choice){
this.database_selectorDialogVisible=false; this.database_selectorDialogVisible=false;
const res = await axios.post("/select_database",{"name": choice}); const res = await axios.post("/select_database", {"name": choice}, {headers: this.posts_headers});
if(res.status){ if(res.status){
console.log("Selected database") console.log("Selected database")
this.$store.state.config = await axios.get("/get_config"); this.$store.state.config = await axios.get("/get_config");
@ -697,7 +701,7 @@ export default {
await axios.post('/delete_discussion', { await axios.post('/delete_discussion', {
client_id: this.client_id, client_id: this.client_id,
id: id id: id
}) }, {headers: this.posts_headers})
this.loading = false this.loading = false
this.setDiscussionLoading(id, this.loading) this.setDiscussionLoading(id, this.loading)
} }
@ -716,7 +720,7 @@ export default {
client_id: this.client_id, client_id: this.client_id,
id: id, id: id,
title: new_title title: new_title
}) }, {headers: this.posts_headers})
this.loading = false this.loading = false
this.setDiscussionLoading(id, this.loading) this.setDiscussionLoading(id, this.loading)
if (res.status == 200) { if (res.status == 200) {
@ -740,7 +744,7 @@ export default {
const res = await axios.post('/make_title', { const res = await axios.post('/make_title', {
client_id: this.client_id, client_id: this.client_id,
id: id, id: id,
}) }, {headers: this.posts_headers})
console.log("Making title:",res) console.log("Making title:",res)
this.loading = false this.loading = false
@ -761,7 +765,11 @@ export default {
}, },
async delete_message(id) { async delete_message(id) {
try { try {
const res = await axios.get('/delete_message', { params: { client_id: this.client_id, id: id } }) console.log(typeof id)
console.log(typeof this.client_id)
console.log(id)
console.log(this.client_id)
const res = await axios.post('/delete_message', { client_id: this.client_id, id: id }, {headers: this.posts_headers})
if (res) { if (res) {
return res.data return res.data
@ -793,7 +801,7 @@ export default {
}, },
async message_rank_up(id) { async message_rank_up(id) {
try { try {
const res = await axios.get('/message_rank_up', { params: { client_id: this.client_id, id: id } }) const res = await axios.post('/message_rank_up', { params: { client_id: this.client_id, id: id } }, {headers: this.posts_headers})
if (res) { if (res) {
return res.data return res.data
@ -805,7 +813,7 @@ export default {
}, },
async message_rank_down(id) { async message_rank_down(id) {
try { try {
const res = await axios.get('/message_rank_down', { params: { client_id: this.client_id, id: id } }) const res = await axios.post('/message_rank_down', { params: { client_id: this.client_id, id: id } }, {headers: this.posts_headers})
if (res) { if (res) {
return res.data return res.data
@ -817,7 +825,7 @@ export default {
}, },
async edit_message(id, message, audio_url) { async edit_message(id, message, audio_url) {
try { try {
const res = await axios.get('/edit_message', { params: { client_id: this.client_id, id: id, message: message, metadata: {audio_url:audio_url} } }) const res = await axios.post('/edit_message', { params: { client_id: this.client_id, id: id, message: message, metadata: {audio_url:audio_url} } }, {headers: this.posts_headers})
if (res) { if (res) {
return res.data return res.data
@ -2118,6 +2126,7 @@ export default {
</script> </script>
<script setup> <script setup>
import Discussion from '../components/Discussion.vue' import Discussion from '../components/Discussion.vue'
import ChoiceDialog from '@/components/ChoiceDialog.vue' import ChoiceDialog from '@/components/ChoiceDialog.vue'
import ProgressBar from "@/components/ProgressBar.vue"; import ProgressBar from "@/components/ProgressBar.vue";