mirror of
https://github.com/ParisNeo/lollms-webui.git
synced 2024-12-24 06:36:37 +00:00
New model format
This commit is contained in:
parent
b05dde5477
commit
2d598cc5fe
55
app.py
55
app.py
@ -9,6 +9,13 @@
|
|||||||
# Made by the community for the community
|
# Made by the community for the community
|
||||||
######
|
######
|
||||||
|
|
||||||
|
__author__ = "parisneo"
|
||||||
|
__github__ = "https://github.com/nomic-ai/gpt4all-ui"
|
||||||
|
__copyright__ = "Copyright 2023, "
|
||||||
|
__license__ = "Apache 2.0"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
@ -40,9 +47,18 @@ class Gpt4AllWebUI(GPT4AllAPI):
|
|||||||
self.app = _app
|
self.app = _app
|
||||||
|
|
||||||
|
|
||||||
|
self.add_endpoint(
|
||||||
|
"/list_backends", "list_backends", self.list_backends, methods=["GET"]
|
||||||
|
)
|
||||||
self.add_endpoint(
|
self.add_endpoint(
|
||||||
"/list_models", "list_models", self.list_models, methods=["GET"]
|
"/list_models", "list_models", self.list_models, methods=["GET"]
|
||||||
)
|
)
|
||||||
|
self.add_endpoint(
|
||||||
|
"/list_personalities_languages", "list_personalities_languages", self.list_personalities_languages, methods=["GET"]
|
||||||
|
)
|
||||||
|
self.add_endpoint(
|
||||||
|
"/list_personalities_categories", "list_personalities_categories", self.list_personalities_categories, methods=["GET"]
|
||||||
|
)
|
||||||
self.add_endpoint(
|
self.add_endpoint(
|
||||||
"/list_personalities", "list_personalities", self.list_personalities, methods=["GET"]
|
"/list_personalities", "list_personalities", self.list_personalities, methods=["GET"]
|
||||||
)
|
)
|
||||||
@ -55,6 +71,9 @@ class Gpt4AllWebUI(GPT4AllAPI):
|
|||||||
"/list_discussions", "list_discussions", self.list_discussions, methods=["GET"]
|
"/list_discussions", "list_discussions", self.list_discussions, methods=["GET"]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
self.add_endpoint("/set_personality_language", "set_personality_language", self.set_personality_language, methods=["GET"])
|
||||||
|
self.add_endpoint("/set_personality_category", "set_personality_category", self.set_personality_category, methods=["GET"])
|
||||||
|
|
||||||
|
|
||||||
self.add_endpoint("/", "", self.index, methods=["GET"])
|
self.add_endpoint("/", "", self.index, methods=["GET"])
|
||||||
self.add_endpoint("/export_discussion", "export_discussion", self.export_discussion, methods=["GET"])
|
self.add_endpoint("/export_discussion", "export_discussion", self.export_discussion, methods=["GET"])
|
||||||
@ -116,14 +135,30 @@ class Gpt4AllWebUI(GPT4AllAPI):
|
|||||||
"/help", "help", self.help, methods=["GET"]
|
"/help", "help", self.help, methods=["GET"]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def list_backends(self):
|
||||||
|
backends_dir = Path('./pyGpt4All/backends') # replace with the actual path to the models folder
|
||||||
|
backends = [f.stem for f in backends_dir.glob('*.py') if f.name!="backend" and f.stem!="__init__"]
|
||||||
|
return jsonify(backends)
|
||||||
|
|
||||||
|
|
||||||
def list_models(self):
|
def list_models(self):
|
||||||
models_dir = Path('./models') # replace with the actual path to the models folder
|
models_dir = Path('./models')/self.config["backend"] # replace with the actual path to the models folder
|
||||||
models = [f.name for f in models_dir.glob('*.bin')]
|
models = [f.name for f in models_dir.glob('*.bin')]
|
||||||
return jsonify(models)
|
return jsonify(models)
|
||||||
|
|
||||||
|
|
||||||
|
def list_personalities_languages(self):
|
||||||
|
personalities_languages_dir = Path(f'./personalities') # replace with the actual path to the models folder
|
||||||
|
personalities_languages = [f.stem for f in personalities_languages_dir.iterdir() if f.is_dir()]
|
||||||
|
return jsonify(personalities_languages)
|
||||||
|
|
||||||
|
def list_personalities_categories(self):
|
||||||
|
personalities_categories_dir = Path(f'./personalities/{self.config["personality_language"]}') # replace with the actual path to the models folder
|
||||||
|
personalities_categories = [f.stem for f in personalities_categories_dir.iterdir() if f.is_dir()]
|
||||||
|
return jsonify(personalities_categories)
|
||||||
|
|
||||||
def list_personalities(self):
|
def list_personalities(self):
|
||||||
personalities_dir = Path('./personalities') # replace with the actual path to the models folder
|
personalities_dir = Path(f'./personalities/{self.config["personality_language"]}/{self.config["personality_category"]}') # replace with the actual path to the models folder
|
||||||
personalities = [f.stem for f in personalities_dir.glob('*.yaml')]
|
personalities = [f.stem for f in personalities_dir.glob('*.yaml')]
|
||||||
return jsonify(personalities)
|
return jsonify(personalities)
|
||||||
|
|
||||||
@ -145,6 +180,16 @@ class Gpt4AllWebUI(GPT4AllAPI):
|
|||||||
return jsonify(discussions)
|
return jsonify(discussions)
|
||||||
|
|
||||||
|
|
||||||
|
def set_personality_language(self):
|
||||||
|
lang = request.args.get('language')
|
||||||
|
self.config['personality_language'] = lang
|
||||||
|
return jsonify({'success':True})
|
||||||
|
|
||||||
|
def set_personality_category(self):
|
||||||
|
category = request.args.get('category')
|
||||||
|
self.config['personality_category'] = category
|
||||||
|
return jsonify({'success':True})
|
||||||
|
|
||||||
def add_endpoint(
|
def add_endpoint(
|
||||||
self,
|
self,
|
||||||
endpoint=None,
|
endpoint=None,
|
||||||
@ -247,7 +292,7 @@ class Gpt4AllWebUI(GPT4AllAPI):
|
|||||||
return Response(
|
return Response(
|
||||||
stream_with_context(
|
stream_with_context(
|
||||||
self.parse_to_prompt_stream(message, message_id)
|
self.parse_to_prompt_stream(message, message_id)
|
||||||
)
|
), content_type='text/plain; charset=utf-8'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -284,7 +329,7 @@ class Gpt4AllWebUI(GPT4AllAPI):
|
|||||||
for message in messages:
|
for message in messages:
|
||||||
message["content"] = markdown.markdown(message["content"])
|
message["content"] = markdown.markdown(message["content"])
|
||||||
|
|
||||||
return jsonify(messages)
|
return jsonify(messages), {'Content-Type': 'application/json; charset=utf-8'}
|
||||||
|
|
||||||
def delete_discussion(self):
|
def delete_discussion(self):
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
@ -470,7 +515,7 @@ if __name__ == "__main__":
|
|||||||
if arg_value is not None:
|
if arg_value is not None:
|
||||||
config[arg_name] = arg_value
|
config[arg_name] = arg_value
|
||||||
|
|
||||||
personality = load_config(f"personalities/{config['personality']}.yaml")
|
personality = load_config(f"personalities/{config['personality_language']}/{config['personality_category']}/{config['personality']}.yaml")
|
||||||
|
|
||||||
executor = ThreadPoolExecutor(max_workers=2)
|
executor = ThreadPoolExecutor(max_workers=2)
|
||||||
app.config['executor'] = executor
|
app.config['executor'] = executor
|
||||||
|
@ -5,9 +5,13 @@ debug: false
|
|||||||
n_threads: 8
|
n_threads: 8
|
||||||
host: localhost
|
host: localhost
|
||||||
language: en-US
|
language: en-US
|
||||||
|
# Supported backends are llamacpp and gpt-j
|
||||||
|
backend: llama_cpp
|
||||||
model: gpt4all-lora-quantized-ggml.bin
|
model: gpt4all-lora-quantized-ggml.bin
|
||||||
n_predict: 1024
|
n_predict: 1024
|
||||||
nb_messages_to_remember: 5
|
nb_messages_to_remember: 5
|
||||||
|
personality_language: english
|
||||||
|
personality_category: general
|
||||||
personality: gpt4all_chatbot
|
personality: gpt4all_chatbot
|
||||||
port: 9600
|
port: 9600
|
||||||
repeat_last_n: 40
|
repeat_last_n: 40
|
||||||
|
@ -1 +1,4 @@
|
|||||||
Here you can drop your models
|
Here you can drop your models depending on the selected backend
|
||||||
|
Currently, supported backends are:
|
||||||
|
- llamacpp
|
||||||
|
- gpt-j
|
@ -1,47 +0,0 @@
|
|||||||
# GPT4All Chatbot conditionning file
|
|
||||||
# Author : @ParisNeo
|
|
||||||
# Version : 1.0
|
|
||||||
# Description :
|
|
||||||
# An NLP needs conditionning to instruct it to be whatever we want it to be.
|
|
||||||
# This file is used by the GPT4All web ui to condition the personality of the model you are
|
|
||||||
# talking to.
|
|
||||||
|
|
||||||
# Name of the personality
|
|
||||||
name: gpt4all
|
|
||||||
|
|
||||||
# Name of the user
|
|
||||||
user_name: user
|
|
||||||
|
|
||||||
# Language (see the list of supported languages here : https://github.com/ParisNeo/GPT4All_Personalities/blob/main/README.md)
|
|
||||||
language: "en_XX"
|
|
||||||
|
|
||||||
# Category
|
|
||||||
category: "General"
|
|
||||||
|
|
||||||
# Personality description:
|
|
||||||
personality_description: |
|
|
||||||
This personality is a helpful and Kind AI ready to help you solve your problems
|
|
||||||
|
|
||||||
# The conditionning instructions sent to eh model at the start of the discussion
|
|
||||||
personality_conditionning: |
|
|
||||||
GPT4All is a smart and helpful AI chat bot built by Nomic-AI. It can generate stories on demand.
|
|
||||||
|
|
||||||
#Welcome message to be sent to the user when a new discussion is started
|
|
||||||
welcome_message: "Welcome! I am GPT4All A free and open discussion AI. What can I do for you today?"
|
|
||||||
|
|
||||||
# This prefix is added at the beginning of any message input by the user
|
|
||||||
user_message_prefix: "user: "
|
|
||||||
|
|
||||||
# A text to put between user and chatbot messages
|
|
||||||
link_text: "\n"
|
|
||||||
|
|
||||||
# This prefix is added at the beginning of any message output by the ai
|
|
||||||
ai_message_prefix: "gpt4all: "
|
|
||||||
|
|
||||||
# Here is the list of extensions this personality requires
|
|
||||||
dependencies: []
|
|
||||||
|
|
||||||
# Some personalities need a disclaimer to warn the user of potential harm that can be caused by the AI
|
|
||||||
# for example, for medical assistants, it is important to tell the user to be careful and not use medication
|
|
||||||
# without advise from a real docor.
|
|
||||||
disclaimer: ""
|
|
@ -11,11 +11,15 @@ import gc
|
|||||||
import sys
|
import sys
|
||||||
from queue import Queue
|
from queue import Queue
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from pyllamacpp.model import Model
|
|
||||||
from pyGpt4All.db import DiscussionsDB
|
from pyGpt4All.db import DiscussionsDB
|
||||||
|
from pyGpt4All.backends import BACKENDS_LIST
|
||||||
|
__author__ = "parisneo"
|
||||||
|
__github__ = "https://github.com/nomic-ai/gpt4all-ui"
|
||||||
|
__copyright__ = "Copyright 2023, "
|
||||||
|
__license__ = "Apache 2.0"
|
||||||
|
|
||||||
class GPT4AllAPI():
|
class GPT4AllAPI():
|
||||||
def __init__(self, config:dict, personality:dict, config_file_path) -> None:
|
def __init__(self, config:dict, personality:dict, config_file_path:str) -> None:
|
||||||
self.config = config
|
self.config = config
|
||||||
self.personality = personality
|
self.personality = personality
|
||||||
self.config_file_path = config_file_path
|
self.config_file_path = config_file_path
|
||||||
@ -38,6 +42,9 @@ class GPT4AllAPI():
|
|||||||
# This is used to keep track of messages
|
# This is used to keep track of messages
|
||||||
self.full_message_list = []
|
self.full_message_list = []
|
||||||
|
|
||||||
|
# Select backend
|
||||||
|
self.backend = BACKENDS_LIST[self.config["backend"]]
|
||||||
|
|
||||||
# Build chatbot
|
# Build chatbot
|
||||||
self.chatbot_bindings = self.create_chatbot()
|
self.chatbot_bindings = self.create_chatbot()
|
||||||
print("Chatbot created successfully")
|
print("Chatbot created successfully")
|
||||||
@ -66,11 +73,7 @@ class GPT4AllAPI():
|
|||||||
|
|
||||||
def create_chatbot(self):
|
def create_chatbot(self):
|
||||||
try:
|
try:
|
||||||
return Model(
|
return self.backend(self.config)
|
||||||
ggml_model=f"./models/{self.config['model']}",
|
|
||||||
n_ctx=self.config['ctx_size'],
|
|
||||||
seed=self.config['seed'],
|
|
||||||
)
|
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
print(f"Exception {ex}")
|
print(f"Exception {ex}")
|
||||||
return None
|
return None
|
||||||
|
6
pyGpt4All/backends/__init__.py
Normal file
6
pyGpt4All/backends/__init__.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
from pyGpt4All.backends.llamacpp import LLAMACPP
|
||||||
|
from pyGpt4All.backends.gpt_j import GPT_J
|
||||||
|
BACKENDS_LIST={
|
||||||
|
"llama_cpp":LLAMACPP,
|
||||||
|
"gpt_j":GPT_J
|
||||||
|
}
|
37
pyGpt4All/backends/backend.py
Normal file
37
pyGpt4All/backends/backend.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
######
|
||||||
|
# Project : GPT4ALL-UI
|
||||||
|
# File : backend.py
|
||||||
|
# Author : ParisNeo with the help of the community
|
||||||
|
# Supported by Nomic-AI
|
||||||
|
# Licence : Apache 2.0
|
||||||
|
# Description :
|
||||||
|
# This is an interface class for GPT4All-ui backends.
|
||||||
|
######
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Callable
|
||||||
|
|
||||||
|
__author__ = "parisneo"
|
||||||
|
__github__ = "https://github.com/nomic-ai/gpt4all-ui"
|
||||||
|
__copyright__ = "Copyright 2023, "
|
||||||
|
__license__ = "Apache 2.0"
|
||||||
|
|
||||||
|
|
||||||
|
class GPTBackend:
|
||||||
|
def __init__(self, config:dict) -> None:
|
||||||
|
self.config = config
|
||||||
|
def generate(self,
|
||||||
|
prompt:str,
|
||||||
|
n_predict: int = 128,
|
||||||
|
new_text_callback: Callable[[str], None] = None,
|
||||||
|
verbose: bool = False,
|
||||||
|
**gpt_params ):
|
||||||
|
"""Generates text out of a prompt
|
||||||
|
This should ber implemented by child class
|
||||||
|
|
||||||
|
Args:
|
||||||
|
prompt (str): The prompt to use for generation
|
||||||
|
n_predict (int, optional): Number of tokens to prodict. Defaults to 128.
|
||||||
|
new_text_callback (Callable[[str], None], optional): A callback function that is called everytime a new text element is generated. Defaults to None.
|
||||||
|
verbose (bool, optional): If true, the code will spit many informations about the generation process. Defaults to False.
|
||||||
|
"""
|
||||||
|
pass
|
60
pyGpt4All/backends/gpt_j.py
Normal file
60
pyGpt4All/backends/gpt_j.py
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
######
|
||||||
|
# Project : GPT4ALL-UI
|
||||||
|
# File : backend.py
|
||||||
|
# Author : ParisNeo with the help of the community
|
||||||
|
# Supported by Nomic-AI
|
||||||
|
# Licence : Apache 2.0
|
||||||
|
# Description :
|
||||||
|
# This is an interface class for GPT4All-ui backends.
|
||||||
|
######
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Callable
|
||||||
|
from gpt4allj import Model
|
||||||
|
from pyGpt4All.backends.backend import GPTBackend
|
||||||
|
|
||||||
|
__author__ = "parisneo"
|
||||||
|
__github__ = "https://github.com/nomic-ai/gpt4all-ui"
|
||||||
|
__copyright__ = "Copyright 2023, "
|
||||||
|
__license__ = "Apache 2.0"
|
||||||
|
|
||||||
|
|
||||||
|
class GPT_J(GPTBackend):
|
||||||
|
def __init__(self, config:dict) -> None:
|
||||||
|
"""Builds a GPT-J backend
|
||||||
|
|
||||||
|
Args:
|
||||||
|
config (dict): The configuration file
|
||||||
|
"""
|
||||||
|
super().__init__(config)
|
||||||
|
self.config = config
|
||||||
|
self.model = Model(
|
||||||
|
ggml_model=f"./models/gptj/{self.config['model']}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def generate(self,
|
||||||
|
prompt:str,
|
||||||
|
n_predict: int = 128,
|
||||||
|
new_text_callback: Callable[[str], None] = bool,
|
||||||
|
verbose: bool = False,
|
||||||
|
**gpt_params ):
|
||||||
|
"""Generates text out of a prompt
|
||||||
|
|
||||||
|
Args:
|
||||||
|
prompt (str): The prompt to use for generation
|
||||||
|
n_predict (int, optional): Number of tokens to prodict. Defaults to 128.
|
||||||
|
new_text_callback (Callable[[str], None], optional): A callback function that is called everytime a new text element is generated. Defaults to None.
|
||||||
|
verbose (bool, optional): If true, the code will spit many informations about the generation process. Defaults to False.
|
||||||
|
"""
|
||||||
|
self.model.generate(
|
||||||
|
prompt,
|
||||||
|
new_text_callback=new_text_callback,
|
||||||
|
n_predict=n_predict,
|
||||||
|
temp=self.config['temp'],
|
||||||
|
top_k=self.config['top_k'],
|
||||||
|
top_p=self.config['top_p'],
|
||||||
|
repeat_penalty=self.config['repeat_penalty'],
|
||||||
|
repeat_last_n = self.config['repeat_last_n'],
|
||||||
|
n_threads=self.config['n_threads'],
|
||||||
|
verbose=verbose
|
||||||
|
)
|
62
pyGpt4All/backends/llamacpp.py
Normal file
62
pyGpt4All/backends/llamacpp.py
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
######
|
||||||
|
# Project : GPT4ALL-UI
|
||||||
|
# File : backend.py
|
||||||
|
# Author : ParisNeo with the help of the community
|
||||||
|
# Supported by Nomic-AI
|
||||||
|
# Licence : Apache 2.0
|
||||||
|
# Description :
|
||||||
|
# This is an interface class for GPT4All-ui backends.
|
||||||
|
######
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Callable
|
||||||
|
from pyllamacpp.model import Model
|
||||||
|
from pyGpt4All.backends.backend import GPTBackend
|
||||||
|
|
||||||
|
__author__ = "parisneo"
|
||||||
|
__github__ = "https://github.com/nomic-ai/gpt4all-ui"
|
||||||
|
__copyright__ = "Copyright 2023, "
|
||||||
|
__license__ = "Apache 2.0"
|
||||||
|
|
||||||
|
|
||||||
|
class LLAMACPP(GPTBackend):
|
||||||
|
def __init__(self, config:dict) -> None:
|
||||||
|
"""Builds a LLAMACPP backend
|
||||||
|
|
||||||
|
Args:
|
||||||
|
config (dict): The configuration file
|
||||||
|
"""
|
||||||
|
super().__init__(config)
|
||||||
|
|
||||||
|
self.model = Model(
|
||||||
|
ggml_model=f"./models/llamacpp/{self.config['model']}",
|
||||||
|
n_ctx=self.config['ctx_size'],
|
||||||
|
seed=self.config['seed'],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def generate(self,
|
||||||
|
prompt:str,
|
||||||
|
n_predict: int = 128,
|
||||||
|
new_text_callback: Callable[[str], None] = bool,
|
||||||
|
verbose: bool = False,
|
||||||
|
**gpt_params ):
|
||||||
|
"""Generates text out of a prompt
|
||||||
|
|
||||||
|
Args:
|
||||||
|
prompt (str): The prompt to use for generation
|
||||||
|
n_predict (int, optional): Number of tokens to prodict. Defaults to 128.
|
||||||
|
new_text_callback (Callable[[str], None], optional): A callback function that is called everytime a new text element is generated. Defaults to None.
|
||||||
|
verbose (bool, optional): If true, the code will spit many informations about the generation process. Defaults to False.
|
||||||
|
"""
|
||||||
|
self.model.generate(
|
||||||
|
prompt,
|
||||||
|
new_text_callback=new_text_callback,
|
||||||
|
n_predict=n_predict,
|
||||||
|
temp=self.config['temp'],
|
||||||
|
top_k=self.config['top_k'],
|
||||||
|
top_p=self.config['top_p'],
|
||||||
|
repeat_penalty=self.config['repeat_penalty'],
|
||||||
|
repeat_last_n = self.config['repeat_last_n'],
|
||||||
|
n_threads=self.config['n_threads'],
|
||||||
|
verbose=verbose
|
||||||
|
)
|
@ -11,6 +11,11 @@
|
|||||||
######
|
######
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
|
__author__ = "parisneo"
|
||||||
|
__github__ = "https://github.com/nomic-ai/gpt4all-ui"
|
||||||
|
__copyright__ = "Copyright 2023, "
|
||||||
|
__license__ = "Apache 2.0"
|
||||||
|
|
||||||
def load_config(file_path):
|
def load_config(file_path):
|
||||||
with open(file_path, 'r') as stream:
|
with open(file_path, 'r') as stream:
|
||||||
config = yaml.safe_load(stream)
|
config = yaml.safe_load(stream)
|
||||||
|
@ -1,5 +1,12 @@
|
|||||||
|
|
||||||
import sqlite3
|
import sqlite3
|
||||||
|
|
||||||
|
__author__ = "parisneo"
|
||||||
|
__github__ = "https://github.com/nomic-ai/gpt4all-ui"
|
||||||
|
__copyright__ = "Copyright 2023, "
|
||||||
|
__license__ = "Apache 2.0"
|
||||||
|
|
||||||
|
|
||||||
# =================================== Database ==================================================================
|
# =================================== Database ==================================================================
|
||||||
class DiscussionsDB:
|
class DiscussionsDB:
|
||||||
MSG_TYPE_NORMAL = 0
|
MSG_TYPE_NORMAL = 0
|
||||||
@ -13,6 +20,17 @@ class DiscussionsDB:
|
|||||||
create database schema
|
create database schema
|
||||||
"""
|
"""
|
||||||
db_version = 2
|
db_version = 2
|
||||||
|
# Verify encoding and change it if it is not complient
|
||||||
|
with sqlite3.connect(self.db_path) as conn:
|
||||||
|
# Execute a PRAGMA statement to get the current encoding of the database
|
||||||
|
cur = conn.execute('PRAGMA encoding')
|
||||||
|
current_encoding = cur.fetchone()[0]
|
||||||
|
|
||||||
|
if current_encoding != 'UTF-8':
|
||||||
|
# The current encoding is not UTF-8, so we need to change it
|
||||||
|
print(f"The current encoding is {current_encoding}, changing to UTF-8...")
|
||||||
|
conn.execute('PRAGMA encoding = "UTF-8"')
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
print("Checking discussions database...")
|
print("Checking discussions database...")
|
||||||
with sqlite3.connect(self.db_path) as conn:
|
with sqlite3.connect(self.db_path) as conn:
|
||||||
|
@ -5,6 +5,11 @@
|
|||||||
# it gives your code access to the model, the callback functions, the model conditionning etc
|
# it gives your code access to the model, the callback functions, the model conditionning etc
|
||||||
from config import load_config, save_config
|
from config import load_config, save_config
|
||||||
|
|
||||||
|
__author__ = "parisneo"
|
||||||
|
__github__ = "https://github.com/nomic-ai/gpt4all-ui"
|
||||||
|
__copyright__ = "Copyright 2023, "
|
||||||
|
__license__ = "Apache 2.0"
|
||||||
|
|
||||||
class Extension():
|
class Extension():
|
||||||
def __init__(self, metadata_file_path:str, app) -> None:
|
def __init__(self, metadata_file_path:str, app) -> None:
|
||||||
self.app = app
|
self.app = app
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
flask
|
flask
|
||||||
nomic
|
nomic
|
||||||
pytest
|
pytest
|
||||||
pyllamacpp==1.0.6
|
|
||||||
pyyaml
|
pyyaml
|
||||||
markdown
|
markdown
|
||||||
|
pyllamacpp==1.0.6
|
||||||
|
gpt4allj
|
||||||
|
7
requirements_dev.txt
Normal file
7
requirements_dev.txt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
flask
|
||||||
|
nomic
|
||||||
|
pytest
|
||||||
|
pyyaml
|
||||||
|
markdown
|
||||||
|
pyllamacpp==1.0.6
|
||||||
|
gpt4allj
|
35
setup.py
Normal file
35
setup.py
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
from pathlib import Path
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
|
import setuptools
|
||||||
|
|
||||||
|
with open("README.md", "r") as fh:
|
||||||
|
long_description = fh.read()
|
||||||
|
|
||||||
|
|
||||||
|
def read_requirements(path: Union[str, Path]):
|
||||||
|
with open(path, "r") as file:
|
||||||
|
return file.read().splitlines()
|
||||||
|
|
||||||
|
|
||||||
|
requirements = read_requirements("requirements.txt")
|
||||||
|
requirements_dev = read_requirements("requirements_dev.txt")
|
||||||
|
|
||||||
|
setuptools.setup(
|
||||||
|
name="GPT4Allui",
|
||||||
|
version="0.0.5",
|
||||||
|
author="Saifeddine ALOUI",
|
||||||
|
author_email="aloui.saifeddine@gmail.com",
|
||||||
|
description="A web ui for running chat models with different backends. Supports multiple personalities and extensions.",
|
||||||
|
long_description=long_description,
|
||||||
|
long_description_content_type="text/markdown",
|
||||||
|
url="https://github.com/nomic-ai/gpt4all-ui",
|
||||||
|
packages=setuptools.find_packages(),
|
||||||
|
install_requires=requirements,
|
||||||
|
extras_require={"dev": requirements_dev},
|
||||||
|
classifiers=[
|
||||||
|
"Programming Language :: Python :: 3.10",
|
||||||
|
"License :: OSI Approved :: Apache 2.0 License",
|
||||||
|
"Operating System :: OS Independent",
|
||||||
|
],
|
||||||
|
)
|
@ -93,7 +93,7 @@ function update_main(){
|
|||||||
else{
|
else{
|
||||||
// For the other enrtries, these are just the text of the chatbot
|
// For the other enrtries, these are just the text of the chatbot
|
||||||
for (const char of text) {
|
for (const char of text) {
|
||||||
txt = hiddenElement.innerHTML;
|
txt = bot_msg.hiddenElement.innerHTML;
|
||||||
if (char != '\f') {
|
if (char != '\f') {
|
||||||
txt += char
|
txt += char
|
||||||
bot_msg.hiddenElement.innerHTML = txt;
|
bot_msg.hiddenElement.innerHTML = txt;
|
||||||
|
@ -3,7 +3,7 @@ fetch('/settings')
|
|||||||
.then(response => response.text())
|
.then(response => response.text())
|
||||||
.then(html => {
|
.then(html => {
|
||||||
document.getElementById('settings').innerHTML = html;
|
document.getElementById('settings').innerHTML = html;
|
||||||
|
backendInput = document.getElementById('backend');
|
||||||
modelInput = document.getElementById('model');
|
modelInput = document.getElementById('model');
|
||||||
personalityInput = document.getElementById('personalities');
|
personalityInput = document.getElementById('personalities');
|
||||||
languageInput = document.getElementById('language');
|
languageInput = document.getElementById('language');
|
||||||
@ -54,6 +54,7 @@ fetch('/settings')
|
|||||||
.then((response) => response.json())
|
.then((response) => response.json())
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
console.log(data);
|
console.log(data);
|
||||||
|
backendInput.value = data["backend"]
|
||||||
modelInput.value = data["model"]
|
modelInput.value = data["model"]
|
||||||
personalityInput.value = data["personality"]
|
personalityInput.value = data["personality"]
|
||||||
languageInput.value = data["language"]
|
languageInput.value = data["language"]
|
||||||
@ -89,6 +90,7 @@ fetch('/settings')
|
|||||||
// Get form values and put them in an object
|
// Get form values and put them in an object
|
||||||
const formValues = {
|
const formValues = {
|
||||||
seed: seedInput.value,
|
seed: seedInput.value,
|
||||||
|
backend: backendInput.value,
|
||||||
model: modelInput.value,
|
model: modelInput.value,
|
||||||
personality: personalityInput.value,
|
personality: personalityInput.value,
|
||||||
language: languageInput.value,
|
language: languageInput.value,
|
||||||
@ -129,8 +131,39 @@ fetch('/settings')
|
|||||||
|
|
||||||
function populate_models(){
|
function populate_models(){
|
||||||
// Get a reference to the <select> element
|
// Get a reference to the <select> element
|
||||||
const selectElement = document.getElementById('model');
|
const selectBackend = document.getElementById('backend');
|
||||||
|
const selectModel = document.getElementById('model');
|
||||||
|
|
||||||
|
const selectPersonalityLanguage = document.getElementById('personalities_language');
|
||||||
|
const selectPersonalityCategory = document.getElementById('personalities_category');
|
||||||
|
const selectPersonality = document.getElementById('personalities');
|
||||||
|
|
||||||
|
function populate_backends(){
|
||||||
|
// Fetch the list of .bin files from the models subfolder
|
||||||
|
fetch('/list_backends')
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (Array.isArray(data)) {
|
||||||
|
// data is an array
|
||||||
|
data.forEach(filename => {
|
||||||
|
const optionElement = document.createElement('option');
|
||||||
|
optionElement.value = filename;
|
||||||
|
optionElement.textContent = filename;
|
||||||
|
selectBackend.appendChild(optionElement);
|
||||||
|
});
|
||||||
|
|
||||||
|
// fetch('/get_args')
|
||||||
|
// .then(response=> response.json())
|
||||||
|
// .then(data=>{
|
||||||
|
|
||||||
|
// })
|
||||||
|
} else {
|
||||||
|
console.error('Expected an array, but received:', data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function populate_models(){
|
||||||
// Fetch the list of .bin files from the models subfolder
|
// Fetch the list of .bin files from the models subfolder
|
||||||
fetch('/list_models')
|
fetch('/list_models')
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
@ -141,7 +174,7 @@ function populate_models(){
|
|||||||
const optionElement = document.createElement('option');
|
const optionElement = document.createElement('option');
|
||||||
optionElement.value = filename;
|
optionElement.value = filename;
|
||||||
optionElement.textContent = filename;
|
optionElement.textContent = filename;
|
||||||
selectElement.appendChild(optionElement);
|
selectModel.appendChild(optionElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
// fetch('/get_args')
|
// fetch('/get_args')
|
||||||
@ -153,30 +186,109 @@ function populate_models(){
|
|||||||
console.error('Expected an array, but received:', data);
|
console.error('Expected an array, but received:', data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
function populate_personalities_languages(){
|
||||||
|
selectPersonalityLanguage.innerHTML=""
|
||||||
|
// Fetch the list of .yaml files from the models subfolder
|
||||||
|
fetch('/list_personalities_languages')
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (Array.isArray(data)) {
|
||||||
|
// data is an array
|
||||||
|
data.forEach(filename => {
|
||||||
|
const optionElement = document.createElement('option');
|
||||||
|
optionElement.value = filename;
|
||||||
|
optionElement.textContent = filename;
|
||||||
|
selectPersonalityLanguage.appendChild(optionElement);
|
||||||
|
});
|
||||||
|
|
||||||
|
// fetch('/get_args')
|
||||||
|
// .then(response=> response.json())
|
||||||
|
// .then(data=>{
|
||||||
|
|
||||||
|
// })
|
||||||
|
} else {
|
||||||
|
console.error('Expected an array, but received:', data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function populate_personalities_categories(){
|
||||||
|
selectPersonalityCategory.innerHTML=""
|
||||||
|
// Fetch the list of .yaml files from the models subfolder
|
||||||
|
fetch('/list_personalities_categories')
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (Array.isArray(data)) {
|
||||||
|
// data is an array
|
||||||
|
data.forEach(filename => {
|
||||||
|
const optionElement = document.createElement('option');
|
||||||
|
optionElement.value = filename;
|
||||||
|
optionElement.textContent = filename;
|
||||||
|
selectPersonalityCategory.appendChild(optionElement);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.error('Expected an array, but received:', data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function populate_personalities(){
|
||||||
|
selectPersonality.innerHTML=""
|
||||||
// Fetch the list of .yaml files from the models subfolder
|
// Fetch the list of .yaml files from the models subfolder
|
||||||
fetch('/list_personalities')
|
fetch('/list_personalities')
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
if (Array.isArray(data)) {
|
if (Array.isArray(data)) {
|
||||||
// data is an array
|
// data is an array
|
||||||
const selectElement = document.getElementById('personalities');
|
|
||||||
data.forEach(filename => {
|
data.forEach(filename => {
|
||||||
const optionElement = document.createElement('option');
|
const optionElement = document.createElement('option');
|
||||||
optionElement.value = filename;
|
optionElement.value = filename;
|
||||||
optionElement.textContent = filename;
|
optionElement.textContent = filename;
|
||||||
selectElement.appendChild(optionElement);
|
selectPersonality.appendChild(optionElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
// fetch('/get_args')
|
|
||||||
// .then(response=> response.json())
|
|
||||||
// .then(data=>{
|
|
||||||
|
|
||||||
// })
|
|
||||||
} else {
|
} else {
|
||||||
console.error('Expected an array, but received:', data);
|
console.error('Expected an array, but received:', data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function set_personality_language(lang, callback) {
|
||||||
|
fetch(`/set_personality_language?language=${lang}`)
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
callback(data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Example usage: call another function after set_personality_language returns
|
||||||
|
selectPersonalityLanguage.addEventListener('click', function() {
|
||||||
|
set_personality_language(selectPersonalityLanguage.value, function(data) {
|
||||||
|
console.log('Response received:', data);
|
||||||
|
populate_personalities_categories();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function set_personality_category(category, callback) {
|
||||||
|
fetch(`/set_personality_category?category=${category}`)
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
callback()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Example usage: call another function after set_personality_category returns
|
||||||
|
selectPersonalityCategory.addEventListener('click', function() {
|
||||||
|
set_personality_category(selectPersonalityCategory.value, function(data) {
|
||||||
|
console.log('Response received:', data);
|
||||||
|
populate_personalities();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
populate_backends()
|
||||||
|
populate_models()
|
||||||
|
populate_personalities_languages()
|
||||||
|
populate_personalities_categories()
|
||||||
|
populate_personalities()
|
||||||
|
|
||||||
// Fetch the list of .yaml files from the models subfolder
|
// Fetch the list of .yaml files from the models subfolder
|
||||||
fetch('/list_languages')
|
fetch('/list_languages')
|
||||||
@ -184,19 +296,13 @@ function populate_models(){
|
|||||||
.then(data => {
|
.then(data => {
|
||||||
if (Array.isArray(data)) {
|
if (Array.isArray(data)) {
|
||||||
// data is an array
|
// data is an array
|
||||||
const selectElement = document.getElementById('language');
|
const selectLanguage = document.getElementById('language');
|
||||||
data.forEach(row => {
|
data.forEach(row => {
|
||||||
const optionElement = document.createElement('option');
|
const optionElement = document.createElement('option');
|
||||||
optionElement.value = row.value;
|
optionElement.value = row.value;
|
||||||
optionElement.innerHTML = row.label;
|
optionElement.innerHTML = row.label;
|
||||||
selectElement.appendChild(optionElement);
|
selectLanguage.appendChild(optionElement);
|
||||||
});
|
});
|
||||||
|
|
||||||
// fetch('/get_args')
|
|
||||||
// .then(response=> response.json())
|
|
||||||
// .then(data=>{
|
|
||||||
|
|
||||||
// })
|
|
||||||
} else {
|
} else {
|
||||||
console.error('Expected an array, but received:', data);
|
console.error('Expected an array, but received:', data);
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,25 @@
|
|||||||
<div class="h-full overflow-y-auto">
|
<div class="h-full overflow-y-auto">
|
||||||
<form id="model-params-form" class="bg-gray-50 dark:bg-gray-700 shadow-md rounded px-8 py-8 pt-6 pb-8 mb-4 text-black dark:text-white">
|
<form id="model-params-form" class="bg-gray-50 dark:bg-gray-700 shadow-md rounded px-8 py-8 pt-6 pb-8 mb-4 text-black dark:text-white">
|
||||||
|
<div class="mb-4 flex-row">
|
||||||
|
<label class="font-bold" for="model">Backend</label>
|
||||||
|
<select class="bg-gray-200 dark:bg-gray-700 w-96 shadow appearance-none border rounded py-2 px-3 leading-tight focus:outline-none focus:shadow-outline" id="backend" name="backend">
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
<div class="mb-4 flex-row">
|
<div class="mb-4 flex-row">
|
||||||
<label class="font-bold" for="model">Model</label>
|
<label class="font-bold" for="model">Model</label>
|
||||||
<select class="bg-gray-200 dark:bg-gray-700 w-96 shadow appearance-none border rounded py-2 px-3 leading-tight focus:outline-none focus:shadow-outline" id="model" name="model">
|
<select class="bg-gray-200 dark:bg-gray-700 w-96 shadow appearance-none border rounded py-2 px-3 leading-tight focus:outline-none focus:shadow-outline" id="model" name="model">
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="mb-4 flex-row">
|
||||||
|
<label class="font-bold mb-2" for="model">Personalities Languages</label>
|
||||||
|
<select class="bg-gray-200 dark:bg-gray-700 shadow appearance-none border rounded py-2 px-3 leading-tight focus:outline-none focus:shadow-outline" id="personalities_language" name="personalities_language" value="English">
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="mb-4 flex-row">
|
||||||
|
<label class="font-bold mb-2" for="model">Personalities Category</label>
|
||||||
|
<select class="bg-gray-200 dark:bg-gray-700 shadow appearance-none border rounded py-2 px-3 leading-tight focus:outline-none focus:shadow-outline" id="personalities_category" name="personalities_category" value="general">
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
<div class="mb-4 flex-row">
|
<div class="mb-4 flex-row">
|
||||||
<label class="font-bold mb-2" for="model">Personalities</label>
|
<label class="font-bold mb-2" for="model">Personalities</label>
|
||||||
<select class="bg-gray-200 dark:bg-gray-700 shadow appearance-none border rounded py-2 px-3 leading-tight focus:outline-none focus:shadow-outline" id="personalities" name="personalities" value="gpt4all_chatbot.yaml">
|
<select class="bg-gray-200 dark:bg-gray-700 shadow appearance-none border rounded py-2 px-3 leading-tight focus:outline-none focus:shadow-outline" id="personalities" name="personalities" value="gpt4all_chatbot.yaml">
|
||||||
|
@ -238,18 +238,15 @@ if not exist \models (
|
|||||||
md \models
|
md \models
|
||||||
)
|
)
|
||||||
|
|
||||||
if not exist ./models/gpt4all-lora-quantized-ggml.bin (
|
if not exist ./models/llamacpp/gpt4all-lora-quantized-ggml.bin (
|
||||||
echo.
|
echo.
|
||||||
choice /C YNB /M "The default model file (gpt4all-lora-quantized-ggml.bin) does not exist. Do you want to download it? Press B to download it with a browser (faster)."
|
choice /C YNB /M "The default model file (gpt4all-lora-quantized-ggml.bin) does not exist. Do you want to download it? Press B to download it with a browser (faster)."
|
||||||
if errorlevel 3 goto DOWNLOAD_WITH_BROWSER
|
if errorlevel 3 goto DOWNLOAD_WITH_BROWSER
|
||||||
if errorlevel 2 goto DOWNLOAD_SKIP
|
if errorlevel 2 goto DOWNLOAD_SKIP
|
||||||
if errorlevel 1 goto MODEL_DOWNLOAD
|
if errorlevel 1 goto MODEL_DOWNLOAD
|
||||||
) ELSE (
|
) ELSE (
|
||||||
echo.
|
echo Model already installed
|
||||||
choice /C YNB /M "The default model file (gpt4all-lora-quantized-ggml.bin) already exists. Do you want to replace it? Press B to download it with a browser (faster)."
|
goto CONTINUE
|
||||||
if errorlevel 3 goto DOWNLOAD_WITH_BROWSER
|
|
||||||
if errorlevel 2 goto DOWNLOAD_SKIP
|
|
||||||
if errorlevel 1 goto MODEL_DOWNLOAD
|
|
||||||
)
|
)
|
||||||
|
|
||||||
:DOWNLOAD_WITH_BROWSER
|
:DOWNLOAD_WITH_BROWSER
|
||||||
|
Loading…
Reference in New Issue
Block a user