Vector Embeddings and Store¶
The second content representation, complementing the Knowledge Graph: a numeric space where proximity means similar meaning, and the Qdrant store that holds those vectors alongside metadata for retrieval.
The Knowledge Graph encodes explicit relationships, but not every connection is written down. Vector embeddings capture patterns from language and context, surfacing implicit relations the graph may miss. They let the engine retrieve content through distributional similarity, not just direct links: diaries that speak of deportation in different words, testimonies describing parallel experiences, images that co-occur with similar narratives.
The intuition: items with related meaning land near each other, unrelated ones land far apart. So "find more like this" works on meaning, and the system can bridge vocabulary, languages, and modalities. A check of the WO2 thesaurus embedding showed "Auschwitz" sitting closest to other camp names (Treblinka, Gross-Rosen, Dachau, Sachsenhausen), confirming the space is historically sensible.
Formally an embedding is a function that maps an item to a vector:
Similarity between two items is the cosine of their vectors:
Encoder families the engine can draw on and adapt:
| Family | Examples | Use |
|---|---|---|
| Text-only | word2vec, GloVe, BERT, MPNet, Sentence-BERT | sentence and document vectors |
| Cross-lingual | multilingual BERT, LaBSE, multilingual Sentence-BERT | align languages in one space |
| Multimodal | CLIP and similar dual encoders | align image and text |
At corpus scale, vectors are stored in an Approximate Nearest Neighbour (ANN) index such as HNSW (Hierarchical Navigable Small World) for millisecond lookup. In this system this is the Qdrant vector store described below.
The deployed prototype used spaCy en_core_web_md (300-dim GloVe). The production code
uses sentence-transformers/all-MiniLM-L6-v2 via fastembed, behind the EmbeddingModel
port (see Adapters).
Math rendering
Formulas use LaTeX. They read: f maps an item to a d-dimensional vector; similarity is cosine of the two vectors.
Vector store (Qdrant)¶
Once items are embedded, they need a home that supports two things at once: find by meaning (nearest vectors) and filter by fact (time, place, type, language). A plain vector store treats metadata as an afterthought. The MEMORISE corpus needs both, because a testimony is worth retrieving by what it is about and by where and when it happened.
The store also serves two query styles from one place: a visitor's typed query embedded and matched against content, and the visitor's own behavioral vector used as the query to recommend more of what they engaged with. Both can be combined with filters such as language, victim group, event category, or time period.
The engine uses Qdrant, an open-source vector search engine that stores high-dimensional embeddings alongside rich, flexible metadata. Key features for MEMORISE:
- Unified semantic and metadata retrieval: explicit queries and behavioral vectors both run as similarity search, combined with metadata filters, in one framework.
- Flexible schema: heterogeneous sources can carry different metadata. A survivor interview can hold recording date and languages; a 3D reconstruction can hold geo-coordinates and time ranges; both live in one collection with unified search.
- Scalable search: fast ANN retrieval (HNSW) with structured filters.
- Geospatial support: vectors annotated with latitude/longitude enable point-radius search (items within a radius of a site), polygon/geofence search (testimonies inside a ghetto boundary), and proximity ranking (order by closeness to a visitor's GPS location).
flowchart LR
q["query vector or<br/>behavioral vector"] --> ann["ANN search (HNSW)"]
filt["filters: time · place ·<br/>type · language"] --> ann
ann --> hits["ranked candidates"]
classDef st fill:#EFEAE0,stroke:#A8895B,color:#423D34;
Example combined query: "all testimonies mentioning a camp within a 50 km radius of a city, recorded between 1945 and 1950, semantically similar to a visitor's last viewed content." Content is provided to Qdrant through the Omeka Content Management System.

Qdrant with geospatial annotation: items around a memorial site, supporting point-radius, geofence, and proximity-ranked queries combined with semantic similarity.
Tags in payload. Expert tags ride in the payload as flat tag_labels (facet:label, a
KEYWORD index) for recall via Filter(should=[...]), plus graded weights used by the pure-Python
tag scorer. In code the store sits behind the ContentStore port (search_vector, search_tags,
get, get_vectors); see Adapters. The
Tag system (taxonomy) page describes the tags themselves.
Content Engine service and API
This collection is written by the content-engine service. It formats any source (Omeka,
CSV, JSON) into the shared ContentDocument contract, embeds the text, and upserts to Qdrant;
the AI Engine recommender only reads the result. The service runs on port 8002 with
GET /health, POST /ingest, and POST /sync/omeka. Full detail in the interactive
Content Manager API reference.