Changes between Initial Version and Version 1 of Advanced


Ignore:
Timestamp:
06/16/26 00:58:33 (3 days ago)
Author:
231166
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Advanced

    v1 v1  
     1= Напредна тема: Систем за семантички препораки на содржини базиран на NLP Embeddings =
     2
     3Оваа страница го опишува развојот и имплементацијата на напредниот хибриден подсистем за препораки во проектот '''VidiDB'''. Наместо да се потпреме исклучиво на класични оцена-базирани алгоритми, во овој модул имплементиравме обработка на природен јазик (NLP) за анализа на контекстот и емоциите скриени зад текстуалните коментари на корисниците.
     4
     5---
     6
     7== 1. Вовед и Мотивација ==
     8
     9Во современите стриминг платформи, квалитетот на препораките директно влијае врз задржувањето на корисниците на платформата. Класичните пристапи често паѓаат во замка кога две содржини со ист рејтинг (на пр. 8.5) имаат тотално различна емотивна конотација.
     10
     11Преку генерирање на векторски вгнездувања (Embeddings) базирани на корисничките коментари (`Review`), нашиот подсистем овозможува „читање помеѓу редови“. Целта е да се анализира емоцијата и контекстот што корисниците ги оставаат во текстуална форма, со што базата може да препознае скриени семантички врски меѓу филмовите и сериите кои не се видливи само преку чистите бројки.
     12
     13---
     14
     15== 2. Избор на алгоритам и јазичен модел ==
     16
     17За генерирање на густите семантички вектори е избран моделот '''all-MiniLM-L6-v2''' преку библиотеката `SentenceTransformers`. Ова решение беше преферирано поради следниве клучни предности:
     18
     191. '''Длабоко семантичко разбирање (NLP):''' Моделот не бара само совпаѓање на клучни зборови (keyword matching), туку го разбира значењето на речениците. На пример, фразите ''"Masterpiece of cinema"'' и ''"Absolutely amazing"'' математички ќе ги мапира блиску една до друга во повеќедимензионалниот простор бидејќи рефлектираат ист контекст.
     202. '''Ефикасност на локална архитектура (Lightweight):''' Моделот е оптимизиран за брза егзекуција на процесорско ниво (CPU Execution), што овозможува брзо локално тренирање и мапирање без потреба од скапа GPU инфраструктура.
     213. '''Димензионална адаптација:''' Иако моделот иницијално генерира вектори со 384 димензии, со цел да се оптимизира просторот во базата и да се задоволат реалните капацитети, извршивме димензионално кратење на првите 4 клучни димензии (`vector(4)`), кои ја задржуваат најгустата семантичка информација.
     22
     23---
     24
     25== 3. Процесирање на податоците (Data Pipeline) ==
     26
     27Архитектурата на обработка и трансформација на податоците се одвиваше локално низ три клучни фази:
     28
     29=== Фаза 1: Паметна SQL Агрегација на податоци ===
     30Бидејќи базата содржи огромна табела со коментари (`Review` со околу 10 милиони записи реално распределени низ содржините), извршувањето на индивидуален `UPDATE` за секој коментар поединечно би предизвикало огромен влезно-излезен застој (I/O Bottleneck). Затоа, со помош на упитот:
     31{{{
     32#!sql
     33SELECT r.ContentContentID, m.title, STRING_AGG(r.Comment, ' ') as all_reviews ...
     34}}}
     35направивме тешка текстуална агрегација на ниво на база. За секој филм/серија, сите кориснички коментари беа споени во еден заеднички мега-текст кој го претставува колективниот впечаток на публиката.
     36
     37=== Фаза 2: Генерирање на вектори (Python & PyCharm) ===
     38Податоците во пакет (Batch) беа повлечени во Python скриптата. За секој филм, се конструираше нов контекст од насловот и агрегираниот текст (`combined_context = f"{title}. Reviews: {all_reviews}"`). Овој текст се проследува до `model.encode()`, кој генерира низа од броеви (вектор) што претставува семантички отпечаток на тој филм.
     39
     40=== Фаза 3: Перзистенција и ажурирање на базата ===
     41Преку `psycopg2` драјверот, скриптата секој генериран вектор автоматски го запишуваше во колоната `embedding` во табелата `Media` за соодветното `ContentID`. Промените се потврдуваат трансакциски со `conn.commit()`.
     42
     43---
     44
     45== 4. Имплементација на ниво на База на Податоци (SQL) ==
     46
     47Подолу е прикажан SQL кодот со кој се активира векторската поддршка, се прави корекција/структурирање на табелата `Media` со додавање на колоната `embedding vector(4)`, и се извршува масовна популација (10 милиони записи) со случајни реални коментари за симулација на реално оптоварување.
     48
     49{{{
     50#!sql
     51-- 1. Ја активираме векторската екстензија во базата
     52CREATE EXTENSION IF NOT EXISTS vector;
     53
     54-- 2. Ја додаваме вистинската векторска колона во табелата media по направената структурна измена
     55ALTER TABLE media
     56ADD COLUMN embedding vector(4);
     57
     58-- тука требаше да направиме мала промена во табелата Review
     59
     60-- Чистење на претходни тест податоци
     61TRUNCATE TABLE "review" RESTART IDENTITY;
     62
     63-- 3. Анонимен PL/pgSQL блок за масовно полнење на 10 милиони коментари во табелата Review
     64DO $$
     65DECLARE
     66    user_ids int[] := ARRAY(SELECT UserID FROM "User");
     67    media_ids int[] := ARRAY(SELECT ContentID FROM "media");
     68    u_count int := cardinality(user_ids);
     69    m_count int := cardinality(media_ids);
     70BEGIN
     71    INSERT INTO "review" (Comment, ReviewDate, UserUserID, ContentContentID)
     72    SELECT
     73      (ARRAY[
     74        'Absolutely amazing, one of the best!',
     75        'Great story, highly recommend.',
     76        'A bit slow at the start but gets better.',
     77        'Masterpiece of cinema.',
     78        'Not what I expected but still enjoyable.',
     79        'Incredible performances all around.',
     80        'The ending blew my mind.',
     81        'Would watch again without hesitation.',
     82        'Overrated in my opinion.',
     83        'A classic that stands the test of time.',
     84        'Great cinematography and direction.',
     85        'The plot had some holes but overall good.',
     86        'One of the best series ever made.',
     87        'Keeps you on the edge of your seat.',
     88        'The writing is absolutely top-notch.',
     89        'Brilliant acting from start to finish.',
     90        'A must watch for everyone.',
     91        'Did not live up to the hype.',
     92        'Absolutely loved every minute of it.',
     93        'A cinematic masterpiece.',
     94        'This man is my worst nightmare. 10/10',
     95        'No.',
     96        'The portrayal of toxic relationships is very good.'
     97      ])[ceil(random() * 23)::int],
     98      CURRENT_DATE - (random() * 730)::int,
     99      -- Директно влечење од низата со нов случаен индекс за секој ред
     100      user_ids[ceil(random() * u_count)::int],
     101      media_ids[ceil(random() * m_count)::int]
     102    FROM
     103      generate_series(1, 10000000) AS gs;
     104END $$;
     105}}}
     106
     107---
     108
     109== 5. Имплементација на ETL Векторскиот Процес (Python) ==
     110
     111Оваа скрипта претставува мостот помеѓу базата и NLP моделот. Ги презема суровите коментари, ги трансформира во семантички вектори преку HuggingFace моделот и ги зачувува назад во базата.
     112
     113{{{
     114#!python
     115import psycopg2
     116from sentence_transformers import SentenceTransformer
     117
     118# 1. Поврзување со локалната база vidi_db
     119try:
     120    conn = psycopg2.connect(
     121        dbname="vidi_db",
     122        user="postgres",
     123        password="...",  # Поставете ја вашата системска лозинка
     124        host="localhost",
     125        port="5432"
     126    )
     127    cursor = conn.cursor()
     128    print("Успешно поврзување со локалната vidi_db!")
     129except Exception as e:
     130    print(f"Грешка при поврзување со базата: {e}")
     131    exit()
     132
     133# 2. Вчитување на NLP моделот за генерација на вектори
     134print("Се вчитува моделот за embeddings...")
     135model = SentenceTransformer('all-MiniLM-L6-v2')
     136
     137try:
     138    print("Ги влечам и ги групирам коментарите по содржина од локалната база...")
     139    # SQL упит за паметна агрегација со STRING_AGG
     140    query = """
     141        SELECT r.ContentContentID, m.title, STRING_AGG(r.Comment, ' ') as all_reviews
     142        FROM "review" r
     143        JOIN "media" m ON m.contentid = r.ContentContentID
     144        GROUP BY r.ContentContentID, m.title;
     145    """
     146    cursor.execute(query)
     147    rows = cursor.fetchall()
     148
     149    if not rows:
     150        print("Нема нови филмови со коментари кои чекаат за вектор.")
     151    else:
     152        print(f"Пронајдени се {len(rows)} филмови за обработка на коментари...")
     153
     154        updated_count = 0
     155        for row in rows:
     156            content_id = row[0]
     157            title = row[1]
     158            all_reviews = row[2] if row[2] else ""
     159
     160            # Комбинирање на контекстот: наслов + сите текстуални впечатоци
     161            combined_context = f"{title}. Reviews: {all_reviews}"
     162
     163            # Енкодирање во вектор и димензионално кратење до 4 димензии за vector(4)
     164            embedding_vector = model.encode(combined_context).tolist()
     165            truncated_vector = embedding_vector[:4]
     166
     167            # Ажурирање на соодветниот медиум
     168            cursor.execute(
     169                'UPDATE "media" SET embedding = %s WHERE contentid = %s;',
     170                (truncated_vector, content_id)
     171            )
     172            updated_count += 1
     173
     174            if updated_count % 100 == 0:
     175                print(f"  Процесирани {updated_count} филмови локално...")
     176
     177        # Зачувување на промените во базата
     178        conn.commit()
     179        print(f"\nУспешно ажурирани {updated_count} записи во локалната табела Media!")
     180
     181except Exception as e:
     182    print(f"Настана грешка при работа со локалната база: {e}")
     183    conn.rollback()
     184finally:
     185    cursor.close()
     186    conn.close()
     187    print("Врската со локалниот Postgres е затворена.")
     188}}}
     189
     190---
     191
     192== 6. Користење на податоците во продукција (Косинусно растојание) ==
     193
     194Откако табелата `Media` е целосно пополнета со вектори, пребарувањето на слични содржини е екстремно брзо и се извршува со чист SQL преку векторскиот оператор за косинусно растојание (`<=>`), кој е дел од `pgvector` екстензијата.
     195
     196Кога корисникот прегледува одредена содржина, системот во реално време препорачува '''топ 5 најсемантички слични содржини''' со следниов оптимизиран упит:
     197
     198{{{
     199#!sql
     200SELECT contentid, title,
     201       embedding <=> (SELECT embedding FROM "Media" WHERE contentid = :trenuten_film) AS distance
     202FROM "Media"
     203WHERE contentid != :trenuten_film AND embedding IS NOT NULL
     204ORDER BY distance ASC
     205LIMIT 5;
     206}}}
     207
     208=== Заклучок ===
     209Со ова напредно решение, платформата '''Vidi''' разви интелигентен механизам за семантички препораки. Доколку корисниците во коментарите за два различни филма независно пишуваат дека содржат *„неочекуван пресврт на крајот што го пореметува умот“* или *„одличен приказ на токсични врски“*, јазичниот модел математички ќе ги препознае овие фрази како блиски и ќе ги препорача тие содржини заедно, правејќи го корисничкото искуство супериорно.
     210
     211Тука може да ги погледнете SQL кодот и Python кодот: [attachment:generate_embeddings.py generate_embeddings.py] [attachment:console_14.sql console_14.sql]