Skip to content

Commit

Permalink
Enhanced code and added new tools
Browse files Browse the repository at this point in the history
  • Loading branch information
ParisNeo committed Dec 4, 2023
1 parent bae2a71 commit dc0c6a6
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 412 deletions.
43 changes: 30 additions & 13 deletions configs/config.yaml
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
# =================== Lord Of Large Language Models Configuration file ===========================
version: 27
version: 30
binding_name: null
model_name: null

# Enables gpu usage
enable_gpu: true


# Host information
host: localhost
port: 9601
port: 9600

# Genreration parameters
discussion_prompt_separator: "!@>"
seed: -1
n_predict: 1024
ctx_size: 4048
ctx_size: 4084
min_n_predict: 256
temperature: 0.9
top_k: 50
Expand All @@ -29,25 +28,43 @@ personalities: ["generic/lollms"]
active_personality_id: 0
override_personality_model_parameters: false #if true the personality parameters are overriden by those of the configuration (may affect personality behaviour)

# Extensions
extensions: []

# User infos
user_name: user
user_description: ""
use_user_name_in_discussions: false
user_avatar: default_user
user_avatar: default_user.svg
use_user_informations_in_discussion: false

# UI parameters
db_path: database.db

# Automatic update
auto_update: false
# Automatic updates
debug: False
auto_update: true
auto_save: true
debug: false
auto_title: false
# Enables gpu usage
enable_gpu: true
# Automatically open the browser
auto_show_browser: true

# Audio
audio_in_language: 'en-US'
audio_out_voice: null
auto_speak: false
audio_pitch: 1
audio_auto_send_input: true
audio_silenceTimer: 5000

# Data vectorization
use_discussions_history: false # Activate vectorizing previous conversations
summerize_discussion: false # activate discussion summary (better but adds computation time)
max_summary_size: 512 # in tokens
data_vectorization_visualize_on_vectorization: false
use_files: true # Activate using files
data_vectorization_visualize_on_vectorization: false # if active, the vectorizer wil lshow data whenever index is called
data_vectorization_activate: true # To activate/deactivate data vectorization
data_vectorization_method: "ftidf_vectorizer" #"model_embedding" or "ftidf_vectorizer"
data_vectorization_method: "tfidf_vectorizer" #"model_embedding" or "tfidf_vectorizer"
data_visualization_method: "PCA" #"PCA" or "TSNE"
data_vectorization_save_db: False # For each new session, new files
data_vectorization_chunk_size: 512 # chunk size
Expand Down
68 changes: 63 additions & 5 deletions lollms/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@
from typing import Callable
from ascii_colors import ASCIIColors
from pathlib import Path

from datetime import datetime
from functools import partial
import subprocess
import importlib
import sys

class LollmsApplication:
def __init__(
self,
Expand Down Expand Up @@ -121,10 +124,65 @@ def build_long_term_skills_memory(self):
)
return self.long_term_memory

def learn_from_discussion(self, discussion):
learned_skill = self.model.generate(f"{discussion}\n\n!@>What should we learn from this discussion?!@>Summerizer: Here is a summary of the most important informations extracted from the discussion:\n",)
return learned_skill

def process_chunk(
self,
chunk:str,
message_type,
parameters:dict=None,
metadata:list=None,
personality=None
):

pass

def default_callback(self, chunk, type, generation_infos:dict):
if generation_infos["nb_received_tokens"]==0:
self.start_time = datetime.now()
dt =(datetime.now() - self.start_time).seconds
if dt==0:
dt=1
spd = generation_infos["nb_received_tokens"]/dt
ASCIIColors.green(f"Received {generation_infos['nb_received_tokens']} tokens (speed: {spd:.2f}t/s) ",end="\r",flush=True)
sys.stdout = sys.__stdout__
sys.stdout.flush()
if chunk:
generation_infos["generated_text"] += chunk
antiprompt = self.personality.detect_antiprompt(generation_infos["generated_text"])
if antiprompt:
ASCIIColors.warning(f"\nDetected hallucination with antiprompt: {antiprompt}")
generation_infos["generated_text"] = self.remove_text_from_string(generation_infos["generated_text"],antiprompt)
return False
else:
generation_infos["nb_received_tokens"] += 1
generation_infos["first_chunk"]=False
# if stop generation is detected then stop
if not self.cancel_gen:
return True
else:
self.cancel_gen = False
ASCIIColors.warning("Generation canceled")
return False

