diff --git a/.github/workflows/build-publish.yaml b/.github/workflows/build-publish.yaml
index a5ac980..fe10302 100644
--- a/.github/workflows/build-publish.yaml
+++ b/.github/workflows/build-publish.yaml
@@ -19,8 +19,7 @@ jobs:
cmake-version: 3.x # Specify your desired CMake version
- name: Build and Test (Linux)
- run: |
- mkdir build
+ run: | mkdir build
cd build
cmake ..
make
@@ -46,8 +45,7 @@ jobs:
cmake-version: 3.0 # cmake version
- name: Build and Test (Windows)
- run: |
- mkdir build
+ run: | mkdir build
cd build
cmake ..
cmake --build . --config Release
diff --git a/configs/config.yaml b/configs/config.yaml
index e67efc4..5a540d3 100644
--- a/configs/config.yaml
+++ b/configs/config.yaml
@@ -1,5 +1,5 @@
# =================== Lord Of Large Language Multimodal Systems Configuration file ===========================
-version: 104
+version: 106
binding_name: null
model_name: null
model_variant: null
@@ -29,6 +29,11 @@ app_custom_logo: ""
# Genreration parameters
discussion_prompt_separator: "!@>"
+start_header_id_template: "!@>"
+end_header_id_template: ": "
+separator_template: "\n"
+system_message_template: "system"
+
seed: -1
ctx_size: 4084
max_n_predict: 4096
diff --git a/lollms/app.py b/lollms/app.py
index 84abbb6..c62dfed 100644
--- a/lollms/app.py
+++ b/lollms/app.py
@@ -182,6 +182,13 @@ class LollmsApplication(LoLLMsCom):
return False
def add_discussion_to_skills_library(self, client: Client):
+ discussion_prompt_separator = self.config.discussion_prompt_separator
+ start_header_id_template = self.config.start_header_id_template
+ end_header_id_template = self.config.end_header_id_template
+ separator_template = self.config.separator_template
+ system_message_template = self.config.system_message_template
+
+
messages = client.discussion.get_messages()
# Extract relevant information from messages
@@ -194,20 +201,20 @@ class LollmsApplication(LoLLMsCom):
self.tasks_library.callback = bk_cb
# Generate title
- title_prompt = "\n".join([
- f"!@>system:Generate a concise and descriptive title for the following content.",
+ title_prompt = f"{separator_template}".join([
+ f"{start_header_id_template}{system_message_template}{end_header_id_template}Generate a concise and descriptive title for the following content.",
"The title should summarize the main topic or subject of the content.",
"Do not mention the format of the content (e.g., bullet points, discussion, etc.) in the title.",
"Provide only the title without any additional explanations or context.",
- "!@>content:",
+ f"{start_header_id_template}content{end_header_id_template}",
f"{content}",
- "!@>title:"
+ f"{start_header_id_template}title{end_header_id_template}"
])
title = self._generate_text(title_prompt)
# Determine category
- category_prompt = f"!@>system:Analyze the following title, and determine the most appropriate generic category that encompasses the main subject or theme. The category should be broad enough to include multiple related skill entries. Provide only the category name without any additional explanations or context:\n\nTitle:\n{title}\n\n!@>Category:\n"
+ category_prompt = f"{start_header_id_template}{system_message_template}{end_header_id_template}Analyze the following title, and determine the most appropriate generic category that encompasses the main subject or theme. The category should be broad enough to include multiple related skill entries. Provide only the category name without any additional explanations or context:\n\nTitle:\n{title}\n{separator_template}{start_header_id_template}Category:\n"
category = self._generate_text(category_prompt)
# Add entry to skills library
@@ -763,6 +770,14 @@ class LollmsApplication(LoLLMsCom):
Returns:
Tuple[str, str, List[str]]: The prepared query, original message content, and tokenized query.
"""
+ discussion_prompt_separator = self.config.discussion_prompt_separator
+ start_header_id_template = self.config.start_header_id_template
+ end_header_id_template = self.config.end_header_id_template
+ separator_template = self.config.separator_template
+ system_message_template = self.config.system_message_template
+
+
+
if self.personality.callback is None:
self.personality.callback = partial(self.process_chunk, client_id=client_id)
# Get the list of messages
@@ -802,7 +817,7 @@ class LollmsApplication(LoLLMsCom):
conditionning = self.personality._personality_conditioning
if len(conditionning)>0:
- conditionning = self.personality.replace_keys(conditionning, self.personality.conditionning_commands) +"" if conditionning[-1]=="\n" else "\n"
+ conditionning = start_header_id_template + system_message_template + end_header_id_template + self.personality.replace_keys(conditionning, self.personality.conditionning_commands) + ("" if conditionning[-1]==separator_template else separator_template)
# Check if there are document files to add to the prompt
internet_search_results = ""
@@ -814,21 +829,21 @@ class LollmsApplication(LoLLMsCom):
# boosting information
if self.config.positive_boost:
- positive_boost="\n!@>important information: "+self.config.positive_boost+"\n"
+ positive_boost=f"{separator_template}{start_header_id_template}important information: "+self.config.positive_boost+"\n"
n_positive_boost = len(self.model.tokenize(positive_boost))
else:
positive_boost=""
n_positive_boost = 0
if self.config.negative_boost:
- negative_boost="\n!@>important information: "+self.config.negative_boost+"\n"
+ negative_boost=f"{separator_template}{start_header_id_template}important information: "+self.config.negative_boost+"\n"
n_negative_boost = len(self.model.tokenize(negative_boost))
else:
negative_boost=""
n_negative_boost = 0
if self.config.fun_mode:
- fun_mode="\n!@>important information: Fun mode activated. In this mode you must answer in a funny playful way. Do not be serious in your answers. Each answer needs to make the user laugh.\n"
+ fun_mode=f"{separator_template}{start_header_id_template}important information: Fun mode activated. In this mode you must answer in a funny playful way. Do not be serious in your answers. Each answer needs to make the user laugh.\n"
n_fun_mode = len(self.model.tokenize(positive_boost))
else:
fun_mode=""
@@ -842,14 +857,14 @@ class LollmsApplication(LoLLMsCom):
discussion = self.recover_discussion(client_id)
if self.config.internet_activate_search_decision:
self.personality.step_start(f"Requesting if {self.personality.name} needs to search internet to answer the user")
- need = not self.personality.yes_no(f"!@>system: Answer the question with yes or no. Don't add any extra explanation.\n!@>user: Do you have enough information to give a satisfactory answer to {self.config.user_name}'s request without internet search? (If you do not know or you can't answer 0 (no)", discussion)
+ need = not self.personality.yes_no(f"{start_header_id_template}{system_message_template}{end_header_id_template}Answer the question with yes or no. Don't add any extra explanation.{separator_template}{start_header_id_template}user: Do you have enough information to give a satisfactory answer to {self.config.user_name}'s request without internet search? (If you do not know or you can't answer 0 (no)", discussion)
self.personality.step_end(f"Requesting if {self.personality.name} needs to search internet to answer the user")
self.personality.step("Yes" if need else "No")
else:
need=True
if need:
self.personality.step_start("Crafting internet search query")
- query = self.personality.fast_gen(f"!@>discussion:\n{discussion[-2048:]}\n!@>system: Read the discussion and craft a web search query suited to recover needed information to reply to last {self.config.user_name} message.\nDo not answer the prompt. Do not add explanations.\n!@>current date: {datetime.now()}\n!@>websearch query: ", max_generation_size=256, show_progress=True, callback=self.personality.sink)
+ query = self.personality.fast_gen(f"{start_header_id_template}discussion{end_header_id_template}\n{discussion[-2048:]}{separator_template}{start_header_id_template}system: Read the discussion and craft a web search query suited to recover needed information to reply to last {self.config.user_name} message.\nDo not answer the prompt. Do not add explanations.{separator_template}{start_header_id_template}current date: {datetime.now()}{separator_template}{start_header_id_template}websearch query: ", max_generation_size=256, show_progress=True, callback=self.personality.sink)
self.personality.step_end("Crafting internet search query")
self.personality.step(f"web search query: {query}")
@@ -858,14 +873,14 @@ class LollmsApplication(LoLLMsCom):
else:
self.personality.step_start("Performing Internet search (advanced mode: slower but more advanced)")
- internet_search_results=f"!@>instructions: Use the web search results data to answer {self.config.user_name}. Try to extract information from the web search and use it to perform the requested task or answer the question. Do not come up with information that is not in the websearch results. Try to stick to the websearch results and clarify if your answer was based on the resuts or on your own culture. If you don't know how to perform the task, then tell the user politely that you need more data inputs.\n!@>Web search results:\n"
+ internet_search_results=f"{start_header_id_template}instructions{end_header_id_template}Use the web search results data to answer {self.config.user_name}. Try to extract information from the web search and use it to perform the requested task or answer the question. Do not come up with information that is not in the websearch results. Try to stick to the websearch results and clarify if your answer was based on the resuts or on your own culture. If you don't know how to perform the task, then tell the user politely that you need more data inputs.{separator_template}{start_header_id_template}Web search results:\n"
docs, sorted_similarities, document_ids = self.personality.internet_search_with_vectorization(query, self.config.internet_quick_search)
if len(docs)>0:
for doc, infos,document_id in zip(docs, sorted_similarities, document_ids):
internet_search_infos.append(document_id)
- internet_search_results += f"!@>search result chunk:\nchunk_infos:{document_id['url']}\nchunk_title:{document_id['title']}\ncontent:{doc}\n"
+ internet_search_results += f"{start_header_id_template}search result chunk{end_header_id_template}\nchunk_infos:{document_id['url']}\nchunk_title:{document_id['title']}\ncontent:{doc}\n"
else:
internet_search_results += "The search response was empty!\nFailed to recover useful information from the search engine.\n"
if self.config.internet_quick_search:
@@ -875,12 +890,12 @@ class LollmsApplication(LoLLMsCom):
if self.personality.persona_data_vectorizer:
if documentation=="":
- documentation="\n!@>Documentation:\n"
+ documentation=f"{separator_template}{start_header_id_template}Documentation:\n"
if self.config.data_vectorization_build_keys_words:
if discussion is None:
discussion = self.recover_discussion(client_id)
- query = self.personality.fast_gen(f"\n!@>instruction: Read the discussion and rewrite the last prompt for someone who didn't read the entire discussion.\nDo not answer the prompt. Do not add explanations.\n!@>discussion:\n{discussion[-2048:]}\n!@>enhanced query: ", max_generation_size=256, show_progress=True)
+ query = self.personality.fast_gen(f"{separator_template}{start_header_id_template}instruction: Read the discussion and rewrite the last prompt for someone who didn't read the entire discussion.\nDo not answer the prompt. Do not add explanations.{separator_template}{start_header_id_template}discussion:\n{discussion[-2048:]}{separator_template}{start_header_id_template}enhanced query: ", max_generation_size=256, show_progress=True)
ASCIIColors.cyan(f"Query:{query}")
else:
query = current_message.content
@@ -888,9 +903,9 @@ class LollmsApplication(LoLLMsCom):
docs, sorted_similarities, document_ids = self.personality.persona_data_vectorizer.recover_text(query, top_k=self.config.data_vectorization_nb_chunks)
for doc, infos, doc_id in zip(docs, sorted_similarities, document_ids):
if self.config.data_vectorization_put_chunk_informations_into_context:
- documentation += f"!@>document chunk:\nchunk_infos:{infos}\ncontent:{doc}\n"
+ documentation += f"{start_header_id_template}document chunk{end_header_id_template}\nchunk_infos:{infos}\ncontent:{doc}\n"
else:
- documentation += f"!@>chunk:\n{doc}\n"
+ documentation += f"{start_header_id_template}chunk{end_header_id_template}\n{doc}\n"
except Exception as ex:
trace_exception(ex)
@@ -901,11 +916,11 @@ class LollmsApplication(LoLLMsCom):
discussion = self.recover_discussion(client_id)
if documentation=="":
- documentation="\n!@>important information: Use the documentation data to answer the user questions. If the data is not present in the documentation, please tell the user that the information he is asking for does not exist in the documentation section. It is strictly forbidden to give the user an answer without having actual proof from the documentation.\n!@>Documentation:\n"
+ documentation=f"{separator_template}{start_header_id_template}important information: Use the documentation data to answer the user questions. If the data is not present in the documentation, please tell the user that the information he is asking for does not exist in the documentation section. It is strictly forbidden to give the user an answer without having actual proof from the documentation.{separator_template}{start_header_id_template}Documentation:\n"
if self.config.data_vectorization_build_keys_words:
self.personality.step_start("Building vector store query")
- query = self.personality.fast_gen(f"\n!@>instruction: Read the discussion and rewrite the last prompt for someone who didn't read the entire discussion.\nDo not answer the prompt. Do not add explanations.\n!@>discussion:\n{discussion[-2048:]}\n!@>enhanced query: ", max_generation_size=256, show_progress=True, callback=self.personality.sink)
+ query = self.personality.fast_gen(f"{separator_template}{start_header_id_template}instruction: Read the discussion and rewrite the last prompt for someone who didn't read the entire discussion.\nDo not answer the prompt. Do not add explanations.{separator_template}{start_header_id_template}discussion:\n{discussion[-2048:]}{separator_template}{start_header_id_template}enhanced query: ", max_generation_size=256, show_progress=True, callback=self.personality.sink)
self.personality.step_end("Building vector store query")
ASCIIColors.cyan(f"Query: {query}")
else:
@@ -919,20 +934,20 @@ class LollmsApplication(LoLLMsCom):
content = client.discussion.vectorizer.chunks[doc_index]['chunk_text']
if self.config.data_vectorization_put_chunk_informations_into_context:
- documentation += f"!@>document chunk:\nchunk_infos:{doc_id}\ncontent:{content}\n"
+ documentation += f"{start_header_id_template}document chunk{end_header_id_template}\nchunk_infos:{doc_id}\ncontent:{content}\n"
else:
- documentation += f"!@>chunk:\n{content}\n"
+ documentation += f"{start_header_id_template}chunk{end_header_id_template}\n{content}\n"
docs, sorted_similarities, document_ids = client.discussion.vectorizer.recover_text(query, top_k=self.config.data_vectorization_nb_chunks)
for doc, infos in zip(docs, sorted_similarities):
if self.config.data_vectorization_force_first_chunk and len(client.discussion.vectorizer.chunks)>0 and infos[0]==doc_id:
continue
if self.config.data_vectorization_put_chunk_informations_into_context:
- documentation += f"!@>document chunk:\nchunk path: {infos[0]}\nchunk content:\n{doc}\n"
+ documentation += f"{start_header_id_template}document chunk{end_header_id_template}\nchunk path: {infos[0]}\nchunk content:\n{doc}\n"
else:
- documentation += f"!@>chunk:\n{doc}\n"
+ documentation += f"{start_header_id_template}chunk{end_header_id_template}\n{doc}\n"
- documentation += "\n!@>important information: Use the documentation data to answer the user questions. If the data is not present in the documentation, please tell the user that the information he is asking for does not exist in the documentation section. It is strictly forbidden to give the user an answer without having actual proof from the documentation.\n"
+ documentation += f"{separator_template}{start_header_id_template}important information: Use the documentation data to answer the user questions. If the data is not present in the documentation, please tell the user that the information he is asking for does not exist in the documentation section. It is strictly forbidden to give the user an answer without having actual proof from the documentation.\n"
except Exception as ex:
trace_exception(ex)
self.warning("Couldn't add documentation to the context. Please verify the vector database")
@@ -943,7 +958,7 @@ class LollmsApplication(LoLLMsCom):
if discussion is None:
discussion = self.recover_discussion(client_id)
self.personality.step_start("Building query")
- query = self.personality.fast_gen(f"!@>Your task is to carefully read the provided discussion and reformulate {self.config.user_name}'s request concisely. Return only the reformulated request without any additional explanations, commentary, or output.\n!@>discussion:\n{discussion[-2048:]}\n!@>search query: ", max_generation_size=256, show_progress=True, callback=self.personality.sink)
+ query = self.personality.fast_gen(f"{start_header_id_template}{system_message_template}{end_header_id_template}Your task is to carefully read the provided discussion and reformulate {self.config.user_name}'s request concisely. Return only the reformulated request without any additional explanations, commentary, or output.{separator_template}{start_header_id_template}discussion:\n{discussion[-2048:]}{separator_template}{start_header_id_template}search query: ", max_generation_size=256, show_progress=True, callback=self.personality.sink)
self.personality.step_end("Building query")
# skills = self.skills_library.query_entry(query)
self.personality.step_start("Adding skills")
@@ -953,9 +968,9 @@ class LollmsApplication(LoLLMsCom):
knowledge_infos={"titles":skill_titles,"contents":skills}
if len(skills)>0:
if knowledge=="":
- knowledge=f"!@>knowledge:\n"
+ knowledge=f"{start_header_id_template}knowledge{end_header_id_template}\n"
for i,(title, content) in enumerate(zip(skill_titles,skills)):
- knowledge += f"!@>knowledge {i}:\ntitle:\n{title}\ncontent:\n{content}\n"
+ knowledge += f"{start_header_id_template}knowledge {i}{end_header_id_template}\ntitle:\n{title}\ncontent:\n{content}\n"
self.personality.step_end("Adding skills")
self.personality.step_end("Querying skills library")
except Exception as ex:
@@ -965,7 +980,7 @@ class LollmsApplication(LoLLMsCom):
self.personality.step_end("Querying skills library",False)
user_description=""
if self.config.use_user_informations_in_discussion:
- user_description="!@>User description:\n"+self.config.user_description+"\n"
+ user_description=f"{start_header_id_template}User description{end_header_id_template}\n"+self.config.user_description+"\n"
# Tokenize the conditionning text and calculate its number of tokens
@@ -1121,9 +1136,9 @@ class LollmsApplication(LoLLMsCom):
ASCIIColors.bold("HISTORY")
ASCIIColors.yellow(knowledge)
ASCIIColors.bold("DISCUSSION")
- ASCIIColors.hilight(discussion_messages,"!@>",ASCIIColors.color_yellow,ASCIIColors.color_bright_red,False)
+ ASCIIColors.hilight(discussion_messages,f"{start_header_id_template}",ASCIIColors.color_yellow,ASCIIColors.color_bright_red,False)
ASCIIColors.bold("Final prompt")
- ASCIIColors.hilight(prompt_data,"!@>",ASCIIColors.color_yellow,ASCIIColors.color_bright_red,False)
+ ASCIIColors.hilight(prompt_data,f"{start_header_id_template}",ASCIIColors.color_yellow,ASCIIColors.color_bright_red,False)
ASCIIColors.info(f"prompt size:{len(tokens)} tokens")
ASCIIColors.info(f"available space after doc and knowledge:{available_space} tokens")
diff --git a/lollms/com.py b/lollms/com.py
index d689c1b..c1bed36 100644
--- a/lollms/com.py
+++ b/lollms/com.py
@@ -41,6 +41,7 @@ class LoLLMsCom:
def __init__(self, sio:socketio.AsyncServer=None, verbose:bool=False) -> None:
self.sio= sio
self.verbose = verbose
+ self.config = None
self.tti = None
self.tts = None
self.stt = None
diff --git a/lollms/configs/config.yaml b/lollms/configs/config.yaml
index e67efc4..5a540d3 100644
--- a/lollms/configs/config.yaml
+++ b/lollms/configs/config.yaml
@@ -1,5 +1,5 @@
# =================== Lord Of Large Language Multimodal Systems Configuration file ===========================
-version: 104
+version: 106
binding_name: null
model_name: null
model_variant: null
@@ -29,6 +29,11 @@ app_custom_logo: ""
# Genreration parameters
discussion_prompt_separator: "!@>"
+start_header_id_template: "!@>"
+end_header_id_template: ": "
+separator_template: "\n"
+system_message_template: "system"
+
seed: -1
ctx_size: 4084
max_n_predict: 4096
diff --git a/lollms/databases/discussions_database.py b/lollms/databases/discussions_database.py
index c502a42..51f684d 100644
--- a/lollms/databases/discussions_database.py
+++ b/lollms/databases/discussions_database.py
@@ -1030,10 +1030,12 @@ class Discussion:
messages += f'{sender}: {content}\n'
return title, messages
- def format_discussion(self, max_allowed_tokens, splitter_text="!@>"):
+ def format_discussion(self, max_allowed_tokens, splitter_text=None):
+ if not splitter_text:
+ splitter_text = self.lollms.config.discussion_prompt_separator
formatted_text = ""
for message in reversed(self.messages): # Start from the newest message
- formatted_message = f"{splitter_text}{message.sender.replace(':','').replace('!@>','')}:\n{message.content}\n"
+ formatted_message = f"{splitter_text}{message.sender.replace(':','').replace(splitter_text,'')}:\n{message.content}\n"
tokenized_message = self.lollms.model.tokenize(formatted_message)
if len(tokenized_message) + len(self.lollms.model.tokenize(formatted_text)) <= max_allowed_tokens:
formatted_text = formatted_message + formatted_text
diff --git a/lollms/functions/bibliography.py b/lollms/functions/bibliography.py
index dfb32aa..660ae70 100644
--- a/lollms/functions/bibliography.py
+++ b/lollms/functions/bibliography.py
@@ -8,7 +8,7 @@ from pathlib import Path
from functools import partial
# It is advised to import typing elements
-from typing import List, Optional, Any
+from typing import List, Optional, Any, Tuple, Dict
# Import PackageManager if there are potential libraries that need to be installed
from lollms.utilities import PackageManager, find_first_available_file_index, discussion_path_to_url
@@ -102,7 +102,6 @@ def arxiv_pdf_search(query: str, max_results: Optional[int] = 5, sort_by: Option
PDF Link
Local PDF
-
"""
# Append to report content
report_content += f"""
diff --git a/lollms/personality.py b/lollms/personality.py
index f688edc..bf197ca 100644
--- a/lollms/personality.py
+++ b/lollms/personality.py
@@ -120,11 +120,15 @@ class AIPersonality:
Raises:
ValueError: If the provided path is not a folder or does not contain a config.yaml file.
"""
+ self.config = config
+ start_header_id_template = self.config.start_header_id_template
+ end_header_id_template = self.config.end_header_id_template
+ system_message_template = self.config.system_message_template
+
self.bot_says = ""
self.lollms_paths = lollms_paths
self.model = model
- self.config = config
self.callback = callback
self.app = app
@@ -157,10 +161,11 @@ class AIPersonality:
self._languages: List[dict]=[]
+
+
# Conditionning
self._personality_description: str = "This personality is a helpful and Kind AI ready to help you solve your problems"
self._personality_conditioning: str = "\n".join([
- "!@>system:",
"lollms (Lord of LLMs) is a smart and helpful Assistant built by the computer geek ParisNeo.",
"It is compatible with many bindings to LLM models such as llama, gpt4all, gptj, autogptq etc.",
"It can discuss with humans and assist them on many subjects.",
@@ -172,10 +177,9 @@ class AIPersonality:
])
self._welcome_message: str = "Welcome! I am lollms (Lord of LLMs) A free and open assistant built by ParisNeo. What can I do for you today?"
self._include_welcome_message_in_discussion: bool = True
- self._user_message_prefix: str = "!@>human: "
+ self._user_message_prefix: str = f"human:"
self._link_text: str = "\n"
- self._ai_message_prefix: str = "!@>lollms:"
- self._anti_prompts:list = [self.config.discussion_prompt_separator]
+ self._ai_message_prefix: str = f"lollms:"
# Extra
self._dependencies: List[str] = []
@@ -187,7 +191,6 @@ class AIPersonality:
# Default model parameters
self._model_temperature: float = 0.1 # higher: more creative, lower more deterministic
- self._model_n_predicts: int = 2048 # higher: generates many words, lower generates
self._model_top_k: int = 50
self._model_top_p: float = 0.95
self._model_repeat_penalty: float = 1.3
@@ -435,25 +438,29 @@ class AIPersonality:
Returns:
int: Index of the selected option within the possible_ansers list. Or -1 if there was not match found among any of them.
"""
+ start_header_id_template = self.config.start_header_id_template
+ end_header_id_template = self.config.end_header_id_template
+ system_message_template = self.config.system_message_template
+
choices = "\n".join([f"{i}. {possible_answer}" for i, possible_answer in enumerate(possible_answers)])
elements = [conditionning] if conditionning!="" else []
elements += [
- "!@>instructions:",
+ f"{start_header_id_template}{system_message_template}{end_header_id_template}",
"Answer this multi choices question.",
"Answer with an id from the possible answers.",
"Do not answer with an id outside this possible answers.",
]
if context!="":
elements+=[
- "!@>Context:",
+ f"{start_header_id_template}context{end_header_id_template}",
f"{context}",
]
elements += [
- f"!@>question: {question}",
- "!@>possible answers:",
+ f"{start_header_id_template}question{end_header_id_template}{question}",
+ f"{start_header_id_template}possible answers{end_header_id_template}",
f"{choices}",
]
- elements += ["!@>answer:"]
+ elements += [f"{start_header_id_template}answer{end_header_id_template}"]
prompt = self.build_prompt(elements)
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, callback=self.sink).strip().replace("","").replace("","")
@@ -478,24 +485,28 @@ class AIPersonality:
Returns:
int: Index of the selected option within the possible_ansers list. Or -1 if there was not match found among any of them.
"""
+ start_header_id_template = self.config.start_header_id_template
+ end_header_id_template = self.config.end_header_id_template
+ system_message_template = self.config.system_message_template
+
choices = "\n".join([f"{i}. {possible_answer}" for i, possible_answer in enumerate(possible_answers)])
elements = [conditionning] if conditionning!="" else []
elements += [
- "!@>instructions:",
+ f"{start_header_id_template}{system_message_template}{end_header_id_template}",
"Answer this multi choices question.",
"Answer with an id from the possible answers.",
"Do not answer with an id outside this possible answers.",
- f"!@>question: {question}",
- "!@>possible answers:",
+ f"{start_header_id_template}{end_header_id_template}{question}",
+ f"{start_header_id_template}possible answers{end_header_id_template}",
f"{choices}",
]
if context!="":
elements+=[
- "!@>Context:",
+ f"{start_header_id_template}context{end_header_id_template}",
f"{context}",
]
- elements += ["!@>answer:"]
+ elements += [f"{start_header_id_template}answer{end_header_id_template}"]
prompt = self.build_prompt(elements)
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("","").replace("","")
@@ -581,8 +592,12 @@ class AIPersonality:
Returns:
- str: The generated text after removing special tokens ("" and "") and stripping any leading/trailing whitespace.
"""
+ start_header_id_template = self.config.start_header_id_template
+ end_header_id_template = self.config.end_header_id_template
+ system_message_template = self.config.system_message_template
+
prompt = "\n".join([
- "!@>system: I am an AI assistant that can converse and analyze images. When asked to locate something in an image you send, I will reply with:",
+ f"{start_header_id_template}{system_message_template}{end_header_id_template}I am an AI assistant that can converse and analyze images. When asked to locate something in an image you send, I will reply with:",
"boundingbox(image_index, label, left, top, width, height)",
"Where:",
"image_index: 0-based index of the image",
@@ -822,13 +837,11 @@ class AIPersonality:
self._user_message_prefix = config.get("user_message_prefix", self._user_message_prefix)
self._link_text = config.get("link_text", self._link_text)
self._ai_message_prefix = config.get("ai_message_prefix", self._ai_message_prefix)
- self._anti_prompts = [self.config.discussion_prompt_separator]+config.get("anti_prompts", self._anti_prompts)
self._dependencies = config.get("dependencies", self._dependencies)
self._disclaimer = config.get("disclaimer", self._disclaimer)
self._help = config.get("help", self._help)
self._commands = config.get("commands", self._commands)
self._model_temperature = config.get("model_temperature", self._model_temperature)
- self._model_n_predicts = config.get("model_n_predicts", self._model_n_predicts)
self._model_top_k = config.get("model_top_k", self._model_top_k)
self._model_top_p = config.get("model_top_p", self._model_top_p)
self._model_repeat_penalty = config.get("model_repeat_penalty", self._model_repeat_penalty)
@@ -889,7 +902,7 @@ class AIPersonality:
files = [f for f in self.data_path.iterdir() if f.suffix.lower() in ['.asm', '.bat', '.c', '.cpp', '.cs', '.csproj', '.css',
'.csv', '.docx', '.h', '.hh', '.hpp', '.html', '.inc', '.ini', '.java', '.js', '.json', '.log',
'.lua', '.map', '.md', '.pas', '.pdf', '.php', '.pptx', '.ps1', '.py', '.rb', '.rtf', '.s', '.se', '.sh', '.sln',
- '.snippet', '.snippets', '.sql', '.sym', '.ts', '.txt', '.xlsx', '.xml', '.yaml', '.yml'] ]
+ '.snippet', '.snippets', '.sql', '.sym', '.ts', '.txt', '.xlsx', '.xml', '.yaml', '.yml', '.msg'] ]
if len(files)>0:
dl = GenericDataLoader()
self.persona_data_vectorizer = TextVectorizer(
@@ -1106,13 +1119,11 @@ class AIPersonality:
"user_message_prefix": self._user_message_prefix,
"link_text": self._link_text,
"ai_message_prefix": self._ai_message_prefix,
- "anti_prompts": self._anti_prompts,
"dependencies": self._dependencies,
"disclaimer": self._disclaimer,
"help": self._help,
"commands": self._commands,
"model_temperature": self._model_temperature,
- "model_n_predicts": self._model_n_predicts,
"model_top_k": self._model_top_k,
"model_top_p": self._model_top_p,
"model_repeat_penalty": self._model_repeat_penalty,
@@ -1148,13 +1159,11 @@ class AIPersonality:
"user_message_prefix": self._user_message_prefix,
"link_text": self._link_text,
"ai_message_prefix": self._ai_message_prefix,
- "anti_prompts": self._anti_prompts,
"dependencies": self._dependencies,
"disclaimer": self._disclaimer,
"help": self._help,
"commands": self._commands,
"model_temperature": self._model_temperature,
- "model_n_predicts": self._model_n_predicts,
"model_top_k": self._model_top_k,
"model_top_p": self._model_top_p,
"model_repeat_penalty": self._model_repeat_penalty,
@@ -1416,27 +1425,6 @@ class AIPersonality:
"""
self._ai_message_prefix = prefix
- @property
- def anti_prompts(self):
- """
- Get the anti-prompts list.
-
- Returns:
- list: The anti-prompts list.
- """
- return self._anti_prompts
-
- @anti_prompts.setter
- def anti_prompts(self, prompts):
- """
- Set the anti-prompts list.
-
- Args:
- prompts (list): The anti-prompts list to set.
- """
- self._anti_prompts = prompts
-
-
@property
def dependencies(self) -> List[str]:
"""Getter method for the dependencies attribute.
@@ -1526,20 +1514,6 @@ class AIPersonality:
"""
self._model_temperature = value
- @property
- def model_n_predicts(self) -> int:
- """Get the number of predictions the model generates."""
- return self._model_n_predicts
-
- @model_n_predicts.setter
- def model_n_predicts(self, value: int):
- """Set the number of predictions the model generates.
-
- Args:
- value (int): The new number of predictions value.
- """
- self._model_n_predicts = value
-
@property
def model_top_k(self) -> int:
"""Get the model's top-k value."""
@@ -1652,7 +1626,11 @@ class AIPersonality:
Returns:
bool: True if any antiprompt is found in the text (ignoring case), False otherwise.
"""
- for prompt in self.anti_prompts:
+ anti_prompts = [self.app.config.discussion_prompt_separator]
+ if self.app.config.separator_template!="\n":
+ anti_prompts.append(self.app.config.separator_template)
+
+ for prompt in anti_prompts:
if prompt.lower() in text.lower():
return prompt.lower()
return None
@@ -1897,6 +1875,7 @@ class APScript(StateMachine):
self.notify = personality.app.notify
self.personality = personality
+ self.config = personality.config
self.personality_config = personality_config
self.installation_option = personality.installation_option
self.configuration_file_path = self.personality.lollms_paths.personal_configuration_path/"personalities"/self.personality.personality_folder_name/f"config.yaml"
@@ -1932,7 +1911,7 @@ class APScript(StateMachine):
"""
triggered when a new conversation is created
"""
- return None
+ return welcome_message
def selected(self):
"""
@@ -2208,16 +2187,20 @@ class APScript(StateMachine):
def translate(self, text_chunk, output_language="french", max_generation_size=3000):
+ start_header_id_template = self.config.start_header_id_template
+ end_header_id_template = self.config.end_header_id_template
+ system_message_template = self.config.system_message_template
+
translated = self.fast_gen(
"\n".join([
- f"!@>system:",
+ f"{start_header_id_template}{system_message_template}{end_header_id_template}",
f"Translate the following text to {output_language}.",
"Be faithful to the original text and do not add or remove any information.",
"Respond only with the translated text.",
"Do not add comments or explanations.",
- f"!@>text to translate:",
+ f"{start_header_id_template}text to translate{end_header_id_template}",
f"{text_chunk}",
- f"!@>translation:",
+ f"{start_header_id_template}translation{end_header_id_template}",
]),
max_generation_size=max_generation_size, callback=self.sink)
return translated
@@ -2320,18 +2303,22 @@ class APScript(StateMachine):
chunk_summary_post_processing=None,
summary_mode=SUMMARY_MODE.SUMMARY_MODE_SEQUENCIAL
):
+ start_header_id_template = self.config.start_header_id_template
+ end_header_id_template = self.config.end_header_id_template
+ system_message_template = self.config.system_message_template
+
if summary_mode==SUMMARY_MODE.SUMMARY_MODE_SEQUENCIAL:
summary = ""
for i, chunk in enumerate(chunks):
self.step_start(f" Summary of {doc_name} - Processing chunk : {i+1}/{len(chunks)}")
summary = f"{answer_start}"+ self.fast_gen(
"\n".join([
- f"!@>Document_chunk: {doc_name}:",
+ f"{start_header_id_template}Document_chunk{end_header_id_template}{doc_name}:",
f"{summary}",
f"{chunk}",
- f"!@>instruction: {summary_instruction}",
+ f"{start_header_id_template}{system_message_template}{end_header_id_template}{summary_instruction}",
f"Answer directly with the summary with no extra comments.",
- f"!@>summary:",
+ f"{start_header_id_template}summary{end_header_id_template}",
f"{answer_start}"
]),
max_generation_size=max_generation_size,
@@ -2346,11 +2333,11 @@ class APScript(StateMachine):
self.step_start(f" Summary of {doc_name} - Processing chunk : {i+1}/{len(chunks)}")
summary = f"{answer_start}"+ self.fast_gen(
"\n".join([
- f"!@>Document_chunk [{doc_name}]:",
+ f"{start_header_id_template}Document_chunk [{doc_name}]{end_header_id_template}",
f"{chunk}",
- f"!@>instruction: {summary_instruction}",
+ f"{start_header_id_template}{system_message_template}{end_header_id_template}{summary_instruction}",
f"Answer directly with the summary with no extra comments.",
- f"!@>summary:",
+ f"{start_header_id_template}summary{end_header_id_template}",
f"{answer_start}"
]),
max_generation_size=max_generation_size,
@@ -2371,6 +2358,9 @@ class APScript(StateMachine):
callback=None,
chunk_summary_post_processing=None
):
+ start_header_id_template = self.config.start_header_id_template
+ end_header_id_template = self.config.end_header_id_template
+ system_message_template = self.config.system_message_template
summeries = []
for i, chunk in enumerate(chunks):
if iDocument_chunk: {doc_name}:",
+ f"{start_header_id_template}Document_chunk: {doc_name}{end_header_id_template}",
f"Block1:",
f"{chunk}",
f"Block2:",
f"{chunk1}",
- f"!@>instruction: {summary_instruction}",
+ f"{start_header_id_template}{system_message_template}{end_header_id_template}{summary_instruction}",
f"Answer directly with the summary with no extra comments.",
- f"!@>summary:",
+ f"{start_header_id_template}summary{end_header_id_template}",
f"{answer_start}"
]),
max_generation_size=max_generation_size,
@@ -2401,18 +2391,21 @@ class APScript(StateMachine):
return "\n".join(summeries)
def build_prompt_from_context_details(self, context_details:dict, custom_entries=""):
+ start_header_id_template = self.config.start_header_id_template
+ end_header_id_template = self.config.end_header_id_template
+ system_message_template = self.config.system_message_template
return self.build_prompt([
context_details["conditionning"] if context_details["conditionning"] else "",
- "!@>documentation:\n"+context_details["documentation"] if context_details["documentation"] else "",
- "!@>knowledge:\n"+context_details["knowledge"] if context_details["knowledge"] else "",
+ f"{start_header_id_template}documentation{end_header_id_template}\n"+context_details["documentation"] if context_details["documentation"] else "",
+ f"{start_header_id_template}knowledge{end_header_id_template}\n"+context_details["knowledge"] if context_details["knowledge"] else "",
context_details["user_description"] if context_details["user_description"] else "",
- "!@>positive_boost:\n"+context_details["positive_boost"] if context_details["positive_boost"] else "",
- "!@>negative_boost:\n"+context_details["negative_boost"] if context_details["negative_boost"] else "",
- "!@>current_language:\n"+context_details["current_language"] if context_details["current_language"] else "",
- "!@>fun_mode:\n"+context_details["fun_mode"] if context_details["fun_mode"] else "",
- "!@>discussion_window:\n"+context_details["discussion_messages"] if context_details["discussion_messages"] else "",
+ f"{start_header_id_template}positive_boost{end_header_id_template}\n"+context_details["positive_boost"] if context_details["positive_boost"] else "",
+ f"{start_header_id_template}negative_boost{end_header_id_template}\n"+context_details["negative_boost"] if context_details["negative_boost"] else "",
+ f"{start_header_id_template}current_language{end_header_id_template}\n"+context_details["current_language"] if context_details["current_language"] else "",
+ f"{start_header_id_template}fun_mode{end_header_id_template}\n"+context_details["fun_mode"] if context_details["fun_mode"] else "",
+ f"{start_header_id_template}discussion_window{end_header_id_template}\n"+context_details["discussion_messages"] if context_details["discussion_messages"] else "",
custom_entries,
- "!@>"+context_details["ai_prefix"].replace("!@>","").replace(":","")+":"
+ f"{start_header_id_template}"+context_details["ai_prefix"].replace(f"{start_header_id_template}","").replace(":","")+f"{end_header_id_template}"
],
8)
def build_prompt(self, prompt_parts:List[str], sacrifice_id:int=-1, context_size:int=None, minimum_spare_context_size:int=None):
@@ -2734,19 +2727,23 @@ class APScript(StateMachine):
return output.decode("utf8")
def build_python_code(self, prompt, max_title_length=4096):
+ start_header_id_template = self.config.start_header_id_template
+ end_header_id_template = self.config.end_header_id_template
+ system_message_template = self.config.system_message_template
+
if not PackageManager.check_package_installed("autopep8"):
PackageManager.install_package("autopep8")
import autopep8
global_prompt = "\n".join([
f"{prompt}",
- "!@>Extra conditions:",
+ f"{start_header_id_template}Extra conditions{end_header_id_template}",
"- The code must be complete, not just snippets, and should be put inside a single python markdown code.",
"-Preceive each python codeblock with a line using this syntax:",
"$$file_name|the file path relative to the root folder of the project$$",
"```python",
"# Placeholder. Here you need to put the code for the file",
"```",
- "!@>Code Builder:"
+ f"{start_header_id_template}Code Builder{end_header_id_template}"
])
code = self.fast_gen(global_prompt, max_title_length)
code_blocks = self.extract_code_blocks(code)
@@ -2772,7 +2769,11 @@ class APScript(StateMachine):
Returns:
str: The generated title.
"""
- global_prompt = f"!@>instructions: Based on the provided prompt, suggest a concise and relevant title that captures the main topic or theme of the conversation. Only return the suggested title, without any additional text or explanation.\n!@>prompt: {prompt}\n!@>title:"
+ start_header_id_template = self.config.start_header_id_template
+ separator_template = self.config.separator_template
+ end_header_id_template = self.config.end_header_id_template
+ system_message_template = self.config.system_message_template
+ global_prompt = f"{start_header_id_template}{system_message_template}{end_header_id_template}Based on the provided prompt, suggest a concise and relevant title that captures the main topic or theme of the conversation. Only return the suggested title, without any additional text or explanation.{separator_template}{start_header_id_template}prompt{end_header_id_template}{prompt}{separator_template}{start_header_id_template}title{end_header_id_template}"
title = self.fast_gen(global_prompt,max_title_length)
return title
@@ -2788,12 +2789,16 @@ class APScript(StateMachine):
Returns:
int: Index of the selected option within the possible_ansers list. Or -1 if there was not match found among any of them.
"""
- template = """!@>instruction:
+ start_header_id_template = self.config.start_header_id_template
+ end_header_id_template = self.config.end_header_id_template
+ system_message_template = self.config.system_message_template
+
+ template = f"""{start_header_id_template}{system_message_template}{end_header_id_template}
Act as plan builder, a tool capable of making plans to perform the user requested operation.
"""
if len(actions_list)>0:
- template +="""The plan builder is an AI that responds in json format. It should plan a succession of actions in order to reach the objective.
-!@>list of action types information:
+ template +=f"""The plan builder is an AI that responds in json format. It should plan a succession of actions in order to reach the objective.
+{start_header_id_template}list of action types information{end_header_id_template}
[
{{actions_list}}
]
@@ -2817,12 +2822,12 @@ The AI should respond in this format using data from actions_list:
}
"""
if context!="":
- template += """!@>Context:
+ template += f"""{start_header_id_template}context{end_header_id_template}
{{context}}Ok
"""
- template +="""!@>request: {{request}}
+ template +=f"""{start_header_id_template}request{end_header_id_template}{{request}}
"""
- template +="""!@>plan: To acheive the requested objective, this is the list of actions to follow, formatted as requested in json format:\n```json\n"""
+ template +=f"""{start_header_id_template}plan{end_header_id_template}To acheive the requested objective, this is the list of actions to follow, formatted as requested in json format:\n```json\n"""
pr = PromptReshaper(template)
prompt = pr.build({
"context":context,
@@ -2851,12 +2856,16 @@ The AI should respond in this format using data from actions_list:
Returns:
int: Index of the selected option within the possible_ansers list. Or -1 if there was not match found among any of them.
"""
- template = """!@>instruction:
+ start_header_id_template = self.config.start_header_id_template
+ end_header_id_template = self.config.end_header_id_template
+ system_message_template = self.config.system_message_template
+
+ template = f"""{start_header_id_template}instruction:
Act as plan builder, a tool capable of making plans to perform the user requested operation.
"""
if len(actions_list)>0:
- template +="""The plan builder is an AI that responds in json format. It should plan a succession of actions in order to reach the objective.
-!@>list of action types information:
+ template +=f"""The plan builder is an AI that responds in json format. It should plan a succession of actions in order to reach the objective.
+{start_header_id_template}list of action types information{end_header_id_template}
[
{{actions_list}}
]
@@ -2880,12 +2889,12 @@ The AI should respond in this format using data from actions_list:
}
"""
if context!="":
- template += """!@>Context:
+ template += f"""{start_header_id_template}context{end_header_id_template}
{{context}}Ok
"""
- template +="""!@>request: {{request}}
+ template +=f"""{start_header_id_template}request{end_header_id_template}{{request}}
"""
- template +="""!@>plan: To acheive the requested objective, this is the list of actions to follow, formatted as requested in json format:\n```json\n"""
+ template +=f"""{start_header_id_template}plan{end_header_id_template}To acheive the requested objective, this is the list of actions to follow, formatted as requested in json format:\n```json\n"""
pr = PromptReshaper(template)
prompt = pr.build({
"context":context,
@@ -3012,17 +3021,21 @@ The AI should respond in this format using data from actions_list:
def build_and_execute_python_code(self,context, instructions, execution_function_signature, extra_imports=""):
+ start_header_id_template = self.config.start_header_id_template
+ end_header_id_template = self.config.end_header_id_template
+ system_message_template = self.config.system_message_template
+
code = "```python\n"+self.fast_gen(
self.build_prompt([
- "!@>context!:",
+ f"{start_header_id_template}context{end_header_id_template}",
context,
- f"!@>system:",
+ f"{start_header_id_template}{system_message_template}{end_header_id_template}",
f"{instructions}",
f"Here is the signature of the function:\n{execution_function_signature}",
"Don't call the function, just write it",
"Do not provide usage example.",
"The code must me without comments",
- f"!@>coder: Sure, in the following code, I import the necessary libraries, then define the function as you asked.",
+ f"{start_header_id_template}coder{end_header_id_template}Sure, in the following code, I import the necessary libraries, then define the function as you asked.",
"The function is ready to be used in your code and performs the task as you asked:",
"```python\n"
],2), callback=self.sink)
@@ -3070,15 +3083,19 @@ The AI should respond in this format using data from actions_list:
Returns:
int: Index of the selected option within the possible_ansers list. Or -1 if there was not match found among any of them.
"""
+ start_header_id_template = self.config.start_header_id_template
+ end_header_id_template = self.config.end_header_id_template
+ system_message_template = self.config.system_message_template
+
choices = "\n".join([f"{i}. {possible_answer}" for i, possible_answer in enumerate(possible_answers)])
elements = [conditionning] if conditionning!="" else []
elements += [
- "!@>system:",
+ f"{start_header_id_template}{system_message_template}{end_header_id_template}",
"Answer this multi choices question.",
]
if context!="":
elements+=[
- "!@>Context:",
+ f"{start_header_id_template}Context{end_header_id_template}",
f"{context}",
]
elements +=[
@@ -3088,11 +3105,11 @@ The AI should respond in this format using data from actions_list:
"the output should be an integer."
]
elements += [
- f"!@>question: {question}",
- "!@>possible answers:",
+ f"{start_header_id_template}question{end_header_id_template}{question}",
+ f"{start_header_id_template}possible answers{end_header_id_template}",
f"{choices}",
]
- elements += ["!@>answer:"]
+ elements += [f"{start_header_id_template}answer{end_header_id_template}"]
prompt = self.build_prompt(elements)
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, callback=self.sink).strip().replace("","").replace("","")
@@ -3120,24 +3137,28 @@ The AI should respond in this format using data from actions_list:
Returns:
int: Index of the selected option within the possible_ansers list. Or -1 if there was not match found among any of them.
"""
+ start_header_id_template = self.config.start_header_id_template
+ end_header_id_template = self.config.end_header_id_template
+ system_message_template = self.config.system_message_template
+
choices = "\n".join([f"{i}. {possible_answer}" for i, possible_answer in enumerate(possible_answers)])
elements = [conditionning] if conditionning!="" else []
elements += [
- "!@>instructions:",
+ f"{start_header_id_template}instructions{end_header_id_template}",
"Answer this multi choices question.",
"Answer with an id from the possible answers.",
"Do not answer with an id outside this possible answers.",
- f"!@>question: {question}",
- "!@>possible answers:",
+ f"{start_header_id_template}question{end_header_id_template}{question}",
+ f"{start_header_id_template}possible answers{end_header_id_template}",
f"{choices}",
]
if context!="":
elements+=[
- "!@>Context:",
+ f"{start_header_id_template}context{end_header_id_template}",
f"{context}",
]
- elements += ["!@>answer:"]
+ elements += [f"{start_header_id_template}answer{end_header_id_template}"]
prompt = self.build_prompt(elements)
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("","").replace("","")
@@ -3373,24 +3394,28 @@ The AI should respond in this format using data from actions_list:
Returns:
str: The upgraded prompt that includes information about the function calls.
"""
- function_descriptions = ["!@>information: If you need to call a function to fulfull the user request, use a function markdown tag with the function call as the following json format:",
+ start_header_id_template = self.config.start_header_id_template
+ end_header_id_template = self.config.end_header_id_template
+ system_message_template = self.config.system_message_template
+
+ function_descriptions = [f"{start_header_id_template}{system_message_template}{end_header_id_template}If you need to call a function to fulfull the user request, use a function markdown tag with the function call as the following json format:",
"```function",
"{",
'"function_name":the name of the function to be called,',
'"function_parameters": a list of parameter values',
"}",
"```",
+ "Only use available functions.",
"You can call multiple functions in one generation.",
"Each function call needs to be in a separate function markdown tag.",
"Do not add status of the execution as it will be added automatically by the system.",
- "If you want to get the output of the function before answering the user, then use the keyword @@ at the end of your message.",
- "!@>List of possible functions to be called:\n"]
+ f"{start_header_id_template}Available functions{end_header_id_template}\n"]
for function in functions:
description = f"{function['function_name']}: {function['function_description']}\nparameters:{function['function_parameters']}"
function_descriptions.append(description)
# Combine the function descriptions with the original prompt.
- function_info = ' '.join(function_descriptions)
+ function_info = '\n'.join(function_descriptions)
upgraded_prompt = f"{function_info}\n{prompt}"
return upgraded_prompt
@@ -3405,6 +3430,7 @@ The AI should respond in this format using data from actions_list:
Returns:
List[Dict[str, Any]]: A list of dictionaries representing the function calls.
"""
+
# Extract markdown code blocks that contain JSON.
code_blocks = self.extract_code_blocks(text)
@@ -3427,7 +3453,18 @@ The AI should respond in this format using data from actions_list:
return function_calls
- def interact_with_function_call(self, prompt, function_definitions, prompt_after_execution=True, callback = None, hide_function_call=False):
+ def interact_with_function_call(
+ self,
+ prompt,
+ function_definitions,
+ prompt_after_execution=True,
+ callback = None,
+ hide_function_call=False,
+ separate_output=False):
+ start_header_id_template = self.config.start_header_id_template
+ end_header_id_template = self.config.end_header_id_template
+ system_message_template = self.config.system_message_template
+ separator_template = self.config.separator_template
final_output = ""
if len(self.personality.image_files)>0:
out, function_calls = self.generate_with_function_calls_and_images(prompt, self.personality.image_files, function_definitions, callback=callback)
@@ -3438,9 +3475,12 @@ The AI should respond in this format using data from actions_list:
self.full("") #Hide function call
outputs = self.execute_function_calls(function_calls,function_definitions)
final_output = "\n".join([str(o) if type(o)==str else str(o[0]) if (type(o)==tuple or type(0)==list) and len(o)>0 else "" for o in outputs])
- out += "\n!@>function calls results:\n" + final_output
+ out += f"{separator_template}{start_header_id_template}function calls results{end_header_id_template}\n" + final_output
if prompt_after_execution:
- prompt += out +"\n"+ "!@>"+self.personality.name+":"
+ if separate_output:
+ self.full(final_output)
+ self.new_message("")
+ prompt += out +"\n"+ f"{start_header_id_template}"+self.personality.name+f"{end_header_id_template}"
if len(self.personality.image_files)>0:
out, function_calls = self.generate_with_function_calls_and_images(prompt, self.personality.image_files, function_definitions, callback=callback)
else:
@@ -3449,8 +3489,8 @@ The AI should respond in this format using data from actions_list:
if len(function_calls)>0:
outputs = self.execute_function_calls(function_calls,function_definitions)
final_output = "\n".join([str(o) if type(o)==str else str(o[0]) if (type(o)==tuple or type(0)==list) and len(o)>0 else "" for o in outputs])
- out += "\n!@>function calls results:\n" + final_output
- prompt += out +"\n"+ "!@>"+self.personality.name+":"
+ out += f"{separator_template}{start_header_id_template}function calls results{end_header_id_template}\n" + final_output
+ prompt += out +"\n"+ f"{start_header_id_template}"+self.personality.name+f"{end_header_id_template}"
else:
final_output = out
return final_output
diff --git a/lollms/server/configs/config.yaml b/lollms/server/configs/config.yaml
index e67efc4..5a540d3 100644
--- a/lollms/server/configs/config.yaml
+++ b/lollms/server/configs/config.yaml
@@ -1,5 +1,5 @@
# =================== Lord Of Large Language Multimodal Systems Configuration file ===========================
-version: 104
+version: 106
binding_name: null
model_name: null
model_variant: null
@@ -29,6 +29,11 @@ app_custom_logo: ""
# Genreration parameters
discussion_prompt_separator: "!@>"
+start_header_id_template: "!@>"
+end_header_id_template: ": "
+separator_template: "\n"
+system_message_template: "system"
+
seed: -1
ctx_size: 4084
max_n_predict: 4096
diff --git a/lollms/server/endpoints/lollms_generator.py b/lollms/server/endpoints/lollms_generator.py
index a1d2698..c1b9993 100644
--- a/lollms/server/endpoints/lollms_generator.py
+++ b/lollms/server/endpoints/lollms_generator.py
@@ -457,12 +457,12 @@ async def v1_chat_completions(request: ChatGenerationRequest):
roles= False
for message in messages:
if message.role!="":
- prompt += f"!@>{message.role}: {message.content}\n"
+ prompt += f"{elf_server.config.discussion_prompt_separator}{message.role}: {message.content}\n"
roles = True
else:
prompt += f"{message.content}\n"
if roles:
- prompt += "!@>assistant:"
+ prompt += f"{elf_server.config.discussion_prompt_separator}assistant:"
n_predict = max_tokens if max_tokens>0 else 1024
stream = request.stream
prompt_tokens = len(elf_server.binding.tokenize(prompt))
@@ -599,12 +599,12 @@ async def ollama_chat_completion(request: ChatGenerationRequest):
roles= False
for message in messages:
if message.role!="":
- prompt += f"!@>{message.role}: {message.content}\n"
+ prompt += f"{elf_server.config.discussion_prompt_separator}{message.role}: {message.content}\n"
roles = True
else:
prompt += f"{message.content}\n"
if roles:
- prompt += "!@>assistant:"
+ prompt += f"{elf_server.config.discussion_prompt_separator}assistant:"
n_predict = max_tokens if max_tokens>0 else 1024
stream = request.stream
prompt_tokens = len(elf_server.binding.tokenize(prompt))
diff --git a/lollms/server/events/lollms_generation_events.py b/lollms/server/events/lollms_generation_events.py
index 3de79a8..a55dd60 100644
--- a/lollms/server/events/lollms_generation_events.py
+++ b/lollms/server/events/lollms_generation_events.py
@@ -76,6 +76,9 @@ def add_events(sio:socketio):
prompt = model.detokenize(tokenized[-n_crop:])
n_predicts = data["n_predicts"]
+ if n_predicts is None:
+ n_predicts = lollmsElfServer.config.max_n_predict
+
parameters = data.get("parameters",{
"temperature":lollmsElfServer.config["temperature"],
"top_k":lollmsElfServer.config["top_k"],
@@ -176,7 +179,7 @@ def add_events(sio:socketio):
tk = personality.model.tokenize(full_discussion)
n_tokens = len(tk)
- fd = personality.model.detokenize(tk[-min(lollmsElfServer.config.ctx_size-n_cond_tk-personality.model_n_predicts,n_tokens):])
+ fd = personality.model.detokenize(tk[-min(lollmsElfServer.config.ctx_size-n_cond_tk-n_predicts, n_tokens):])
if personality.processor is not None and personality.processor_cfg["custom_workflow"]:
ASCIIColors.info("processing...")
@@ -188,7 +191,7 @@ def add_events(sio:socketio):
ASCIIColors.info("generating...")
generated_text = personality.model.generate(
personality.personality_conditioning+fd,
- n_predict=personality.model_n_predicts,
+ n_predict=n_predicts,
callback=callback)
if personality.processor is not None and personality.processor_cfg["process_model_output"]:
diff --git a/lollms/services/dalle/lollms_dalle.py b/lollms/services/dalle/lollms_dalle.py
index 6ee6ce0..c9e7fc1 100644
--- a/lollms/services/dalle/lollms_dalle.py
+++ b/lollms/services/dalle/lollms_dalle.py
@@ -51,6 +51,7 @@ class LollmsDalle(LollmsTTI):
def paint(
self,
prompt,
+ negative_prompt,
width=512,
height=512,
images = [],
diff --git a/lollms/services/diffusers/lollms_diffusers.py b/lollms/services/diffusers/lollms_diffusers.py
index 5048ef9..46217cf 100644
--- a/lollms/services/diffusers/lollms_diffusers.py
+++ b/lollms/services/diffusers/lollms_diffusers.py
@@ -156,8 +156,8 @@ class LollmsDiffusers(LollmsTTI):
def paint(
self,
- diffusers_positive_prompt,
- diffusers_negative_prompt,
+ positive_prompt,
+ negative_prompt,
files=[],
sampler_name="Euler",
seed=-1,
@@ -172,10 +172,10 @@ class LollmsDiffusers(LollmsTTI):
if output_path is None:
output_path = self.output_dir
from diffusers.utils.pil_utils import pt_to_pil
- image = self.model(diffusers_positive_prompt, negative_prompt=diffusers_negative_prompt, guidance_scale=scale, num_inference_steps=steps,).images[0]
+ image = self.model(positive_prompt, negative_prompt=negative_prompt, guidance_scale=scale, num_inference_steps=steps,).images[0]
output_path = Path(output_path)
fn = find_next_available_filename(output_path,"diff_img_")
# Save the image
image.save(fn)
- return fn, {"prompt":diffusers_positive_prompt, "negative_prompt":diffusers_negative_prompt}
+ return fn, {"prompt":positive_prompt, "negative_prompt":negative_prompt}
diff --git a/lollms/services/midjourney/lollms_midjourney.py b/lollms/services/midjourney/lollms_midjourney.py
index d31d212..ed683a5 100644
--- a/lollms/services/midjourney/lollms_midjourney.py
+++ b/lollms/services/midjourney/lollms_midjourney.py
@@ -50,7 +50,8 @@ class LollmsMidjourney(LollmsTTI):
def paint(
self,
- prompt,
+ positive_prompt,
+ negative_prompt,
width=512,
height=512,
images = [],
@@ -111,7 +112,7 @@ class LollmsMidjourney(LollmsTTI):
else:
response = openai.images.generate(
model=generation_engine,
- prompt=prompt.strip(),
+ positive_prompt=positive_prompt.strip(),
quality="standard",
size=f"{width}x{height}",
n=1,
diff --git a/lollms/services/sd/lollms_sd.py b/lollms/services/sd/lollms_sd.py
index 0852174..a3f87d5 100644
--- a/lollms/services/sd/lollms_sd.py
+++ b/lollms/services/sd/lollms_sd.py
@@ -356,8 +356,8 @@ class LollmsSD(LollmsTTI):
def paint(
self,
- sd_positive_prompt,
- sd_negative_prompt,
+ positive_prompt,
+ negative_prompt,
files=[],
sampler_name="Euler",
seed=-1,
@@ -376,8 +376,8 @@ class LollmsSD(LollmsTTI):
if len(files)>0:
try:
generated = self.img2img(
- sd_positive_prompt,
- sd_negative_prompt,
+ positive_prompt,
+ negative_prompt,
[self.loadImage(files[-1])],
sampler_name=sampler_name,
seed=seed,
@@ -405,8 +405,8 @@ class LollmsSD(LollmsTTI):
else:
try:
generated = self.txt2img(
- sd_positive_prompt,
- negative_prompt=sd_negative_prompt,
+ positive_prompt,
+ negative_prompt=negative_prompt,
sampler_name=sampler_name,
seed=seed,
cfg_scale=scale,
diff --git a/lollms/services/xtts/lollms_xtts.py b/lollms/services/xtts/lollms_xtts.py
index 5ea0016..fc27651 100644
--- a/lollms/services/xtts/lollms_xtts.py
+++ b/lollms/services/xtts/lollms_xtts.py
@@ -190,15 +190,17 @@ class LollmsXTTS(LollmsTTS):
def update_settings(self):
try:
settings = {
- "stream_chunk_size": self.app.config.xtts_stream_chunk_size,
- "temperature": self.app.config.xtts_temperature,
- "speed": self.app.config.xtts_speed,
- "length_penalty": self.app.config.xtts_length_penalty,
- "repetition_penalty": self.app.config.xtts_repetition_penalty,
- "top_p": self.app.config.xtts_top_p,
- "top_k": self.app.config.xtts_top_k,
- "enable_text_splitting": self.app.config.xtts_enable_text_splitting
- }
+ "stream_chunk_size": int(self.app.config.xtts_stream_chunk_size),
+ "temperature": float(self.app.config.xtts_temperature),
+ "speed": float(self.app.config.xtts_speed),
+ "length_penalty": float(self.app.config.xtts_length_penalty),
+ "repetition_penalty": float(self.app.config.xtts_repetition_penalty),
+ "top_p": float(self.app.config.xtts_top_p),
+ "top_k": int(self.app.config.xtts_top_k),
+ "enable_text_splitting": bool(self.app.config.xtts_enable_text_splitting)
+ }
+ print("set_tts_settings")
+ print(f"{settings}")
response = requests.post(f"{self.xtts_base_url}/set_tts_settings", settings,headers={
'accept': 'application/json',
'Content-Type': 'application/json'
diff --git a/lollms/tasks.py b/lollms/tasks.py
index 4d341d7..5499fa7 100644
--- a/lollms/tasks.py
+++ b/lollms/tasks.py
@@ -12,8 +12,11 @@ import json
class TasksLibrary:
def __init__(self, lollms:LoLLMsCom, callback: Callable[[str, MSG_TYPE, dict, list], bool]=None) -> None:
self.lollms = lollms
+ self.config = lollms.config
self.callback = callback
- self.anti_prompts = [self.lollms.config.discussion_prompt_separator]+["!@>"]
+ self.anti_prompts = [lollms.config.discussion_prompt_separator]
+ if lollms.config.separator_template!="\n":
+ self.anti_prompts.append(lollms.config.separator_template)
def print_prompt(self, title, prompt):
ASCIIColors.red("*-*-*-*-*-*-*-* ", end="")
@@ -182,8 +185,12 @@ class TasksLibrary:
Returns:
- str: The generated text after removing special tokens ("" and "") and stripping any leading/trailing whitespace.
"""
+ start_header_id_template = self.config.start_header_id_template
+ end_header_id_template = self.config.end_header_id_template
+ system_message_template = self.config.system_message_template
+ separator_template = self.config.separator_template
prompt = "\n".join([
- "!@>system: I am an AI assistant that can converse and analyze images. When asked to locate something in an image you send, I will reply with:",
+ f"{start_header_id_template}{system_message_template}{end_header_id_template}I am an AI assistant that can converse and analyze images. When asked to locate something in an image you send, I will reply with:",
"boundingbox(image_index, label, left, top, width, height)",
"Where:",
"image_index: 0-based index of the image",
@@ -510,25 +517,33 @@ class TasksLibrary:
return code_blocks
def translate_conditionning(self, prompt, original_language, language):
- conditionning_translation_text = f"!@>instruction: Translate the following prompt to {language}.\nDo not translate any css or code, just the text and strings.\n!@>prompt:\n```{original_language}\n{prompt.replace('!@>','')}\n```\n!@>translation:\nHere is the translated prompt:\n```{language}\n"
+ start_header_id_template = self.config.start_header_id_template
+ end_header_id_template = self.config.end_header_id_template
+ system_message_template = self.config.system_message_template
+ separator_template = self.config.separator_template
+ conditionning_translation_text = f"{start_header_id_template}{system_message_template}{end_header_id_template}Translate the following prompt to {language}.\nDo not translate any css or code, just the text and strings.{separator_template}{start_header_id_template}prompt{end_header_id_template}\n```{original_language}\n{prompt.replace(f'{start_header_id_template}','')}\n```{separator_template}{start_header_id_template}translation{end_header_id_template}\nHere is the translated prompt:\n```{language}\n"
cond_translation = f"```{language}\n"+self.fast_gen(conditionning_translation_text, temperature=0.1, callback=self.sink)
response = self.extract_code_blocks(cond_translation)
if len(response)>0 and len(response[0]["content"])>0:
- conditionning = "!@>system: "+response[0]["content"]
+ conditionning = response[0]["content"]
else:
ASCIIColors.print(f"Failed to translate the conditionning message. Reverting to english conditionning with a request to use the lanuage {language}")
conditionning = prompt + f"\nAlways answer in {language}\n"
return conditionning
def translate_message(self, prompt, original_language, language):
- message_translation_text = f"!@>instruction: Translate the following message to {language}.\nDo not translate any css or code, just the text and strings.\n!@>prompt:\n```{original_language}\n{prompt.replace('!@>','')}\n```\n!@>translation:\n```{language}\n"
+ start_header_id_template = self.config.start_header_id_template
+ end_header_id_template = self.config.end_header_id_template
+ system_message_template = self.config.system_message_template
+ separator_template = self.config.separator_template
+ message_translation_text = f"{start_header_id_template}{system_message_template}{end_header_id_template}Translate the following message to {language}.\nDo not translate any css or code, just the text and strings.{separator_template}{start_header_id_template}prompt:\n```{original_language}\n{prompt.replace(f'{start_header_id_template}','')}\n```{separator_template}{start_header_id_template}translation{end_header_id_template}\n```{language}\n"
cond_translation = f"```{language}\n"+self.fast_gen(message_translation_text, temperature=0.1, callback=self.sink)
response = self.extract_code_blocks(cond_translation)
if len(response)>0 and len(response[0]["content"])>0:
translated = response[0]["content"]
else:
ASCIIColors.print(f"Failed to translate the message. Reverting to english conditionning with a request to use the lanuage {language}")
- message_translation_text = f"!@>instruction: Translate the following message to {language}.\nDo not translate any css or code, just the text and strings.\n!@>message:\n{prompt.replace('!@>','')}\n!@>translation:\n"
+ message_translation_text = f"{start_header_id_template}{system_message_template}{end_header_id_template}Translate the following message to {language}.\nDo not translate any css or code, just the text and strings.{separator_template}{start_header_id_template}message{end_header_id_template}\n{prompt.replace(f'{start_header_id_template}','')}{separator_template}{start_header_id_template}translation{end_header_id_template}\n"
translated = self.fast_gen(message_translation_text, temperature=0.1, callback=self.sink)
return translated
@@ -630,6 +645,10 @@ class TasksLibrary:
chunk_summary_post_processing=None,
summary_mode=SUMMARY_MODE.SUMMARY_MODE_SEQUENCIAL
):
+ start_header_id_template = self.config.start_header_id_template
+ end_header_id_template = self.config.end_header_id_template
+ system_message_template = self.config.system_message_template
+ separator_template = self.config.separator_template
if summary_mode==SUMMARY_MODE.SUMMARY_MODE_SEQUENCIAL:
summary = ""
for i, chunk in enumerate(chunks):
@@ -637,16 +656,16 @@ class TasksLibrary:
if summary !="":
summary = f"{answer_start}"+ self.fast_gen(
"\n".join([
- f"!@>Document_chunk: {doc_name}:",
+ f"{start_header_id_template}Document_chunk: {doc_name}{end_header_id_template}",
f"This is a cumulative summary step. Use the summary of the previous chunks and the current chunk of the document to make a new summary integrating information from both. Make sure not to loose information from previous summaries",
f"Summary of previous chunks",
f"{summary}",
f"current chunk:",
f"{chunk}",
- f"!@>instruction: {summary_instruction}",
+ f"{start_header_id_template}{system_message_template}{end_header_id_template}{summary_instruction}",
f"The summary should extract required information from the current chunk to increment the previous summary.",
f"Answer directly with the cumulative summary with no extra comments.",
- f"!@>summary:",
+ f"{start_header_id_template}summary{end_header_id_template}",
f"{answer_start}"
]),
max_generation_size=max_generation_size,
@@ -654,12 +673,12 @@ class TasksLibrary:
else:
summary = f"{answer_start}"+ self.fast_gen(
"\n".join([
- f"!@>Document_chunk: {doc_name}:",
+ f"{start_header_id_template}Document_chunk: {doc_name}{end_header_id_template}",
f"current chunk:",
f"{chunk}",
- f"!@>instruction: {summary_instruction}",
+ f"{start_header_id_template}{system_message_template}{end_header_id_template}{summary_instruction}",
f"Answer directly with the summary with no extra comments.",
- f"!@>summary:",
+ f"{start_header_id_template}summary{end_header_id_template}",
f"{answer_start}"
]),
max_generation_size=max_generation_size,
@@ -674,11 +693,11 @@ class TasksLibrary:
self.step_start(f" Summary of {doc_name} - Processing chunk : {i+1}/{len(chunks)}")
summary = f"{answer_start}"+ self.fast_gen(
"\n".join([
- f"!@>Document_chunk [{doc_name}]:",
+ f"{start_header_id_template}Document_chunk [{doc_name}]{end_header_id_template}",
f"{chunk}",
- f"!@>instruction: {summary_instruction}",
+ f"{start_header_id_template}{system_message_template}{end_header_id_template}{summary_instruction}",
f"Answer directly with the summary with no extra comments.",
- f"!@>summary:",
+ f"{start_header_id_template}summary{end_header_id_template}",
f"{answer_start}"
]),
max_generation_size=max_generation_size,
@@ -699,6 +718,10 @@ class TasksLibrary:
callback=None,
chunk_summary_post_processing=None
):
+ start_header_id_template = self.config.start_header_id_template
+ end_header_id_template = self.config.end_header_id_template
+ system_message_template = self.config.system_message_template
+ separator_template = self.config.separator_template
summeries = []
for i, chunk in enumerate(chunks):
if iDocument_chunk: {doc_name}:",
+ f"{start_header_id_template}Document_chunk: {doc_name}{end_header_id_template}",
f"Block1:",
f"{chunk}",
f"Block2:",
f"{chunk1}",
- f"!@>instruction: {summary_instruction}",
+ f"{start_header_id_template}{system_message_template}{end_header_id_template}{summary_instruction}",
f"Answer directly with the summary with no extra comments.",
- f"!@>summary:",
+ f"{start_header_id_template}summary{end_header_id_template}:",
f"{answer_start}"
]),
max_generation_size=max_generation_size,
@@ -740,7 +763,11 @@ class TasksLibrary:
Returns:
str: The upgraded prompt that includes information about the function calls.
"""
- function_descriptions = ["!@>information: If you need to call a function to fulfull the user request, use a function markdown tag with the function call as the following json format:",
+ start_header_id_template = self.config.start_header_id_template
+ end_header_id_template = self.config.end_header_id_template
+ system_message_template = self.config.system_message_template
+ separator_template = self.config.separator_template
+ function_descriptions = [f"{start_header_id_template}information{end_header_id_template}If you need to call a function to fulfull the user request, use a function markdown tag with the function call as the following json format:",
"```function",
"{",
'"function_name":the name of the function to be called,',
@@ -750,8 +777,7 @@ class TasksLibrary:
"You can call multiple functions in one generation.",
"Each function call needs to be in a separate function markdown tag.",
"Do not add status of the execution as it will be added automatically by the system.",
- "If you want to get the output of the function before answering the user, then use the keyword @@ at the end of your message.",
- "!@>List of possible functions to be called:\n"]
+ f"{start_header_id_template}List of possible functions to be called{end_header_id_template}\n"]
for function in functions:
description = f"{function['function_name']}: {function['function_description']}\nparameters:{function['function_parameters']}"
function_descriptions.append(description)
diff --git a/lollms/tti.py b/lollms/tti.py
index 96cede4..18921c0 100644
--- a/lollms/tti.py
+++ b/lollms/tti.py
@@ -48,7 +48,14 @@ class LollmsTTI:
self.voices = [] # To be filled by the child class
self.models = [] # To be filled by the child class
- def paint(self, positive_prompt: str, negative_prompt: str = "") -> List[Dict[str, str]]:
+ def paint(self,
+ positive_prompt: str,
+ negative_prompt: str = "",
+ width=512,
+ height=512,
+ images = [],
+ generation_engine=None,
+ output_path = None) -> List[Dict[str, str]]:
"""
Generates images based on the given positive and negative prompts.