Spaces:
Running
Running
from langchain.chains import RetrievalQA | |
from langchain.prompts import PromptTemplate | |
from langchain.embeddings import OpenAIEmbeddings | |
# from langchain_community.embeddings import OpenAIEmbeddings | |
from langchain.vectorstores import Chroma | |
from src.utils import brian_knows_system_message | |
from uuid import uuid4 | |
import chromadb | |
from chromadb.config import Settings | |
from chromadb.utils import embedding_functions | |
import sys | |
import os | |
import openai | |
import logging | |
sys.path.append("../..") | |
from dotenv import load_dotenv, find_dotenv | |
_ = load_dotenv(find_dotenv()) # read local .env file | |
openai.api_key = os.environ["OPENAI_API_KEY"] | |
class VectordbManager: | |
def __init__( | |
self, | |
knowledge_base_name: str, | |
) -> None: | |
self.knowledge_base_name = knowledge_base_name | |
self.vector_db = None | |
def load_vectordb( | |
self, | |
embedding_function=OpenAIEmbeddings(), | |
): | |
client = chromadb.HttpClient( | |
host="chroma.brianknows.org", | |
port="443", | |
ssl=True, | |
settings=Settings(allow_reset=True), | |
) | |
vectordb = Chroma(embedding_function=embedding_function, client=client) | |
self.vector_db = vectordb | |
def load_collection(self, embedding_function=OpenAIEmbeddings()): | |
client = chromadb.HttpClient( | |
host="chroma.brianknows.org", | |
port=443, | |
ssl=True, | |
settings=Settings( | |
allow_reset=True, | |
), | |
) | |
collection = client.get_collection( | |
self.knowledge_base_name, | |
embedding_function=embedding_functions.OpenAIEmbeddingFunction( | |
api_key=os.environ["OPENAI_API_KEY"] | |
), | |
) | |
return collection | |
def create_vector_db(self, splits: list, knowledge_base_name: str): | |
logging.info("create_vector_db") | |
embedding_fn = OpenAIEmbeddings() | |
try: | |
client = chromadb.HttpClient( | |
host="chroma.brianknows.org", | |
port=443, | |
ssl=True, | |
settings=Settings( | |
allow_reset=True, | |
), | |
) | |
collection = client.get_or_create_collection( | |
knowledge_base_name, | |
embedding_function=embedding_functions.OpenAIEmbeddingFunction( | |
api_key=os.environ["OPENAI_API_KEY"] | |
), | |
) | |
ids = [] | |
metadatas = [] | |
documents = [] | |
for split in splits: | |
ids.append(str(uuid4())) | |
metadatas.append(split.metadata) | |
documents.append(split.page_content) | |
collection.add(documents=documents, ids=ids, metadatas=metadatas) | |
vector_db = Chroma.from_documents( | |
documents=splits, embedding=embedding_fn, client=client | |
) | |
self.vector_db = vector_db | |
except Exception as e: | |
logging.error(f"error in creating db: {str(e)}") | |
def add_splits_to_existing_vectordb( | |
self, | |
splits: list, | |
): | |
for split in splits: | |
try: | |
self.vector_db.add_documents([split]) | |
print("document loaded!") | |
except Exception as e: | |
print(f"Error with doc : {split}") | |
print(e) | |
def retrieve_docs_from_query(self, query: str, k=2, fetch_k=3) -> list: | |
""" | |
query : Text to look up documents similar to. | |
k : Number of Documents to return. Defaults to 4. | |
fetch_k : Number of Documents to fetch to pass to MMR algorithm. | |
lambda_mult : Number between 0 and 1 that determines the degree of diversity among the results with 0 corresponding to maximum diversity and 1 to minimum diversity. Defaults to 0.5. | |
""" | |
retrieved_docs = self.vector_db.max_marginal_relevance_search( | |
query, k=k, fetch_k=fetch_k | |
) | |
return retrieved_docs | |
def retrieve_qa( | |
self, | |
llm, | |
query: str, | |
score_threshold: float = 0.65, | |
system_message=brian_knows_system_message, | |
): | |
"""return llm answer based on docs""" | |
# Build prompt | |
template = """You are a Web3 assistant. Use the following pieces of context to answer the question at \ | |
the end. If you don't know the answer, just say: "I don't know". Don't try to make up an \ | |
answer! Provide a always a detailed and comprehensive response. """ | |
fixed_template = """ {context} | |
Question: {question} | |
Detailed Answer:""" | |
template = system_message + fixed_template | |
QA_CHAIN_PROMPT = PromptTemplate.from_template(template) | |
# Run chain | |
qa_chain = RetrievalQA.from_chain_type( | |
llm, | |
retriever=self.vector_db.as_retriever( | |
search_type="similarity_score_threshold", | |
search_kwargs={"score_threshold": score_threshold}, | |
), | |
return_source_documents=True, | |
chain_type_kwargs={"prompt": QA_CHAIN_PROMPT}, | |
# reduce_k_below_max_tokens=True, | |
) | |
result = qa_chain({"query": query}) | |
return result | |