def learn_from_discussion(self, title, discussion, nb_gen=None, callback=None):
if self.config.summerize_discussion:
prompt = f"!@>discussion:\n--\n!@>title:{title}!@>content:\n{discussion}\n--\n!@>question:What should we learn from this discussion?!@>Summerizer: Here is a summary of the most important informations extracted from the discussion:\n"
if nb_gen is None:
nb_gen = self.config.max_summary_size
generated = ""
gen_infos={
"nb_received_tokens":0,
"generated_text":"",
"processing":False,
"first_chunk": True,
}
if callback is None:
callback = partial(self.default_callback, generation_infos=gen_infos)
self.model.generate(prompt, nb_gen, callback)
if self.config.debug:
ASCIIColors.yellow(gen_infos["generated_text"])
return gen_infos["generated_text"]
else:
return discussion

def remove_text_from_string(self, string, text_to_find):
"""
Expand Down
3 changes: 2 additions & 1 deletion lollms/binding.py
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,7 @@ def generate(self,
verbose (bool, optional): If true, the code will spit many informations about the generation process. Defaults to False.
"""
pass

def tokenize(self, prompt:str):
"""
Tokenizes the given prompt using the model's tokenizer.
Expand Down Expand Up @@ -489,9 +490,9 @@ def clear_cuda():
print(LLMBinding.vram_usage())
try:
torch.cuda.empty_cache()
ASCIIColors.green("Cleared cache")
except Exception as ex:
ASCIIColors.error("Couldn't clear cuda memory")
ASCIIColors.red("Cleared cache")
ASCIIColors.red("*-*-*-*-*-*-*-*")
ASCIIColors.red("Cuda VRAM usage")
ASCIIColors.red("*-*-*-*-*-*-*-*")
Expand Down
4 changes: 3 additions & 1 deletion lollms/configs/config.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# =================== Lord Of Large Language Models Configuration file ===========================
version: 28
version: 30
binding_name: null
model_name: null

Expand Down Expand Up @@ -59,6 +59,8 @@ audio_silenceTimer: 5000

# Data vectorization
use_discussions_history: false # Activate vectorizing previous conversations
summerize_discussion: false # activate discussion summary (better but adds computation time)
max_summary_size: 512 # in tokens
data_vectorization_visualize_on_vectorization: false
use_files: true # Activate using files
data_vectorization_activate: true # To activate/deactivate data vectorization
Expand Down
62 changes: 33 additions & 29 deletions lollms/personality.py
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,7 @@ def generate_with_images(self, prompt, images, max_size, temperature = None, top
).strip()
return self.bot_says

def generate(self, prompt, max_size, temperature = None, top_k = None, top_p=None, repeat_penalty=None, callback=None, debug=False, show_progress=False ):
def generate(self, prompt, max_size, temperature = None, top_k = None, top_p=None, repeat_penalty=None, repeat_last_n=None, callback=None, debug=False, show_progress=False ):
ASCIIColors.info("Text generation started: Warming up")
self.nb_received_tokens = 0
self.bot_says = ""
Expand All @@ -460,6 +460,7 @@ def generate(self, prompt, max_size, temperature = None, top_k = None, top_p=Non
top_k=self.model_top_k if top_k is None else top_k,
top_p=self.model_top_p if top_p is None else top_p,
repeat_penalty=self.model_repeat_penalty if repeat_penalty is None else repeat_penalty,
repeat_last_n = self.model_repeat_last_n if repeat_last_n is None else repeat_last_n,
).strip()
return self.bot_says

Expand Down Expand Up @@ -669,14 +670,13 @@ def add_file(self, path, callback=None):
if path.suffix in [".png",".jpg",".gif",".bmp",".webp"]:
if self.callback:
try:
if callback:
pth = str(path).replace("\\","/").split('/')
if "uploads" in pth:
idx = pth.index("uploads")
pth = "/".join(pth[idx:])
self.new_message("",MSG_TYPE.MSG_TYPE_FULL)
output = f'<img src="{pth}" width="300">\n\n'
self.full(output)
pth = str(path).replace("\\","/").split('/')
if "uploads" in pth:
idx = pth.index("uploads")
pth = "/".join(pth[idx:])
self.new_message("",MSG_TYPE.MSG_TYPE_FULL)
output = f'<img src="{pth}" width="300">\n\n'
self.full(output)

if self.model.binding_type not in [BindingType.TEXT_IMAGE, BindingType.TEXT_IMAGE_VIDEO]:
self.step_start("Understanding image (please wait)")
Expand All @@ -693,7 +693,6 @@ def add_file(self, path, callback=None):
else:
self.step_start("Importing image (please wait)")
self.step_end("Importing image (please wait)")
self.full(output)

except Exception as ex:
trace_exception(ex)
Expand Down Expand Up @@ -1684,11 +1683,11 @@ def save_config_file(self, path, data):
with open(path, 'w') as file:
yaml.dump(data, file)

def generate_with_images(self, prompt, images, max_size, temperature = None, top_k = None, top_p=None, repeat_penalty=None, callback=None, debug=False ):
return self.personality.generate_with_images(prompt, images, max_size, temperature, top_k, top_p, repeat_penalty, callback, debug=debug)
def generate_with_images(self, prompt, images, max_size, temperature = None, top_k = None, top_p=None, repeat_penalty=None, repeat_last_n=None, callback=None, debug=False ):
return self.personality.generate_with_images(prompt, images, max_size, temperature, top_k, top_p, repeat_penalty, repeat_last_n, callback, debug=debug)

def generate(self, prompt, max_size, temperature = None, top_k = None, top_p=None, repeat_penalty=None, callback=None, debug=False ):
return self.personality.generate(prompt, max_size, temperature, top_k, top_p, repeat_penalty, callback, debug=debug)
def generate(self, prompt, max_size, temperature = None, top_k = None, top_p=None, repeat_penalty=None, repeat_last_n=None, callback=None, debug=False ):
return self.personality.generate(prompt, max_size, temperature, top_k, top_p, repeat_penalty, repeat_last_n, callback, debug=debug)

def run_workflow(self, prompt:str, previous_discussion_text:str="", callback: Callable[[str, MSG_TYPE, dict, list], bool]=None):
"""
Expand Down Expand Up @@ -2133,7 +2132,7 @@ def yes_no(self, question: str, context:str="", max_answer_length: int = 50) ->
Returns:
bool: True if the user prompt is asking to generate an image, False otherwise.
"""
return self.multichoice_question(question, ["no","yes"],context, max_answer_length)==1
return self.multichoice_question(question, ["no","yes"], context, max_answer_length)>0

def multichoice_question(self, question: str, possible_answers:list, context:str = "", max_answer_length: int = 50) -> int:
"""
Expand All @@ -2148,34 +2147,39 @@ def multichoice_question(self, question: str, possible_answers:list, context:str
int: Index of the selected option within the possible_ansers list. Or -1 if there was not match found among any of them.
"""
if context!="":
template = """!@>instruction:
Act as prompt classifier, a tool capable of classifying the user prompt.
!@>Context:
template = """!@>instructions:
Answer this multi choices question.
Answer with an id from the possible answers.
Do not answer with an id outside this possible answers.
!@>question: {{question}}
!@>possible answers:
{{choices}}
!@>Context:
{{context}}
!@>answer:"""
else:
template = """!@>instructions:
Answer this multi choices question.
Answer with an id from the possible answers.
Do not answer with an id outside this possible answers.
!@>question: {{question}}
!@>choices:
{{choices}}
!@>prompt analyzer: After analyzing the user prompt, the most suitable choice is choice number """
else:
template = """!@>Instructions:
Act as prompt analyzer, a tool capable of analyzing the user prompt and answering yes or no this prompt asking to generate an image.
!@>instruction: {{question}}
!@>choices: {{choices}}
!@>prompt analyzer: After analyzing the user prompt, the most suitable choice is choice number """
{{choices}}
!@>answer:"""

pr = PromptReshaper(template)
prompt = pr.build({
"context":context,
"question":question,
"choices":"\n".join([f"{i} - {possible_answer}" for i,possible_answer in enumerate(possible_answers)])
"choices":"\n".join([f"{i}. {possible_answer}" for i, possible_answer in enumerate(possible_answers)])
},
self.personality.model.tokenize,
self.personality.model.detokenize,
self.personality.model.config.ctx_size,
["previous_discussion"]
)
gen = self.generate(prompt, max_answer_length).strip().replace("</s>","").replace("<s>","")
selection = gen.split()[0]
gen = self.generate(prompt, max_answer_length, temperature=0.1, top_k=50, top_p=0.9, repeat_penalty=1.0, repeat_last_n=50).strip().replace("</s>","").replace("<s>","")
selection = gen.strip().split()[0].replace(",","")
self.print_prompt("Multi choice selection",prompt+gen)
try:
return int(selection)
Expand Down
Loading

0 comments on commit dc0c6a6

Please sign in to comment.