ASDRP · Agentic RAG Track · Module 03
Embed a handful of sentences, store them in Qdrant, and retrieve the nearest neighbours — no API key required.
What we'll cover
Track 1 · The Math
Track 1 · The Math
Distance.COSINE normalises internally.
Track 1 · The Math
import numpy as np
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("all-MiniLM-L6-v2") # 384-dim, keyless
a = model.encode("What is a troy ounce?")
b = model.encode("Gold is measured in troy ounces.")
c = model.encode("Machine learning optimises loss functions.")
def cosine(x, y):
x, y = np.asarray(x, float), np.asarray(y, float)
return float(x @ y / (np.linalg.norm(x) * np.linalg.norm(y)))
print(f"sim(a, b) = {cosine(a, b):.4f}") # high (~0.85)
print(f"sim(a, c) = {cosine(a, c):.4f}") # low (~0.15)
cosine() manually — Qdrant runs it over
millions of vectors in milliseconds. The manual version builds the intuition.
Track 2 · The Store
:memory: — in-process, no disk, perfect for tutorialsTrack 2 · The Store
from qdrant_client import QdrantClient
from qdrant_client.models import VectorParams, Distance, PointStruct
client = QdrantClient(":memory:") # in-process, no server needed
client.create_collection(
collection_name="demo",
vectors_config=VectorParams(size=384, distance=Distance.COSINE),
)
# encode a small toy corpus
sentences = [
"Gold is priced in troy ounces.",
"Silver has significant industrial demand.",
"A troy ounce equals 31.1 grams.",
"Platinum is rarer than gold.",
"Machine learning optimises loss functions.",
]
vectors = model.encode(sentences)
client.upsert(
collection_name="demo",
points=[
PointStruct(id=i, vector=vec.tolist(), payload={"text": s})
for i, (vec, s) in enumerate(zip(vectors, sentences))
],
)
Track 3 · The Search
query = "What is a troy ounce?"
q_vec = model.encode(query).tolist()
hits = client.query_points(
collection_name="demo",
query=q_vec,
limit=3,
).points
for rank, hit in enumerate(hits, 1):
print(f"#{rank} score={hit.score:.4f} → {hit.payload['text']}")
#1 score=0.8831 → A troy ounce equals 31.1 grams.#2 score=0.7245 → Gold is priced in troy ounces.#3 score=0.5102 → Silver has significant industrial demand.
Track 3 · The Search
all-MiniLM-L6-v2 was trained on general text. Domain-specific jargon
(e.g. "contango", "LBMA fix") may land in unexpected regions of the space.
Module 05 migrates to a cloud embedder better tuned to finance.
k=3 drops rank 4, even if scores 3 and 4 are nearly identical.
Module 10 introduces reranking to handle this gracefully.
Track 3 · The Search
| Metric | Measures | Sensitive to vector length? | Use case |
|---|---|---|---|
| Cosine | Angle between vectors | No (normalised) | Semantic text search ✓ |
| Euclidean (L2) | Straight-line distance | Yes | Image embeddings, clustering |
| Dot product | Projection magnitude | Yes | When vectors are pre-normalised |
Distance.COSINE, Distance.EUCLID,
Distance.DOT. For text search with sentence-transformers,
always use Distance.COSINE.
Summary
:memory: — zero-config, in-processRun the notebook: 03_similarity_search.ipynb