chatbot / main.py
JDWebProgrammer's picture
Upload 17 files
964d65a
from ctransformers import AutoModelForCausalLM, AutoConfig
from sentence_transformers import SentenceTransformer
from chromadb.utils import embedding_functions
from chromadb.config import Settings
from pathlib import Path
import chromadb
import os
import json
# TheBloke/deepseek-coder-33B-instruct-GGUF "ddh0/Yi-6B-200K-GGUF-fp16"
# "TheBloke/Mistral-7B-Code-16K-qlora-GGUF" # "TheBloke/Mistral-7B-Instruct-v0.1-GGUF" # "TheBloke/Mistral-7B-OpenOrca-GGUF"
# "NousResearch/Yarn-Mistral-7b-128k" "JDWebProgrammer/custom_sft_adapter"
MODEL_HF = "TheBloke/Yarn-Mistral-7B-128k-GGUF"
EMBEDDING_MODEL = "sentence-transformers/all-MiniLM-L6-v2"
class AppModel:
def __init__(self, embedding_model_name=EMBEDDING_MODEL, model=MODEL_HF, dataset_path="./data/logs", dir="./data",
context_limit=32000, temperature=0.8, max_new_tokens=4096, context_length=128000):
self.model = model
self.embedding_model_name = embedding_model_name
self.model_config = AutoConfig.from_pretrained(self.model, context_length=context_length)
self.emb_fn = embedding_functions.SentenceTransformerEmbeddingFunction(model_name=self.embedding_model_name.split("/")[1])
self.chroma_client = chromadb.PersistentClient(path="./data/vectorstore", settings=Settings(anonymized_telemetry=False))
self.sentences = []
self.ref_collection = self.chroma_client.get_or_create_collection("ref", embedding_function=self.emb_fn)
self.logs_collection = self.chroma_client.get_or_create_collection("logs", embedding_function=self.emb_fn)
self.init_chroma()
self.embedding_model = SentenceTransformer(self.embedding_model_name)
self.llm = AutoModelForCausalLM.from_pretrained(self.model, model_type="mistral", config=self.model_config) #, cache_dir="./models" , gpu_layers=0 local_files_only=True) ,
self.chat_log = []
self.last_ai_response = ""
self.last_user_prompt = ""
self.context_limit=context_limit
self.temperature=temperature
self.max_new_tokens=max_new_tokens
def get_llm_query(self, input_prompt, user_prompt):
self.last_user_prompt = str(user_prompt)
new_response = self.llm(prompt=input_prompt, temperature=self.temperature, max_new_tokens=self.max_new_tokens) #, temperature=self.temperature, max_new_tokens=self.max_new_tokens)
self.last_ai_response = str(new_response)
self.save_file(f"[User_Prompt]: {user_prompt} \n[AI_Response]: {new_response} \n", "./data/logs/chat-log.txt")
return new_response
def get_embedding_values(self, input_str):
tokenized_input = self.build_embeddings(input_str)
print(tokenized_input)
embedding_values = self.embedding_model.encode(tokenized_input)
return embedding_values
def get_embedding_docs(self, query_text, n_results=2):
query_embeddings = self.get_embedding_values(query_text).tolist()[0]
query_result = self.ref_collection.query(query_embeddings=query_embeddings,n_results=n_results)
return query_result["documents"]
def init_chroma(self):
docs, metas, ids = self.build_chroma_docs(directory="./data/reference", id_name="ref_")
if docs:
print(f"Loading Chroma (Reference) Docs: {len(docs)}")
self.ref_collection.add(documents=docs, metadatas=metas, ids=ids)
docs, metas, ids = self.build_chroma_docs(directory="./data/context", id_name="context_")
if docs:
print(f"Loading Chroma (Context) Docs: {len(docs)}")
self.logs_collection.add(documents=docs, metadatas=metas, ids=ids)
def build_chroma_docs(self, directory="./data/context", id_name="doc_", metatag={"source": "notion"}):
directory = os.path.join(os.getcwd(), directory)
docs = []
metas = []
ids = []
fnum = 0
for filename in os.listdir(directory):
file_path = os.path.join(directory, filename)
with open(file_path, 'r') as file:
file_contents = file.read()
splitter = "\n\n"
if ".csv" in file_path:
splitter = "\n"
anum = 0
for a in file_contents.split(splitter): # split first by paragraph
docs.append(a)
ids.append(id_name + str(fnum))
additional_metas = {"dir": directory, "filename":file_path, "chunk_number": anum }
metas.append({**metatag, **additional_metas})
fnum += 1
anum += 1
docs = list(docs)
metas = list(metas)
ids = list(ids)
return docs, metas, ids
def build_embeddings(self, content, add_sentences=False):
tokenized_sentences = []
for b in content.split("\n"): # then by line
for c in b.split(" "): # then by tab
for d in c.split(". "): # by sentence
tokenized_sentences.append(str(d))
if add_sentences:
self.sentences.append(str(d))
return tokenized_sentences
def save_file(self, data, filename="./data/context/chat-log.txt"):
with open(filename, 'a') as f:
f.write('\n\n' + str(data))
def add_feedback(self, is_positive=True):
feedback_str = ""
if is_positive:
feedback_str = "GOOD/PASS"
self.chat_log.append(self.last_ai_response[:self.context_limit])
self.save_file(self.last_ai_response)
else:
feedback_str = "BAD/FAIL"
new_obj = f"[User_Prompt]: {self.last_user_prompt}\n[AI_Response]: {self.last_ai_response}\n[User_Feedback]: {feedback_str}\n\n"
self.save_file(new_obj, "./data/logs/feedback-log.txt")
def open_file(self, file_path):
file_contents = ""
with open(file_path, "r") as file:
file_contents = file.read()
return file_contents