M4 · Multimodal DataM4-0716 min read
Lesson 34 of 51 · Module 5 of 7 · Week 4
Threads:The generative pipeline thread
Python Multimodal Tooling: NumPy, spaCy, Keras, and Vector Databases
Four named tools cover the Python stack this domain expects you to recognize: NumPy for n-dimensional arrays and vectorized math underneath nearly every ML library, spaCy for classic NLP tasks like tokenization, POS tagging, NER, and lemmatization, Keras as a high-level neural-network API built on TensorFlow, and vector databases (FAISS, Milvus, Pinecone, Chroma, pgvector) that index embeddings for the nearest-neighbor retrieval RAG depends on.
By the end you can
- 01Name each of the four tool categories this lesson covers and state, in one sentence, the specific job each one does — not a vague "it's for AI," but the actual role.
- 02Recognize which named vector database a scenario is describing by matching its stated deployment shape (embedded library, managed service, Postgres extension) to the correct name.
- 03Place NumPy, spaCy, and Keras correctly relative to each other in a typical pipeline, rather than treating all three as interchangeable "Python ML tools."
- 04Connect the vector-database tooling here directly back to the RAG pipeline's storage and retrieval stages covered in the previous lesson.
NumPy: the array library underneath almost everything else
[GROUND TRUTH] (Sources/nca-genm/domain-4-multimodal-data.md) names NumPy's role directly: "N-dimensional arrays and vectorized math; foundation for ML libraries." Every tensor this module has discussed — a token-embedding sequence, a patch-embedding grid, a spectrogram — is, underneath whatever framework ultimately trains a model on it, an n-dimensional array, and NumPy is the library that popularized fast, vectorized operations over exactly that kind of array in Python. "Vectorized" here means operating on an entire array at once via a single call, rather than looping over individual elements in Python — a distinction that matters because a Python-level loop over millions of array elements is dramatically slower than the same operation expressed as one array-level call that runs in optimized, compiled code underneath. NumPy itself does not train models or run neural networks; it is the array-manipulation layer that TensorFlow, PyTorch, and most of the rest of the Python ML ecosystem build on, or at minimum interoperate with directly.
spaCy: classic NLP tasks, not generative language modeling
[GROUND TRUTH] (Sources/nca-genm/domain-4-multimodal-data.md) names spaCy's role as "NLP: tokenization, POS tagging, NER, lemmatization." Each of those four tasks is a distinct, classic natural-language-processing operation. Tokenization splits text into words or subword units — related to, but a different specific implementation than, the BPE/WordPiece tokenization M4-01 covers for transformer inputs; spaCy's tokenizer predates and serves a different purpose than a transformer's subword vocabulary. POS (part-of-speech) tagging labels each token with its grammatical role — noun, verb, adjective. NER (named-entity recognition) identifies spans of text that name a specific entity — a person, an organization, a location — and labels them accordingly. Lemmatization reduces a word to its base dictionary form ("running" to "run"), distinct from simple stemming in that it accounts for actual grammar rather than crudely chopping suffixes. spaCy is the toolkit named for exactly these four tasks; it is not the tool this exam associates with training or running a large generative language model, which is a meaningfully different job.
Keras: the high-level API, not the underlying computation engine
[GROUND TRUTH] (Sources/nca-genm/domain-4-multimodal-data.md) names Keras as "High-level neural-network API (on TensorFlow)," directly consistent with the Domain 1 material's own framing of the same fact. Keras provides a simplified, readable interface for defining, training, and evaluating neural networks — stacking layers, choosing an optimizer, calling a single fit method — while TensorFlow underneath handles the actual tensor computation, automatic differentiation, and GPU acceleration Keras's interface sits on top of. The relationship worth holding precisely: Keras is not a competing framework to TensorFlow, it is a layer built on it, which is why the source material writes "on TensorFlow" as a qualifier rather than listing Keras as an independent, unrelated third option alongside TensorFlow and PyTorch.
Vector databases: five named tools, one shared job
[GROUND TRUTH] (Sources/nca-genm/domain-4-multimodal-data.md) names the tool category and its examples together: "Vector databases (FAISS, Milvus, Pinecone, Chroma, pgvector) — Index embeddings for fast nearest-neighbor retrieval; power RAG." Every one of these five tools solves the identical problem M4-06's RAG pipeline needs solved at its storage and retrieval stages: given a large collection of embedding vectors, find the k vectors most similar to a query vector, fast, without a linear scan over every stored vector. They differ mainly in deployment shape rather than in the fundamental operation they perform. FAISS is a library you embed directly into your own application code, built for high-performance similarity search at large scale, without itself being a standalone server. Milvus and Pinecone are purpose-built vector database services — Milvus commonly self-hosted, Pinecone offered as a managed cloud service — each running as its own database system dedicated to vector storage and search. Chroma is a lightweight, developer-friendly vector store often reached for in smaller RAG prototypes specifically because of how little setup it requires. pgvector is distinct from the other four in one specific way worth remembering: it is an extension added to an existing PostgreSQL database, letting a team that already runs Postgres add vector similarity search without standing up a separate dedicated system at all.
4a. Why "index embeddings" is the specific phrase worth holding onto
[GROUND TRUTH] (Sources/nca-genm/domain-4-multimodal-data.md) describes vector databases' job as indexing embeddings "for fast nearest-neighbor retrieval," and "index" here is doing real work as a specific technical claim, not a loose synonym for "store." A vector database does not merely hold embeddings the way a filesystem holds files; it builds an additional data structure — commonly an approximate nearest-neighbor index such as HNSW or IVF, the specific mechanisms a different lesson elsewhere in this course names in depth — over the stored embeddings, so that a similarity query can skip comparing against every stored vector and instead narrow the search to a small, likely-relevant subset first. Without that index structure, a similarity search would have to compute a distance against every single stored embedding for every single query — a linear scan that becomes impractical the moment a store holds more than a small number of vectors. This is the concrete reason a vector database is a distinct category of tool from a regular database in the first place, and it is also the reason all five named tools in section 4 — despite differing in deployment shape — share this one structural commitment: build an index over the embeddings, not just a list of them.
⭐ THE EARNED INSIGHT: > All four tools in this lesson do exactly one job each, and the recurring exam trap is always the same shape regardless of which tool it targets: attributing one tool's specific, narrow job to a different tool that merely sounds similar. NumPy is arrays, not neural networks; spaCy is structural NLP, not generation; Keras is an API, not the computation engine underneath it; a vector database is an index over embeddings, not a generic store. Naming the job precisely, every time, is the entire skill this lesson is built to test.
Comparison: the four tool categories at a glance
| Tool | Category | Core job | Not to be confused with |
|---|---|---|---|
| NumPy | Array computation | N-dimensional arrays, vectorized math | A neural-network framework itself — it underlies frameworks, it is not one |
| spaCy | Classic NLP | Tokenization, POS tagging, NER, lemmatization | A generative language-model toolkit — it performs structural NLP tasks, not text generation |
| Keras | High-level modeling API | Defining and training neural networks on top of TensorFlow | A standalone computation engine — TensorFlow does the actual tensor math underneath |
| Vector databases | Embedding storage/search | Fast nearest-neighbor retrieval over embeddings, powering RAG | A general-purpose relational database — they are purpose-built for similarity search, not arbitrary structured queries |
5a. Where NumPy and spaCy overlap with, and differ from, a modern transformer pipeline
It is worth being precise about one thing this lesson has not yet said directly: neither NumPy nor spaCy is the tool you would reach for to run a modern transformer-based model end to end, even though both remain genuinely useful inside a pipeline that also uses one. NumPy's array operations underlie the tensor math a transformer performs, but a transformer's own training and inference typically run through a dedicated deep-learning framework (TensorFlow or PyTorch, the Domain 1 material's own pair) that provides automatic differentiation and GPU acceleration NumPy itself does not — NumPy participates in the surrounding data-preparation and post-processing steps, not in the transformer's own forward and backward passes at training scale. spaCy, similarly, remains genuinely useful for the classic structural tasks named in section 2 even in a pipeline that also uses a large language model for generation — a team might use spaCy to extract named entities from a document before that document is chunked for RAG, precisely because a dedicated NER tool tuned for that one task can be faster and more predictable than asking a general-purpose LLM to perform the same extraction. Holding this distinction — "useful alongside" versus "the tool that does the heavy lifting" — is exactly the kind of precise placement a scenario question can test.
Worked example: matching five deployment descriptions to the five named vector databases
Treat the following as a direct application of section 4's distinctions, in the shape a recognition-level scenario question actually takes.
Description A: "We embedded a similarity-search library directly into our
Python service; there's no separate database server running."
-> FAISS (a library, not a standalone server)
Description B: "We added the pgvector extension to our existing Postgres
instance so we didn't need to stand up a new system."
-> pgvector (an extension to an existing relational database)
Description C: "We're using a managed cloud vector database service and
never provision or patch a server ourselves."
-> Pinecone (a managed service, in the common association the source
material implies by naming it alongside self-hosted Milvus)
Description D: "We self-host our vector database cluster on our own
infrastructure, purpose-built for vector search at scale."
-> Milvus (commonly self-hosted, per the same association)
Description E: "We're prototyping a small RAG demo and wanted the
lightest-weight vector store to get running quickly."
-> Chroma (the lightweight, developer-friendly option)
This is a constructed matching exercise, not a claim that any of these five tools is architecturally restricted to only the deployment shape shown — FAISS can be wrapped in a server, Milvus offers a managed option, and so on. The exercise reflects the common association the source material's own framing implies, which is the level of recognition a foundational-scope question is built to test, and it is worth practicing this same matching in reverse — starting from a tool's name and stating its typical deployment shape from memory — since a scenario question can present the tool name first and ask for the deployment description just as easily as the other direction.
Where each tool actually sits in a multimodal pipeline
It is worth placing all four tools onto one concrete pipeline rather than leaving them as four isolated definitions, since a scenario question sometimes asks not "what does this tool do" but "at which stage of a described pipeline would this tool appear." Take the multimodal RAG worked example from M4-06: ingesting a repair manual, chunking it, embedding both text and diagrams, storing those embeddings, and retrieving by similarity. NumPy sits underneath essentially every stage, since every chunk's embedding is, underneath whatever specific framework produced it, an n-dimensional array NumPy-style operations can manipulate — computing a cosine similarity by hand, for instance, is exactly the kind of vectorized array operation NumPy is built for. spaCy would plausibly appear at the ingestion or chunking stage specifically, if the pipeline needed to identify named entities in the manual's text (flagging which chunks mention a specific part number, say, via NER) or needed lemmatized tokens for a simpler keyword-based pre-filter layered in front of the embedding-based retrieval. Keras would appear if the team building this pipeline trained or fine-tuned any of its own neural components — a custom text encoder, for instance — rather than using an already-trained one off the shelf. The vector database appears exactly where M4-06 already placed it: the storage and retrieval stages, holding every chunk's embedding and serving the top-k similarity search a technician's query triggers.
This placement exercise also clarifies what each tool is not responsible for in that same pipeline. NumPy never decides which chunks are relevant — it only ever performs the arithmetic once a similarity comparison has already been set up. spaCy never generates the final answer a technician reads — that is the generation model's job, downstream of retrieval entirely. Keras, if used at all in this specific pipeline, trains a component ahead of deployment; it does not itself run at query time the way the vector database does. Holding these boundaries precisely is exactly the recognition-level skill this lesson's material is built to test.
Why this tooling is on the NCA-GENM exam
[GROUND TRUTH] (Sources/nca-genm/domain-4-multimodal-data.md) closes Domain 4 with exactly this tool list, plus a broader expectation: "monitor data collection, experiments, and software processes," "identify the system data, hardware, and software components required to meet user needs," and "write software components/scripts under senior supervision." That framing is consistent with the associate-level scope this entire module has operated under — recognize the tools and their roles, and recognize what infrastructure a described system would need, rather than implement a production deployment of any of them yourself.
The question tends to name a tool and ask for its role, or describe a task and ask which tool performs it — "which library would you use for named-entity recognition" (spaCy), "which of these is a Postgres extension rather than a standalone database" (pgvector). The reliable distractor pattern swaps roles between tools that sound superficially similar — attributing spaCy's classic-NLP tasks to Keras, or describing NumPy as a neural-network framework rather than the array layer underneath one.
Second worked example: why NumPy arrays, not plain Python lists, back nearly every ML library
[GROUND TRUTH] (Sources/nca-genm/domain-4-multimodal-data.md) calls NumPy "foundation for ML libraries," and it is worth making that foundational claim concrete with a small, honest arithmetic comparison rather than leaving it as an assertion. Treat the following as a constructed illustration of the mechanism, not a benchmark measured on any specific machine.
Task: compute the element-wise product of two vectors, length 4.
Plain Python list version:
a = [1.5, 2.0, 0.5, 3.0]
b = [2.0, 1.0, 4.0, 0.5]
result = [a[i] * b[i] for i in range(len(a))]
# Python's interpreter dispatches one multiply operation PER element,
# each one going through the interpreter's general-purpose object handling.
NumPy array version:
import numpy as np
a = np.array([1.5, 2.0, 0.5, 3.0])
b = np.array([2.0, 1.0, 4.0, 0.5])
result = a * b
# One call. The multiplication runs over the whole array in
# optimized, compiled code beneath the Python layer -- no per-element
# interpreter dispatch.
At four elements the difference is invisible. The mechanism that matters is that the list version's per-element interpreter dispatch cost is a fixed overhead paid separately for every one of the array's elements, while the NumPy version pays that dispatch overhead once, for the whole call, regardless of how large the array grows. A 768-dimensional embedding vector — the patch-embedding size from M4-01's own worked example — makes the gap far more consequential than four elements do, and a batch of thousands of such vectors, the realistic scale a training loop or a RAG pipeline's embedding stage actually operates at, is exactly the regime "foundation for ML libraries" is describing: every framework built on top of this pattern inherits the same vectorized-array performance NumPy pioneered in the Python ecosystem, which is why virtually nothing in this module's pipeline — from a patch-embedding tensor to a stored vector-database embedding — is represented as a plain Python list once it reaches any stage that actually computes something over it.
Which vector database should a team choose if they already run PostgreSQL for everything else?
pgvector is the tool named specifically for this situation: rather than introducing an entirely new database system to support vector search, a team already operating Postgres can add the pgvector extension and gain nearest-neighbor retrieval within infrastructure they already run, patch, and back up. This does not mean pgvector is universally the best-performing option at very large scale — a purpose-built system like Milvus or Pinecone may outperform it once embedding volume grows large enough — but for a team optimizing for operational simplicity over raw scale, reusing existing Postgres infrastructure is the direct, source-supported reason to reach for it first.
Does knowing these four tools mean you can build a production multimodal pipeline unsupervised?
No, and the source material is explicit about the boundary: the expected skill alongside this tool list is to "write software components/scripts under senior supervision" [GROUND TRUTH] (Sources/nca-genm/domain-4-multimodal-data.md), not to architect and ship a production system independently. Recognizing what NumPy, spaCy, Keras, and a named vector database each do — and being able to place them correctly on a described pipeline, the way section 7's worked placement did for the M4-06 RAG example — is the associate-level competency this exam actually tests. Production concerns this lesson does not cover at all include choosing between the five named vector databases at genuine production scale, tuning an index for a specific latency-versus-recall tradeoff, or managing a multi-terabyte embedding store's operational lifecycle — real, substantial skills that sit well past this exam's foundational scope, and past what a single 40-minute lesson on tool recognition could responsibly claim to teach.
Common mistakes about this tooling
| Mistake | Symptom | Fix |
|---|---|---|
| Treating Keras as a computation engine rather than an API on TensorFlow | Describing Keras as a competitor to TensorFlow rather than a layer built on it | Keras is a high-level API; TensorFlow performs the underlying tensor computation |
| Assuming spaCy is used for generative text output | Expecting spaCy to generate fluent new text the way an LLM does | spaCy performs structural NLP tasks — tokenization, POS tagging, NER, lemmatization — not generation |
| Confusing FAISS with a standalone database server | Expecting FAISS to run as its own independently deployed service by default | FAISS is a library embedded into your own application; Milvus and Pinecone are the standalone database options |
| Forgetting pgvector's distinguishing feature | Not recognizing "added to an existing Postgres instance" as a specific tooling clue | pgvector is a Postgres extension, distinct from the other four dedicated vector-database options |
Glossary recap: Python multimodal tooling terms this lesson introduced
| Term | One-line definition |
|---|---|
| NumPy | A Python library for n-dimensional arrays and vectorized math, underlying most ML libraries |
| spaCy | A classic-NLP library for tokenization, POS tagging, named-entity recognition, and lemmatization |
| Keras | A high-level neural-network API built on top of TensorFlow |
| Vector database | A storage system with index structures purpose-built for fast nearest-neighbor similarity search over embeddings |
| FAISS | An embeddable similarity-search library, not a standalone database server |
| pgvector | A PostgreSQL extension adding vector similarity search to an existing relational database |
Key takeaways on Python multimodal tooling
- NumPy provides the array foundation, spaCy handles classic structural NLP tasks, Keras is a high-level API on TensorFlow, and vector databases index embeddings for the retrieval that powers RAG.
- These four tools solve different, non-overlapping problems; the exam's reliable trap swaps one tool's role onto another superficially similar tool.
- Among the five named vector databases, deployment shape is the fastest way to tell them apart: FAISS is a library, Milvus and Pinecone are standalone database options, Chroma is the lightweight prototyping choice, and pgvector is a Postgres extension.
- This module also expects you to recognize what data, hardware, and software components a described system would need — GPU memory, storage, a serving stack — without necessarily implementing any of it yourself.
Next: Module 5, Performance Optimization, picks up once a multimodal model already exists and asks a different question entirely — how to get more accuracy per unit of compute, memory, and energy out of a model you already have, starting with mixed-precision training and quantization.