mbudisic commited on
Commit
6bf3dd2
·
1 Parent(s): e8cc2e6

Session 15: filled in blanks

Browse files
Files changed (1) hide show
  1. app.py +72 -32
app.py CHANGED
@@ -16,7 +16,7 @@ import asyncio
16
  from tqdm.asyncio import tqdm
17
 
18
  # GLOBAL SCOPE - ENTIRE APPLICATION HAS ACCESS TO VALUES SET IN THIS SCOPE #
19
- # ---- ENV VARIABLES ---- #
20
  """
21
  This function will load our environment file (.env) if it is present.
22
 
@@ -41,20 +41,26 @@ HF_TOKEN = os.environ["HF_TOKEN"]
41
  4. Index Files if they do not exist, otherwise load the vectorstore
42
  """
43
  ### 1. CREATE TEXT LOADER AND LOAD DOCUMENTS
44
- ### NOTE: PAY ATTENTION TO THE PATH THEY ARE IN.
45
- text_loader =
46
- documents =
47
 
48
  ### 2. CREATE TEXT SPLITTER AND SPLIT DOCUMENTS
49
- text_splitter =
50
- split_documents =
51
 
52
  ### 3. LOAD HUGGINGFACE EMBEDDINGS
53
- hf_embeddings =
 
 
 
 
 
54
 
55
  async def add_documents_async(vectorstore, documents):
56
  await vectorstore.aadd_documents(documents)
57
 
 
58
  async def process_batch(vectorstore, batch, is_first_batch, pbar):
59
  if is_first_batch:
60
  result = await FAISS.afrom_documents(batch, hf_embeddings)
@@ -64,44 +70,52 @@ async def process_batch(vectorstore, batch, is_first_batch, pbar):
64
  pbar.update(len(batch))
65
  return result
66
 
 
67
  async def main():
68
  print("Indexing Files")
69
-
70
  vectorstore = None
71
  batch_size = 32
72
-
73
- batches = [split_documents[i:i+batch_size] for i in range(0, len(split_documents), batch_size)]
74
-
 
 
 
75
  async def process_all_batches():
76
  nonlocal vectorstore
77
  tasks = []
78
  pbars = []
79
-
80
  for i, batch in enumerate(batches):
81
- pbar = tqdm(total=len(batch), desc=f"Batch {i+1}/{len(batches)}", position=i)
 
 
82
  pbars.append(pbar)
83
-
84
- if i == 0:
85
  vectorstore = await process_batch(None, batch, True, pbar)
86
- else:
87
  tasks.append(process_batch(vectorstore, batch, False, pbar))
88
-
89
  if tasks:
90
  await asyncio.gather(*tasks)
91
-
92
  for pbar in pbars:
93
  pbar.close()
94
-
95
  await process_all_batches()
96
-
97
  hf_retriever = vectorstore.as_retriever()
98
  print("\nIndexing complete. Vectorstore is ready for use.")
99
  return hf_retriever
100
 
 
101
  async def run():
102
  retriever = await main()
103
  return retriever
104
 
 
105
  hf_retriever = asyncio.run(run())
106
 
107
  # -- AUGMENTED -- #
@@ -110,46 +124,72 @@ hf_retriever = asyncio.run(run())
110
  2. Create a Prompt Template from the String Template
111
  """
112
  ### 1. DEFINE STRING TEMPLATE
113
- RAG_PROMPT_TEMPLATE =
 
 
 
 
 
 
 
 
 
 
 
 
114
 
115
  ### 2. CREATE PROMPT TEMPLATE
116
- rag_prompt =
117
 
118
  # -- GENERATION -- #
119
  """
120
  1. Create a HuggingFaceEndpoint for the LLM
121
  """
122
  ### 1. CREATE HUGGINGFACE ENDPOINT FOR LLM
123
- hf_llm =
 
 
 
 
 
 
 
 
 
 
124
 
125
  @cl.author_rename
126
  def rename(original_author: str):
127
  """
128
- This function can be used to rename the 'author' of a message.
129
 
130
  In this case, we're overriding the 'Assistant' author to be 'Paul Graham Essay Bot'.
131
  """
132
- rename_dict = {
133
- "Assistant" : "Paul Graham Essay Bot"
134
- }
135
  return rename_dict.get(original_author, original_author)
136
 
 
137
  @cl.on_chat_start
138
  async def start_chat():
139
  """
140
- This function will be called at the start of every user session.
141
 
142
- We will build our LCEL RAG chain here, and store it in the user session.
143
 
144
  The user session is a dictionary that is unique to each user session, and is stored in the memory of the server.
145
  """
146
 
147
  ### BUILD LCEL RAG CHAIN THAT ONLY RETURNS TEXT
148
- lcel_rag_chain =
 
 
 
 
149
 
150
  cl.user_session.set("lcel_rag_chain", lcel_rag_chain)
151
 
152
- @cl.on_message
 
153
  async def main(message: cl.Message):
154
  """
155
  This function will be called every time a message is recieved from a session.
@@ -168,4 +208,4 @@ async def main(message: cl.Message):
168
  ):
169
  await msg.stream_token(chunk)
170
 
171
- await msg.send()
 
16
  from tqdm.asyncio import tqdm
17
 
18
  # GLOBAL SCOPE - ENTIRE APPLICATION HAS ACCESS TO VALUES SET IN THIS SCOPE #
19
+ # ---- ENV VARIABLES ---- #
20
  """
21
  This function will load our environment file (.env) if it is present.
22
 
 
41
  4. Index Files if they do not exist, otherwise load the vectorstore
42
  """
