Spaces:
Sleeping
Sleeping
Update README answers to questions
Browse files
README.md
CHANGED
@@ -12,7 +12,7 @@ license: apache-2.0
|
|
12 |
|
13 |
In today's breakout rooms, we will be following the process that you saw during the challenge.
|
14 |
|
15 |
-
Today, we will repeat the same process - but powered by our Pythonic RAG implementation we created last week.
|
16 |
|
17 |
You'll notice a few differences in the `app.py` logic - as well as a few changes to the `aimakerspace` package to get things working smoothly with Chainlit.
|
18 |
|
@@ -28,7 +28,7 @@ You'll notice a few differences in the `app.py` logic - as well as a few changes
|
|
28 |
|
29 |
The primary method of customizing and interacting with the Chainlit UI is through a few critical [decorators](https://blog.hubspot.com/website/decorators-in-python).
|
30 |
|
31 |
-
> NOTE: Simply put, the decorators (in Chainlit) are just ways we can "plug-in" to the functionality in Chainlit.
|
32 |
|
33 |
We'll be concerning ourselves with three main scopes:
|
34 |
|
@@ -40,7 +40,7 @@ Let's dig into each scope and see what we're doing!
|
|
40 |
|
41 |
### On Application Start:
|
42 |
|
43 |
-
The first thing you'll notice is that we have the traditional "wall of imports" this is to ensure we have everything we need to run our application.
|
44 |
|
45 |
```python
|
46 |
import os
|
@@ -58,7 +58,7 @@ from aimakerspace.openai_utils.chatmodel import ChatOpenAI
|
|
58 |
import chainlit as cl
|
59 |
```
|
60 |
|
61 |
-
Next up, we have some prompt templates. As all sessions will use the same prompt templates without modification, and we don't need these templates to be specific per template - we can set them up here - at the application scope.
|
62 |
|
63 |
```python
|
64 |
system_template = """\
|
@@ -77,7 +77,7 @@ user_role_prompt = UserRolePrompt(user_prompt_template)
|
|
77 |
|
78 |
> NOTE: You'll notice that these are the exact same prompt templates we used from the Pythonic RAG Notebook in Week 1 Day 2!
|
79 |
|
80 |
-
Following that - we can create the Python Class definition for our RAG pipeline - or
|
81 |
|
82 |
Let's look at the definition first:
|
83 |
|
@@ -111,12 +111,12 @@ class RetrievalAugmentedQAPipeline:
|
|
111 |
|
112 |
Notice a few things:
|
113 |
|
114 |
-
1. We have modified this `RetrievalAugmentedQAPipeline` from the initial notebook to support streaming.
|
115 |
-
2. In essence, our pipeline is
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
3. We are using a lot of `async` again!
|
121 |
|
122 |
Now, we're going to create a helper function for processing uploaded text files.
|
@@ -133,22 +133,22 @@ Now we can define our helper.
|
|
133 |
def process_file(file: AskFileResponse):
|
134 |
import tempfile
|
135 |
import shutil
|
136 |
-
|
137 |
print(f"Processing file: {file.name}")
|
138 |
-
|
139 |
# Create a temporary file with the correct extension
|
140 |
suffix = f".{file.name.split('.')[-1]}"
|
141 |
with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as temp_file:
|
142 |
# Copy the uploaded file content to the temporary file
|
143 |
shutil.copyfile(file.path, temp_file.name)
|
144 |
print(f"Created temporary file at: {temp_file.name}")
|
145 |
-
|
146 |
# Create appropriate loader
|
147 |
if file.name.lower().endswith('.pdf'):
|
148 |
loader = PDFLoader(temp_file.name)
|
149 |
else:
|
150 |
loader = TextFileLoader(temp_file.name)
|
151 |
-
|
152 |
try:
|
153 |
# Load and process the documents
|
154 |
documents = loader.load_documents()
|
@@ -168,11 +168,13 @@ Simply put, this downloads the file as a temp file, we load it in with `TextFile
|
|
168 |
|
169 |
Why do we want to support streaming? What about streaming is important, or useful?
|
170 |
|
|
|
|
|
171 |
### On Chat Start:
|
172 |
|
173 |
The next scope is where "the magic happens". On Chat Start is when a user begins a chat session. This will happen whenever a user opens a new chat window, or refreshes an existing chat window.
|
174 |
|
175 |
-
You'll see that our code is set-up to immediately show the user a chat box requesting them to upload a file.
|
176 |
|
177 |
```python
|
178 |
while files == None:
|
@@ -204,12 +206,14 @@ retrieval_augmented_qa_pipeline = RetrievalAugmentedQAPipeline(
|
|
204 |
|
205 |
Now, we'll save that into our user session!
|
206 |
|
207 |
-
> NOTE: Chainlit has some great documentation about [User Session](https://docs.chainlit.io/concepts/user-session).
|
208 |
|
209 |
-
#### ❓ QUESTION #2:
|
210 |
|
211 |
Why are we using User Session here? What about Python makes us need to use this? Why not just store everything in a global variable?
|
212 |
|
|
|
|
|
213 |
### On Message
|
214 |
|
215 |
First, we load our chain from the user session:
|
@@ -258,7 +262,7 @@ Due to the way the repository is created - it should be straightforward to deplo
|
|
258 |
<details>
|
259 |
<summary>Adding this Repository to the Newly Created Space</summary>
|
260 |
|
261 |
-
1. Collect the SSH address from the newly created Space.
|
262 |
|
263 |

|
264 |
|
@@ -276,9 +280,9 @@ git remote add hf HF_SPACE_SSH_ADDRESS_HERE
|
|
276 |
git pull hf main --no-rebase --allow-unrelated-histories -X ours
|
277 |
```
|
278 |
|
279 |
-
4. Use the command:
|
280 |
|
281 |
-
```bash
|
282 |
git add .
|
283 |
```
|
284 |
|
@@ -288,7 +292,7 @@ git add .
|
|
288 |
git commit -m "Deploying Pythonic RAG"
|
289 |
```
|
290 |
|
291 |
-
6. Use the command:
|
292 |
|
293 |
```bash
|
294 |
git push hf main
|
@@ -307,7 +311,7 @@ git push hf main
|
|
307 |
|
308 |

|
309 |
|
310 |
-
2. Navigate to `Variables and secrets` on the Settings page and click `New secret`:
|
311 |
|
312 |

|
313 |
|
|
|
12 |
|
13 |
In today's breakout rooms, we will be following the process that you saw during the challenge.
|
14 |
|
15 |
+
Today, we will repeat the same process - but powered by our Pythonic RAG implementation we created last week.
|
16 |
|
17 |
You'll notice a few differences in the `app.py` logic - as well as a few changes to the `aimakerspace` package to get things working smoothly with Chainlit.
|
18 |
|
|
|
28 |
|
29 |
The primary method of customizing and interacting with the Chainlit UI is through a few critical [decorators](https://blog.hubspot.com/website/decorators-in-python).
|
30 |
|
31 |
+
> NOTE: Simply put, the decorators (in Chainlit) are just ways we can "plug-in" to the functionality in Chainlit.
|
32 |
|
33 |
We'll be concerning ourselves with three main scopes:
|
34 |
|
|
|
40 |
|
41 |
### On Application Start:
|
42 |
|
43 |
+
The first thing you'll notice is that we have the traditional "wall of imports" this is to ensure we have everything we need to run our application.
|
44 |
|
45 |
```python
|
46 |
import os
|
|
|
58 |
import chainlit as cl
|
59 |
```
|
60 |
|
61 |
+
Next up, we have some prompt templates. As all sessions will use the same prompt templates without modification, and we don't need these templates to be specific per template - we can set them up here - at the application scope.
|
62 |
|
63 |
```python
|
64 |
system_template = """\
|
|
|
77 |
|
78 |
> NOTE: You'll notice that these are the exact same prompt templates we used from the Pythonic RAG Notebook in Week 1 Day 2!
|
79 |
|
80 |
+
Following that - we can create the Python Class definition for our RAG pipeline - or _chain_, as we'll refer to it in the rest of this walkthrough.
|
81 |
|
82 |
Let's look at the definition first:
|
83 |
|
|
|
111 |
|
112 |
Notice a few things:
|
113 |
|
114 |
+
1. We have modified this `RetrievalAugmentedQAPipeline` from the initial notebook to support streaming.
|
115 |
+
2. In essence, our pipeline is _chaining_ a few events together:
|
116 |
+
1. We take our user query, and chain it into our Vector Database to collect related chunks
|
117 |
+
2. We take those contexts and our user's questions and chain them into the prompt templates
|
118 |
+
3. We take that prompt template and chain it into our LLM call
|
119 |
+
4. We chain the response of the LLM call to the user
|
120 |
3. We are using a lot of `async` again!
|
121 |
|
122 |
Now, we're going to create a helper function for processing uploaded text files.
|
|
|
133 |
def process_file(file: AskFileResponse):
|
134 |
import tempfile
|
135 |
import shutil
|
136 |
+
|
137 |
print(f"Processing file: {file.name}")
|
138 |
+
|
139 |
# Create a temporary file with the correct extension
|
140 |
suffix = f".{file.name.split('.')[-1]}"
|
141 |
with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as temp_file:
|
142 |
# Copy the uploaded file content to the temporary file
|
143 |
shutil.copyfile(file.path, temp_file.name)
|
144 |
print(f"Created temporary file at: {temp_file.name}")
|
145 |
+
|
146 |
# Create appropriate loader
|
147 |
if file.name.lower().endswith('.pdf'):
|
148 |
loader = PDFLoader(temp_file.name)
|
149 |
else:
|
150 |
loader = TextFileLoader(temp_file.name)
|
151 |
+
|
152 |
try:
|
153 |
# Load and process the documents
|
154 |
documents = loader.load_documents()
|
|
|
168 |
|
169 |
Why do we want to support streaming? What about streaming is important, or useful?
|
170 |
|
171 |
+
- Streaming is important because it allows us to send the response to the user in chunks - rather than waiting for the entire response to be generated. This is useful because it allows the user to see the response as it is being generated - and it allows us to use the response in a streaming fashion.
|
172 |
+
|
173 |
### On Chat Start:
|
174 |
|
175 |
The next scope is where "the magic happens". On Chat Start is when a user begins a chat session. This will happen whenever a user opens a new chat window, or refreshes an existing chat window.
|
176 |
|
177 |
+
You'll see that our code is set-up to immediately show the user a chat box requesting them to upload a file.
|
178 |
|
179 |
```python
|
180 |
while files == None:
|
|
|
206 |
|
207 |
Now, we'll save that into our user session!
|
208 |
|
209 |
+
> NOTE: Chainlit has some great documentation about [User Session](https://docs.chainlit.io/concepts/user-session).
|
210 |
|
211 |
+
#### ❓ QUESTION #2:
|
212 |
|
213 |
Why are we using User Session here? What about Python makes us need to use this? Why not just store everything in a global variable?
|
214 |
|
215 |
+
- We need to persist the data in memory for the lifecycle of a user session on a per user basis. Using a global variable not work as if more than one user is using the application - they will all overwrite each other's data.
|
216 |
+
|
217 |
### On Message
|
218 |
|
219 |
First, we load our chain from the user session:
|
|
|
262 |
<details>
|
263 |
<summary>Adding this Repository to the Newly Created Space</summary>
|
264 |
|
265 |
+
1. Collect the SSH address from the newly created Space.
|
266 |
|
267 |

|
268 |
|
|
|
280 |
git pull hf main --no-rebase --allow-unrelated-histories -X ours
|
281 |
```
|
282 |
|
283 |
+
4. Use the command:
|
284 |
|
285 |
+
```bash
|
286 |
git add .
|
287 |
```
|
288 |
|
|
|
292 |
git commit -m "Deploying Pythonic RAG"
|
293 |
```
|
294 |
|
295 |
+
6. Use the command:
|
296 |
|
297 |
```bash
|
298 |
git push hf main
|
|
|
311 |
|
312 |

|
313 |
|
314 |
+
2. Navigate to `Variables and secrets` on the Settings page and click `New secret`:
|
315 |
|
316 |

|
317 |
|