| Version 7 (modified by , 3 days ago) ( diff ) |
|---|
Advanced Phase
Опис
Имплементација на систем за препораки базиран на AI embeddings користејќи pgvector екстензија за PostgreSQL. Секоја активност, услуга и опрема добива своја векторска репрезентација (embedding) на нејзиниот опис, а системот наоѓа математички слични записи преку cosine similarity.
Како функционира?
Основната идеја е дека текстот (опис на активност, услуга или опрема) се претвора во вектор — листа од броеви каде секој број го претставува значењето на зборот во тој текст. Колку се векторите поблиску математички, толку се посличните записи.
Опис на запис → AI модел → Vector [0.23, 0.89, ...] → Слични записи
Чекори
Чекор 1
Инсталација на pgvector во Docker контејнерот и активирање на екстензијата во PostgreSQL
docker exec -it camping-postgres bash -c \ "apt-get update && apt-get install -y postgresql-16-pgvector"
CREATE EXTENSION IF NOT EXISTS vector;
Чекор 2
На табелите Activity, Service и Equipment се додава нова колона од тип vector(384). Димензијата 384 одговара на моделот all-MiniLM-L6-v2 кој се користи за генерирање на embeddings.
ALTER TABLE Activity ADD COLUMN embedding vector(384); ALTER TABLE Service ADD COLUMN embedding vector(384); ALTER TABLE Equipment ADD COLUMN embedding vector(384)
Чекор 3
Embeddings се генерираат преку Python скрипта која користи sentence-transformers библиотека.
Инсталација на потребните библиотеки
pip install sentence-transformers psycopg2-binary python-dotenv
Во .env фајлот ги пополнуваме HOST, PORT, NAME, USER, PASSWORD.
Креираме python скрипта generate_embeddings.py
import psycopg2
from sentence_transformers import SentenceTransformer
from dotenv import load_dotenv
import os
load_dotenv()
conn = psycopg2.connect(
host=os.getenv("DB_HOST"),
port=os.getenv("DB_PORT"),
database=os.getenv("DB_NAME"),
user=os.getenv("DB_USER"),
password=os.getenv("DB_PASSWORD")
)
cursor = conn.cursor()
model = SentenceTransformer('all-MiniLM-L6-v2')
# Embeddings za Activity
print("Generating embeddings for activities...")
cursor.execute("SELECT activity_id, description FROM Activity WHERE description IS NOT NULL")
activities = cursor.fetchall()
for activity_id, description in activities:
embedding = model.encode(description).tolist()
cursor.execute(
"UPDATE Activity SET embedding = %s WHERE activity_id = %s",
(embedding, activity_id)
)
conn.commit()
print(f"Done! {len(activities)} activities executed.")
# Embeddings za Service
print("Generating embeddings for services...")
cursor.execute("SELECT serviceId, description FROM Service WHERE description IS NOT NULL")
services = cursor.fetchall()
for service_id, description in services:
embedding = model.encode(description).tolist()
cursor.execute(
"UPDATE Service SET embedding = %s WHERE serviceId = %s",
(embedding, service_id)
)
conn.commit()
print(f"Done! {len(services)} services executed.")
# Embeddings za Equipment
print("Generating embeddings for Equipment...")
cursor.execute("SELECT equipmentId, description FROM Equipment WHERE description IS NOT NULL")
equipments = cursor.fetchall()
for equipment_id, description in equipments:
embedding = model.encode(description).tolist()
cursor.execute(
"UPDATE Equipment SET embedding = %s WHERE equipmentId = %s",
(embedding, equipment_id)
)
conn.commit()
print(f"Done! {len(equipments)} equipments executed.")
cursor.close()
conn.close()
Чекор 4
За брзо пребарување по сличност се креираат ivfflat индекси. Со ivfflat индекс, векторите се групираат во кластери и се пребарува само во најблиските.
CREATE INDEX ON Activity USING ivfflat (embedding vector_cosine_ops); CREATE INDEX ON Service USING ivfflat (embedding vector_cosine_ops); CREATE INDEX ON Equipment USING ivfflat (embedding vector_cosine_ops);
Чекор 5
Се креираат PostgreSQL функции кои примаат вектор и враќаат N најслични записи сортирани по cosine similarity.
Функција за слични активности
CREATE OR REPLACE FUNCTION find_similar_activities(
query_embedding vector,
top_n INT DEFAULT 5
)
RETURNS TABLE (activity_id INT, name VARCHAR, description VARCHAR, similarity FLOAT) AS $$
SELECT activity_id, name, description,
1 - (embedding <=> query_embedding) AS similarity
FROM Activity
WHERE embedding IS NOT NULL
ORDER BY embedding <=> query_embedding
LIMIT top_n;
$$ LANGUAGE sql;
Функција за слични услуги
CREATE OR REPLACE FUNCTION find_similar_services(
query_embedding vector,
top_n INT DEFAULT 5
)
RETURNS TABLE (serviceId INT, service_name VARCHAR, description VARCHAR, similarity FLOAT) AS $$
SELECT serviceId, service_name, description,
1 - (embedding <=> query_embedding) AS similarity
FROM Service
WHERE embedding IS NOT NULL
ORDER BY embedding <=> query_embedding
LIMIT top_n;
$$ LANGUAGE sql;
Функција за слична опрема
CREATE OR REPLACE FUNCTION find_similar_equipment(
query_embedding vector,
top_n INT DEFAULT 5
)
RETURNS TABLE (equipmentId INT, name VARCHAR, description VARCHAR, similarity FLOAT) AS $$
SELECT equipmentId, name, description,
1 - (embedding <=> query_embedding) AS similarity
FROM Equipment
WHERE embedding IS NOT NULL
ORDER BY embedding <=> query_embedding
LIMIT top_n;
$$ LANGUAGE sql;
Attachments (1)
- search_recommendations_swimming.png (63.7 KB ) - added by 39 hours ago.
Download all attachments as: .zip
