Python & Data Toolkit Refresher: overview
- Source
- From the RAG & Agents Engineering course
- By
- Sourav Banerjee
- Last updated
- 8 Nov 2026
Every RAG and agent notebook in this course moves data through the same few Python tools. Chunks arrive as rows in a table, become rows of a float matrix, get scored with one matrix product, and the results land back in a table you can query. The model calls in between are slow network waits, so they run concurrently. The T2.1 notebooks build on four ideas: NumPy arrays, pandas DataFrames, SQL from Python, and asyncio for concurrent calls.
The running example is the Larkspur Cloud handbook that T5.1 to T5.3 index: twelve chunks on pricing, refunds, exports, outages and server sizing. Here the chunks sit in a DataFrame and a NumPy matrix, T5.1's baseline numbers sit in a SQLite table, and the lab sends eight handbook questions to a model at once.
In short
- An embedding index is a 2-D NumPy array, one row per chunk. Normalise the rows with
keepdims=Trueand one matrix product gives every cosine score. Withoutkeepdims, a square toy matrix divides columns instead of rows and the ranking flips. float32halves the memory offloat64: a million 1,536-dimension vectors take 6.1 GB instead of 12.3 GB.- The baseline row every later module compares against is a
groupby: T5.1's mean recall is 0.33, 0.50, 0.50 and 0.50 atk= 1, 2, 5 and 12.mean()skipsNaN, so a question that errored silently raises the average. - Pass values to SQL as parameters (
?insqlite3,%sin PyMySQL and psycopg2), never through an f-string. A plan name ofstarter' OR '1'='1returns every plan when the query is built from a string. - In the lab, eight model calls take 11.0 s one at a time, 5.6 s with a semaphore of 2, 3.1 s with 4, and 2.6 s from a limit of 7, the time of the slowest call. A sync client inside
async defkeeps it at 11.0 s at any limit.
Mental model
pd.read_csvreads twelve handbook chunks, one row each.- The DataFrame drops empty rows and keeps the
idandtextcolumns. asyncio.gathersends the twelve embedding calls together instead of one after another.- The twelve vectors become one NumPy array of shape (12, 384).
- One matrix product scores every chunk against the question, and
argsortkeeps the top two. - The run’s results go into a SQLite table, where
GROUP BYgives the baseline row.
Each tool holds the data in the shape the next step needs. pandas keeps labelled rows and columns, NumPy keeps one dtype in a fixed shape so arithmetic runs on whole arrays, SQL keeps results you can filter and group later, and asyncio keeps the slow calls from waiting on each other. Most bugs in the later modules are a shape, a dtype or a blocked event loop at one of these handoffs.
Interactive lab
Concurrent calls with asyncio: open the file in a browser. Slide the semaphore from 1 to 8 and watch the wall time fall from 11.0 s to 2.6 s, then stop falling at 7. Then switch the client to llm.invoke and move the slider again; nothing changes, because a sync call never hands the event loop back.
How it connects
- Before: nothing. T2.1 is the first module; skim the lessons you know.
- Next: T2.2 makes the model calls this module runs concurrently. NumPy scoring returns in T5.1 (TF-IDF nearest neighbours) and T5.4 (embeddings). SQL becomes a retriever in T8.3 (text-to-SQL) and a memory store in T10.2. asyncio drives LangGraph's async nodes in T4.4 and the parallel agents of T11.2.
Key Takeaways
- Keep vectors in one 2-D array of a fixed dtype; check
.shapeand.dtypebefore you trust a score. - Make the baseline a
groupbyover a long results table, and comparecount()withsize()before you read the mean. - Every value that reaches SQL from outside goes in as a parameter, and every credential comes from the environment.
- Use asyncio for many slow network calls, cap them with a semaphore, and make sure every call inside
async defis awaited.