43
  ### 1. CREATE TEXT LOADER AND LOAD DOCUMENTS
44
+ ### NOTE: PAY ATTENTION TO THE PATH THEY ARE IN.
45
+ text_loader = TextLoader("./data/paul_graham_essays.txt")
46
+ documents = text_loader.load()
47
 
48
  ### 2. CREATE TEXT SPLITTER AND SPLIT DOCUMENTS
49
+ text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=30)
50
+ split_documents = text_splitter.split_documents(documents)
51
 
52
  ### 3. LOAD HUGGINGFACE EMBEDDINGS
53
+ hf_embeddings = HuggingFaceEndpointEmbeddings(
54
+ model=HF_EMBED_ENDPOINT,
55
+ task="feature-extraction",
56
+ huggingfacehub_api_token=HF_TOKEN,
57
+ )
58
+
59
 
60
  async def add_documents_async(vectorstore, documents):
61
  await vectorstore.aadd_documents(documents)
62
 
63
+
64
  async def process_batch(vectorstore, batch, is_first_batch, pbar):
65
  if is_first_batch:
66
  result = await FAISS.afrom_documents(batch, hf_embeddings)
 
70
  pbar.update(len(batch))
71
  return result
72
 
73
+
74
  async def main():
75
  print("Indexing Files")
76
+
77
  vectorstore = None
78
  batch_size = 32
79
+
80
+ batches = [
81
+ split_documents[i : i + batch_size]
82
+ for i in range(0, len(split_documents), batch_size)
83
+ ]
84
+
85
  async def process_all_batches():
86
  nonlocal vectorstore
87
  tasks = []
88
  pbars = []
89
+
90
  for i, batch in enumerate(batches):
91
+ pbar = tqdm(
92
+ total=len(batch), desc=f"Batch {i+1}/{len(batches)}", position=i
93
+ )
94
  pbars.append(pbar)
95
+
96
+ if i == 0: # first batch is processed directly to initialize vectorstore
97
  vectorstore = await process_batch(None, batch, True, pbar)
98
+ else: # the remaining batches are processed in parallel
99
  tasks.append(process_batch(vectorstore, batch, False, pbar))
100
+
101
  if tasks:
102
  await asyncio.gather(*tasks)
103
+
104
  for pbar in pbars:
105
  pbar.close()
106
+
107
  await process_all_batches()
108
+
109
  hf_retriever = vectorstore.as_retriever()
110
  print("\nIndexing complete. Vectorstore is ready for use.")
111
  return hf_retriever
112
 
113
+
114
  async def run():
115
  retriever = await main()
116
  return retriever
117
 
118
+
119
  hf_retriever = asyncio.run(run())
120
 
121
  # -- AUGMENTED -- #
 
124
  2. Create a Prompt Template from the String Template
125
  """
126
  ### 1. DEFINE STRING TEMPLATE
127
+ RAG_PROMPT_TEMPLATE = """\
128
+ <|start_header_id|>system<|end_header_id|>
129
+ You are a helpful assistant. You answer user questions based on provided context. If you can't answer the question with the provided context, say you don't know.<|eot_id|>
130
+
131
+ <|start_header_id|>user<|end_header_id|>
132
+ User Query:
133
+ {query}
134
+
135
+ Context:
136
+ {context}<|eot_id|>
137
+
138
+ <|start_header_id|>assistant<|end_header_id|>
139
+ """
140
 
141
  ### 2. CREATE PROMPT TEMPLATE
142
+ rag_prompt = PromptTemplate.from_template(RAG_PROMPT_TEMPLATE)
143
 
144
  # -- GENERATION -- #
145
  """
146
  1. Create a HuggingFaceEndpoint for the LLM
147
  """
148
  ### 1. CREATE HUGGINGFACE ENDPOINT FOR LLM
149
+ hf_llm = HuggingFaceEndpoint(
150
+ endpoint_url=f"{HF_LLM_ENDPOINT}",
151
+ task="text-generation",
152
+ max_new_tokens=512,
153
+ top_k=10,
154
+ top_p=0.95,
155
+ typical_p=0.95,
156
+ temperature=0.01,
157
+ repetition_penalty=1.03,
158
+ )
159
+
160
 
161
  @cl.author_rename
162
  def rename(original_author: str):
163
  """
164
+ This function can be used to rename the 'author' of a message.
165
 
166
  In this case, we're overriding the 'Assistant' author to be 'Paul Graham Essay Bot'.
167
  """
168
+ rename_dict = {"Assistant": "Paul Graham Essay Bot"}
 
 
169
  return rename_dict.get(original_author, original_author)
170
 
171
+
172
  @cl.on_chat_start
173
  async def start_chat():
174
  """
175
+ This function will be called at the start of every user session.
176
 
177
+ We will build our LCEL RAG chain here, and store it in the user session.
178
 
179
  The user session is a dictionary that is unique to each user session, and is stored in the memory of the server.
180
  """
181
 
182
  ### BUILD LCEL RAG CHAIN THAT ONLY RETURNS TEXT
183
+ lcel_rag_chain = (
184
+ {"context": itemgetter("query") | hf_retriever, "query": itemgetter("query")}
185
+ | rag_prompt
186
+ | hf_llm
187
+ )
188
 
189
  cl.user_session.set("lcel_rag_chain", lcel_rag_chain)
190
 
191
+
192
+ @cl.on_message
193
  async def main(message: cl.Message):
194
  """
195
  This function will be called every time a message is recieved from a session.
 
208
  ):
209
  await msg.stream_token(chunk)
210
 
211
+ await msg.send()