Chapter 23
vector search pgvector
Notebookllm-zoomcamp-2026-vector15 cells
In [2]python · cell 1
python
from tqdm.auto import tqdm
from ingest import load_faq_data
from sentence_transformers import SentenceTransformer
model = SentenceTransformer('all-MiniLM-L6-v2')
documents = load_faq_data()
texts = [doc['question'] + ' ' + doc['answer'] for doc in documents]
batch_size = 50
vectors = []
for i in tqdm(range(0, len(texts), batch_size)):
batch = texts[i:i + batch_size]
batch_vectors = model.encode(batch)
vectors.extend(batch_vectors)Output
Warning: You are sending unauthenticated requests to the HF Hub. Please set a HF_TOKEN to enable higher rate limits and faster downloads.
Loading weights: 0%| | 0/103 [00:00<?, ?it/s]
0%| | 0/25 [00:00<?, ?it/s]
In [4]python · cell 2
python
import psycopg
conn = psycopg.connect(
'postgresql://user:pswd@localhost:5432/faq'
)
conn.execute("CREATE EXTENSION IF NOT EXISTS vector")Output
<psycopg.Cursor [COMMAND_OK] [INTRANS] (host=localhost user=user database=faq) at 0x74ada1d08590>
In [5]python · cell 3
python
conn.execute("""
DROP TABLE IF EXISTS documents
""")
conn.execute("""
CREATE TABLE documents (
id SERIAL PRIMARY KEY,
course TEXT,
section TEXT,
question TEXT,
answer TEXT,
embedding vector(384)
)
""")Output
<psycopg.Cursor [COMMAND_OK] [INTRANS] (host=localhost user=user database=faq) at 0x74aea440ee10>
In [6]python · cell 4
python
def vec_to_str(vector):
return '[' + ','.join(str(x) for x in vector) + ']'
for doc, vec in tqdm(zip(documents, vectors), total=len(documents)):
conn.execute(
"""
INSERT INTO documents (course, section, question, answer, embedding)
VALUES (%s, %s, %s, %s, %s::vector)
""",
(doc['course'], doc['section'], doc['question'], doc['answer'],
vec_to_str(vec))
)
conn.commit()Output
0%| | 0/1208 [00:00<?, ?it/s]
In [7]python · cell 5
python
query = 'I just discovered the course. Can I still join it?'
query_vector = model.encode(query)
query_str = vec_to_str(query_vector)In [10]python · cell 6
python
results = conn.execute(
"""
SELECT course, question, answer,
1 - (embedding <=> %s::vector) AS similarity
FROM documents
ORDER BY embedding <=> %s::vector
LIMIT 5
""",
(query_str, query_str)
).fetchall()
for row in results:
print(f'[{row[0]}] {row[1]} (similarity: {row[3]:.4f})')Output
[llm-zoomcamp] I just discovered the course. Can I still join? (similarity: 0.8365) [machine-learning-zoomcamp] The course has already started. Can I still join it? (similarity: 0.6904) [mlops-zoomcamp] Course - Can I still join the course after the start date? (similarity: 0.6043) [data-engineering-zoomcamp] Course: Can I still join the course after the start date? (similarity: 0.5959) [data-engineering-zoomcamp] Course: Can I get support if I take the course in the self-paced mode? (similarity: 0.5927)
In [11]python · cell 7
python
results = conn.execute(
"""
SELECT course, question, answer,
1 - (embedding <=> %s::vector) AS similarity
FROM documents
WHERE course = %s
ORDER BY embedding <=> %s::vector
LIMIT 5
""",
(query_str, 'llm-zoomcamp', query_str)
).fetchall()
for row in results:
print(f'[{row[0]}] {row[1]} (similarity: {row[3]:.4f})')Output
[llm-zoomcamp] I just discovered the course. Can I still join? (similarity: 0.8365) [llm-zoomcamp] Certificate: Can I follow the course in a self-paced mode and get a certificate? (similarity: 0.5113) [llm-zoomcamp] When will the course be offered next? (similarity: 0.4926) [llm-zoomcamp] Course: I have registered for the LLM Zoomcamp. When can I expect to receive the confirmation email? (similarity: 0.4241) [llm-zoomcamp] OpenAI: Do I have to subscribe and pay for Open AI API for this course? (similarity: 0.4106)
In [12]python · cell 8
python
conn.execute("""
CREATE INDEX ON documents
USING hnsw (embedding vector_cosine_ops)
""")Output
<psycopg.Cursor [COMMAND_OK] [INTRANS] (host=localhost user=user database=faq) at 0x74ada3570050>
In [13]python · cell 9
python
def pgvector_search(query, course='llm-zoomcamp', num_results=5):
query_vector = model.encode(query)
query_str = vec_to_str(query_vector)
rows = conn.execute(
"""
SELECT course, section, question, answer
FROM documents
WHERE course = %s
ORDER BY embedding <=> %s::vector
LIMIT %s
""",
(course, query_str, num_results)
).fetchall()
return [
{'course': r[0], 'section': r[1], 'question': r[2], 'answer': r[3]}
for r in rows
]In [14]python · cell 10
python
pgvector_search('the program has already begun, can I still sign up?')Output
[{'course': 'llm-zoomcamp',
'section': 'General Course-Related Questions',
'question': 'I just discovered the course. Can I still join?',
'answer': 'Yes, but if you want to receive a certificate, you need to submit your project while we’re still accepting submissions.'},
{'course': 'llm-zoomcamp',
'section': 'General Course-Related Questions',
'question': 'Course: I have registered for the LLM Zoomcamp. When can I expect to receive the confirmation email?',
'answer': "You don't need it. You're accepted. You can also just start learning and submitting homework (while the form is open) without registering. It is not checked against any registered list. Registration is just to gauge interest before the start date."},
{'course': 'llm-zoomcamp',
'section': 'General Course-Related Questions',
'question': 'When will the course be offered next?',
'answer': 'Summer 2025.'},
{'course': 'llm-zoomcamp',
'section': 'Capstone Project',
'question': 'Do we submit 2 projects, what does attempt 1 and 2 mean?',
'answer': 'You only need to submit one project. If the submission at the first attempt fails, you can improve it and re-submit during the attempt#2 submission window.\n\n- If you want to submit two projects for the experience and exposure, you must use different datasets and problem statements.\n- If you can’t make it to the attempt#1 submission window, you still have time to catch up to meet the attempt#2 submission window.\n\nRemember that the submission does not count towards the certification if you do not participate in the peer-review of three peers in your cohort.'},
{'course': 'llm-zoomcamp',
'section': 'General Course-Related Questions',
'question': 'I missed the first homework - can I still get a certificate?',
'answer': 'Yes, you need to pass the Capstone project to get the certificate. Homework is not mandatory, though it is recommended for reinforcing concepts, and the points awarded count towards your rank on the leaderboard.'}]In [15]python · cell 11
python
from rag_helper import RAGBase
class RAGPgVector(RAGBase):
def __init__(self, embedder, conn, **kwargs):
super().__init__(index=None, **kwargs)
self.embedder = embedder
self.conn = conn
def search(self, query, num_results=5):
query_vector = self.embedder.encode(query)
query_str = vec_to_str(query_vector)
rows = self.conn.execute(
"""
SELECT course, section, question, answer
FROM documents
WHERE course = %s
ORDER BY embedding <=> %s::vector
LIMIT %s
""",
(self.course, query_str, num_results)
).fetchall()
return [
{'course': r[0], 'section': r[1], 'question': r[2], 'answer': r[3]}
for r in rows
]In [16]python · cell 12
python
from dotenv import load_dotenv
from openai import OpenAI
load_dotenv()
openai_client = OpenAI()In [17]python · cell 13
python
vector_assistant = RAGPgVector(
embedder=model,
conn=conn,
llm_client=openai_client,
)In [18]python · cell 14
python
vector_assistant.rag('the program has already begun, can I still sign up?')Output
'Yes, you can still join. If you want a certificate, make sure you submit your project while submissions are still being accepted.'
In [ ]python · cell 15
python
