RCaz commited on
Commit
b49d619
·
1 Parent(s): 329dee6

dev-retreiver --> include git project s readme

Browse files
Files changed (1) hide show
  1. agent/create_retreiver.py +159 -0
agent/create_retreiver.py ADDED
@@ -0,0 +1,159 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ # load files
3
+ from langchain_community.document_loaders import FileSystemBlobLoader
4
+ from langchain_community.document_loaders.generic import GenericLoader
5
+ from langchain_community.document_loaders.parsers import PyPDFParser
6
+
7
+ # split docs
8
+ from langchain_text_splitters import RecursiveCharacterTextSplitter
9
+ from langchain_core.documents import Document
10
+ from transformers import AutoTokenizer
11
+ from typing import List, Optional
12
+ from tqdm import tqdm
13
+
14
+ # create or load embeds
15
+ from langchain_community.vectorstores import FAISS
16
+ from langchain_community.vectorstores.utils import DistanceStrategy
17
+
18
+ from langchain_community.embeddings import HuggingFaceEmbeddings # deprecated
19
+ # from langchain_huggingface import HuggingFaceEmbeddings
20
+
21
+
22
+
23
+ def load_docs(root_path):
24
+ """ load all pdf documents from root folder 'data'"""
25
+ loader = GenericLoader(
26
+ blob_loader=FileSystemBlobLoader(
27
+ path="../",
28
+ glob=f"{root_path}/**/*.pdf",
29
+ ),
30
+ blob_parser=PyPDFParser(),
31
+ )
32
+
33
+ docs = loader.load()
34
+ return docs
35
+
36
+
37
+ # Split Langchain Document at 512 tokens to embed
38
+
39
+ def split_documents(
40
+ chunk_size: int,
41
+ RAW_KNOWLEDGE_BASE: List[Document],
42
+ tokenizer_name: Optional[str] ,
43
+ ) -> List[Document]:
44
+ """
45
+ Split documents into chunks of maximum size `chunk_size` tokens and return a list of documents.
46
+ """
47
+ text_splitter = RecursiveCharacterTextSplitter.from_huggingface_tokenizer(
48
+ AutoTokenizer.from_pretrained(tokenizer_name),
49
+ chunk_size=chunk_size,
50
+ chunk_overlap=int(chunk_size / 10),
51
+ add_start_index=True,
52
+ strip_whitespace=True,
53
+ separators=".",
54
+ )
55
+
56
+ docs_processed = text_splitter.split_documents(RAW_KNOWLEDGE_BASE)
57
+
58
+ # Remove duplicates
59
+ unique_texts = {}
60
+ docs_processed_unique = []
61
+ for doc in docs_processed:
62
+ if doc.page_content not in unique_texts:
63
+ unique_texts[doc.page_content] = True
64
+ docs_processed_unique.append(doc)
65
+
66
+ return docs_processed_unique
67
+
68
+
69
+
70
+
71
+
72
+ def create_or_load_embeddings(docs_processed,EMBEDDING_MODEL_NAME,VECTOR_DB_PATH):
73
+ # create the embedding model
74
+ embedding_model = HuggingFaceEmbeddings(
75
+ model_name=EMBEDDING_MODEL_NAME,
76
+ # multi_process=True,
77
+ model_kwargs={"device": "mps"}, # use cuda for faster embeddings on nbidia GPUs
78
+ encode_kwargs={"normalize_embeddings": True}, # Set `True` for cosine similarity
79
+ )
80
+
81
+ try:
82
+ # Load the vector database from the folder
83
+ KNOWLEDGE_VECTOR_DATABASE = FAISS.load_local(
84
+ VECTOR_DB_PATH,
85
+ embedding_model,
86
+ allow_dangerous_deserialization=True # Required for security in newer LangChain versions
87
+ )
88
+ return KNOWLEDGE_VECTOR_DATABASE
89
+
90
+ except:
91
+ # create the vector store
92
+ KNOWLEDGE_VECTOR_DATABASE = FAISS.from_documents(
93
+ docs_processed, embedding_model, distance_strategy=DistanceStrategy.COSINE
94
+ )
95
+ # Save the vector database
96
+ KNOWLEDGE_VECTOR_DATABASE.save_local(VECTOR_DB_PATH)
97
+ return KNOWLEDGE_VECTOR_DATABASE
98
+
99
+
100
+ def load_vector_store(EMBEDDING_MODEL_NAME,VECTOR_DB_PATH):
101
+ # create the embedding model
102
+ embedding_model = HuggingFaceEmbeddings(
103
+ model_name=EMBEDDING_MODEL_NAME,
104
+ # multi_process=True,
105
+ model_kwargs={"device": "mps"}, # use cuda for faster embeddings on nbidia GPUs
106
+ encode_kwargs={"normalize_embeddings": True}, # Set `True` for cosine similarity
107
+ )
108
+
109
+ try:
110
+ # Load the vector database from the folder
111
+ KNOWLEDGE_VECTOR_DATABASE = FAISS.load_local(
112
+ VECTOR_DB_PATH,
113
+ embedding_model,
114
+ allow_dangerous_deserialization=True # Required for security in newer LangChain versions
115
+ )
116
+ return KNOWLEDGE_VECTOR_DATABASE
117
+
118
+ except:
119
+ raise "no vector store"
120
+
121
+ if __name__ == "__main__":
122
+ try:
123
+ print("create embeddings")
124
+ raw_knowledge = load_docs("data")
125
+ print(f"found {len(raw_knowledge)} chunks")
126
+ ready_knowledge = split_documents(512,raw_knowledge,"intfloat/e5-base-v2")
127
+ vector_store = create_or_load_embeddings(ready_knowledge,"intfloat/e5-base-v2","data")
128
+ retriever = vector_store
129
+
130
+ except Exception as e:
131
+ print(e)
132
+
133
+
134
+ # # load files
135
+ # root_path = "data"
136
+ # RAW_KNOWLEDGE_BASE = load_docs(root_path)
137
+
138
+ # # split docs
139
+ # chunk_size=512
140
+ # # RAW_KNOWLEDGE_BASE = [
141
+ # # Document(page_content="\n".join([row["source"]] + row["text"].split("\n")[1:]),
142
+ # # metadata={"source": row["source"],
143
+ # # "date": row["text"].split("\n")[0]})
144
+
145
+ # # for _, row in tqdm(df.iterrows(), total=len(df))
146
+ # # ]
147
+ # EMBEDDING_MODEL_NAME = "BAAI/bge-large-en-v1.5" # "sentence-transformers/all-MiniLM-L6-v2"
148
+
149
+ # docs_processed = split_documents(
150
+ # 512, # We choose a chunk size adapted to our model
151
+ # RAW_KNOWLEDGE_BASE,
152
+ # tokenizer_name=EMBEDDING_MODEL_NAME,
153
+ # )
154
+
155
+ # # create or load vector store
156
+ # EMBEDDING_MODEL_NAME = "BAAI/bge-large-en-v1.5" # "sentence-transformers/all-MiniLM-L6-v2"
157
+ # VECTOR_DB_PATH = f"./path/to/vector_store"
158
+
159
+ # vector_store = create_or_load_embeddings(docs_processed,EMBEDDING_MODEL_NAME,VECTOR_DB_PATH)