Noua istorie

Construiți un sistem AI pentru a vă recomanda cele mai jazz pantalonii (sau orice alt costum) de pe planetă

de Superlinked13m2025/04/25
Read on Terminal Reader

Prea lung; A citi

Majoritatea recomandatorilor de comerț electronic sunt fie prea statice (bazate pe reguli), fie prea cutii negre (modele ML opace). Superlinked oferă o cale de mijloc: recomandări flexibile, în timp real, care se pot adapta la utilizatorii cu start rece prin combinarea metadatelor cu comportamentul live - toate fără a re-antrenarea modelelor ML.
featured image - Construiți un sistem AI pentru a vă recomanda cele mai jazz pantalonii (sau orice alt costum) de pe planetă
Superlinked HackerNoon profile picture
0-item
1-item


Ce-ar fi dacă magazinul dvs. online ar ști ce dorește un client înainte de a-l face?

Ce-ar fi dacă magazinul dvs. online ar ști ce dorește un client înainte de a-l face?


Most recommendation engines are like helpful but slightly clueless assistants:sugerează elemente „populare” sau „similare” bazate pe date limitate, depășite.struggleatunci când utilizatorii sunt noi (problema de pornire rece) și rareori se adaptează suficient de repede atunci când preferințele unui utilizator se schimbă în timp real.


Dar dacă sistemul dumneavoastră ar puteaDe fapt, gândescca un merchandiser – combinând datele statice ale produsului și comportamentul utilizatorului în timp real la suprafațăArticolele potriviteLa momentul potrivit?

De fapt, gândesc


This guide walks you through building a modern recommendation engineUtilizareaSuperlinked, unul care depășește aceste deficiențe tradiționale, transformând datele în profiluri de utilizator acționabile, în evoluție, folosind o infrastructură nativă vectorială.


(Vrei să sari direct la cod? Verificați codul open source pe GitHub aici. gata să încercați sistemele de recomandare pentru propriul dvs. caz de utilizare? Obțineți o demonstrație aici.)

AiciAiciAiciAici


Puteți urmări, de asemenea, împreună cu tutorialul în browser cuColabă .


Răspunde dr:

Majoritatea recomandatorilor de comerț electronic sunt fie prea statice (bazate pe reguli), fie prea cutii negre (modele ML opace). Superlinked oferă o cale de mijloc: recomandări flexibile, în timp real, care se pot adapta la utilizatorii cu start rece prin combinarea metadatelor cu comportamentul live - toate fără a re-antrenarea modelelor ML.

Realizarea personalizării în ciuda provocărilor legate de încorporarea vectorului RecSys

În timp ce integrările vectoriale pot îmbunătăți foarte mult sistemele de recomandare, implementarea lor eficientă necesită abordarea mai multor provocări, inclusiv:


  • Calitate și relevanță: Procesul de generare încorporată, arhitectura și datele trebuie luate în considerare cu atenție.
  • Date slabe și zgomotoase: Încorporările sunt mai puțin eficiente atunci când au intrări incomplete sau zgomotoase.
  • Scalabilitate: Sunt necesare metode eficiente pentru seturi mari de date; în caz contrar, latența va fi o problemă.


Superlinked vă permite să abordați aceste provocări combinând toate datele disponibile despre utilizatori și produse în vectori multimodali bogați. În exemplul nostru de comerț electronic RecSys de mai jos, facem acest lucru folosind următoarele elemente ale bibliotecii Superlinked:


  • min_max Număr de spații: pentru a înțelege recenziile clienților și informațiile despre prețuri
  • text-similarity Spațiu: pentru înțelegerea semantică a informațiilor despre produs
  • Schema evenimentelor și efectele pentru a modifica vectorii
  • cântărirea timpului de interogare - pentru a defini modul în care doriți ca datele să fie tratate atunci când rulați interogarea, permițându-vă să optimizați și să scalați fără a reîncorpora întregul set de date (latență)


Prin încorporarea datelor noastre inițial rare specifice utilizatorului (preferința inițială a produsului utilizatorului), putem face față problemei de pornire rece.Hiper- Personalizarea recomandărilor prin încorporarea acestor date de eveniment, crearea unei bucle de feedback care vă permite să actualizați vectorii cu preferințele utilizatorului în timp real.


Let's get started!

Construirea unui motor de recomandare a comerțului electronic cu Superlinked

La începutul dezvoltării, avem următoareleproduct data: din


  • Numărul de recenzii
  • Evaluarea produselor
  • Descrierea textului
  • Denumirea produsului (care conține de obicei denumirea mărcii)
  • Categorii

De asemenea, avem următoareledata about users and products: din


  1. fiecare utilizator alege unul dintre cele trei produse oferite atunci când se înregistrează (adică date despre preferințele produselor)
  2. comportamentul utilizatorului (după înregistrare) furnizează date suplimentare de eveniment - preferințe pentru caracteristicile textuale ale produselor (descriere, nume, categorie)

De asemenea, economia clasică ne spune că, în medie, toți utilizatorii ceteris paribus preferă produse care:


  • Costă mai puțin
  • Avem multe recenzii
  • Câștigă ratinguri mai mari

Putem seta spațiile noastre pentru a lua în considerare aceste date, astfel încât RecSys funcționează în scenarii de start rece - recomandând elemente pentru utilizatorii despre care știm foarte puțin. odată ce RecSys este în funcțiune și funcționează, vom avea, de asemenea, date comportamentale: utilizatorii vor face clic pe anumite produse, vor cumpăra anumite produse etc. Putem captura și utiliza aceste date de eveniment pentru a crea fluxuri de feedback, pentru a actualiza vectorii noștri pentru a reflecta preferințele utilizatorilor și pentru a îmbunătăți calitatea recomandărilor.

Crearea unui superlink

În primul rând, trebuie să instalați biblioteca Superlinked și să importați clasele.


%pip install superlinked==6.0.0

import altair as alt
import os
import pandas as pd
import sys


from superlinked.framework.common.embedding.number_embedding import Mode
from superlinked.framework.common.schema.schema import schema
from superlinked.framework.common.schema.event_schema import event_schema
from superlinked.framework.common.schema.schema_object import String, Integer
from superlinked.framework.common.schema.schema_reference import SchemaReference
from superlinked.framework.common.schema.id_schema_object import IdField
from superlinked.framework.common.parser.dataframe_parser import DataFrameParser
from superlinked.framework.dsl.executor.in_memory.in_memory_executor import (
   InMemoryExecutor,
   InMemoryApp,
)
from superlinked.framework.dsl.index.index import Index
from superlinked.framework.dsl.index.effect import Effect
from superlinked.framework.dsl.query.param import Param
from superlinked.framework.dsl.query.query import Query
from superlinked.framework.dsl.source.in_memory_source import InMemorySource
from superlinked.framework.dsl.space.text_similarity_space import TextSimilaritySpace
from superlinked.framework.dsl.space.number_space import NumberSpace


alt.renderers.enable(get_altair_renderer())
pd.set_option("display.max_colwidth", 190)


De asemenea, definim seturile noastre de date și creăm o constantă pentru stocarea celor mai bune 10 elemente - veziCelulă 3în notebook.

Acum că bibliotecile au fost instalate, clasele importate și locațiile seturilor de date identificate, putem arunca o privire la setul nostru de date pentru a informa modul în care ne-am configurat spațiile. Inițial, avem date din înregistrarea utilizatorilor - adică care dintre cele trei produse user_1 și user_2 au ales.


# the user preferences come from the user being prompted to select a product out of 3 - those will be the initial preferences
# this is done in order to give somewhat personalised recommendations
user_df: pd.DataFrame = pd.read_json(USER_DATASET_URL)
user_df


User product pref at registration


De asemenea, putem stabili o examinare atentă a datelor de distribuție ale produselor noastre - vezicelulă 5Acest lucru vă oferă o imagine a numărului de produse care se află la diferite puncte de preț, au număruri diferite de recenzii și au evaluări diferite (inclusiv în cazul în care majoritatea produselor se află în aceste intervale).


Number of products vs price, review count, and rating distributions


Prețurile pentru produse sunt în mare parte sub prețul de 1000 $. Este posibil să dorim să stabilim intervalul spațial la 25-1000 pentru a-l face reprezentativ, nedistorsionat de valorile exterioare. Cifrele de revizuire a produselor sunt distribuite în mod egal, iar ratingurile de revizuire sunt distribuite relativ uniform, astfel încât nu este necesară nicio tratament suplimentar.Celulele 7-9. .

Crearea indexului pentru căutarea vectorilor

Biblioteca Superlinked conține un set de blocuri de bază pe care le folosim pentru a construi indexul și pentru a gestiona recuperarea.Aici. .


Să punem blocurile de construcție ale acestei biblioteci pentru a fi utilizate în EComm RecSys.define your Schemapentru a spune sistemului despre datele dvs.


# schema is the way to describe the input data flowing into our system - in a typed manner
@schema
class ProductSchema:
   description: String
   name: String
   category: String
   price: Integer
   review_count: Integer
   review_rating: Integer
   id: IdField

@schema
class UserSchema:
   preference_description: String
   preference_name: String
   preference_category: String
   id: IdField

@event_schema
class EventSchema:
   product: SchemaReference[ProductSchema]
   user: SchemaReference[UserSchema]
   event_type: String
   id: IdField

# we instantiate schemas as follows
product = ProductSchema()
user = UserSchema()
event = EventSchema()


Apoi, utilizați spații pentru a spune cum doriți să tratați fiecare parte a datelor atunci când încorporați. În definițiile spațiului, descriem cum să încorporați intrările astfel încât acestea să reflecte relațiile semantice din datele noastre. Fiecare spațiu este optimizat pentru a încorpora datele pentru a returna cea mai înaltă calitate posibilă a rezultatelor de recuperare.


# textual inputs are embedded in a text similarity space powered by a sentence_transformers model
description_space = TextSimilaritySpace(
   text=[user.preference_description, product.description],
   model="sentence-transformers/all-distilroberta-v1",
)
name_space = TextSimilaritySpace(
   text=[user.preference_name, product.name],
   model="sentence-transformers/all-distilroberta-v1",
)
category_space = TextSimilaritySpace(
   text=[user.preference_category, product.category],
   model="sentence-transformers/all-distilroberta-v1",
)

# NumberSpaces encode numeric input in special ways to reflect a relationship
# here we express relationships to price (lower the better), or ratings and review counts (more/higher the better)
price_space = NumberSpace(
   number=product.price, mode=Mode.MINIMUM, min_value=25, max_value=1000
)
review_count_space = NumberSpace(
   number=product.review_count, mode=Mode.MAXIMUM, min_value=0, max_value=100
)
review_rating_space = NumberSpace(
   number=product.review_rating, mode=Mode.MAXIMUM, min_value=0, max_value=4
)

# create the index using the defined spaces
product_index = Index(
   spaces=[
       description_space,
       name_space,
       category_space,
       price_space,
       review_count_space,
       review_rating_space,
   ]
)

# parse our data into the schemas - not matching column names can be conformed to schemas using the mapping parameter
product_df_parser = DataFrameParser(schema=product)
user_df_parser = DataFrameParser(
   schema=user, mapping={user.preference_description: "preference_desc"}
)

# setup our application
source_product: InMemorySource = InMemorySource(product, parser=product_df_parser)
source_user: InMemorySource = InMemorySource(user, parser=user_df_parser)
executor: InMemoryExecutor = InMemoryExecutor(
   sources=[source_product, source_user], indices=[product_index]
)
app: InMemoryApp = executor.run()

# load the actual data into our system
source_product.put([products_df])
source_user.put([user_df])


Acum că aveți datele definite în spații, sunteți gata să vă jucați cu datele și să optimizați rezultatele.Ce se poate face fără evenimenteSoluția noastră de start rece.

Rezolvarea problemei de pornire la rece a RecSys

Aici, definim o interogare de utilizator care caută numai cu vectorul preferințelor utilizatorului.


user_query = (
   Query(
       product_index,
       weights={
           description_space: Param("description_weight"),
           name_space: Param("name_weight"),
           category_space: Param("category_weight"),
           price_space: Param("price_weight"),
           review_count_space: Param("review_count_weight"),
           review_rating_space: Param("review_rating_weight"),
       },
   )
   .find(product)
   .with_vector(user, Param("user_id"))
   .limit(Param("limit"))
)

# simple recommendations for our user_1
# these are based only on the initial product the user chose when first entering our site
simple_result = app.query(
   user_query,
   user_id="user_1",
   description_weight=1,
   name_weight=1,
   category_weight=1,
   price_weight=1,
   review_count_weight=1,
   review_rating_weight=1,
   limit=TOP_N,
)

simple_result.to_pandas()


Rezultatele acestei interogări reflectă faptul că user_1 a ales o geantă atunci când s-a înregistrat pentru prima dată pe site-ul nostru ecomm.


User 1 registration product choice-based recs


De asemenea, este posibil să recomandați produse utilizatorului_1 care suntîn generalatractive - adică bazate pe prețul lor fiind scăzut, și având o mulțime de recenzii bune. rezultatele noastre vor reflecta acum atât alegerea produsului user_1 la înregistrareşipopularitatea generală a produselor. (Putem juca și cu aceste greutăți pentru a distorsiona rezultatele în direcția unui spațiu sau a altuia.)


general_result = app.query(
   user_query,
   user_id="user_1",
   description_weight=0,
   name_weight=0,
   category_weight=0,
   price_weight=1,
   review_count_weight=1,
   review_rating_weight=1,
   limit=TOP_N,
)

general_result.to_pandas() 



General product features-based recs

Căutarea unui utilizator nou introduce textul interogării ca intrare pentru rezultatele recomandărilor noastre - a se vedeaCelulă 20. .

În cazul nostru de exemplu, user_1 a căutat "pantofi pentru femei". ne putem optimiza rezultatele oferindadditional weight to the category space(încategory_weight = 10), pentru a recomanda mai multe produse „jachetele de îmbrăcăminte pentru femei”.


women_cat_result = app.query(
   search_query,
   user_id="user_1",
   query_text="women clothing jackets",
   description_weight=1,
   name_weight=1,
   category_weight=10,
   price_weight=1,
   review_count_weight=1,
   review_rating_weight=1,
   limit=TOP_N,
)

women_cat_result.to_pandas()


Greutatea noastră suplimentară de categorie produce mai multe rezultate de îmbrăcăminte pentru femei.


User 1 query for "women clothing jackets" recs.png


Putem, de asemenea, să împărtășim recomandările noastre pentru produsele de top (review_rating_weight=5Rezultatele reflectă acum preferința inițială a user_1 pentru genți și articole care sunt în general populare, în timp ce produsele cu evaluări scăzute sunt eliminate complet.Celulă 22. .

Utilizarea datelor despre evenimente pentru a crea experiențe personalizate

Utilizatorii noștri au interacționat cu platforma noastră - user_1 mai mult, user_2 mai puțin.behavioral data(a se vedea mai jos), reprezentate ca evenimente:

  • un utilizator interesat de produse casual și de agrement (user_2)
  • un utilizator interesat de produse elegante pentru excursii și ocazii formale de lucru (user_1)
events_df = (
   pd.read_json(EVENT_DATASET_URL)
   .reset_index()
   .rename(columns={"index": "id"})
   .head(NROWS)
)
events_df = events_df.merge(
   products_df[["id"]], left_on="product", right_on="id", suffixes=("", "r")
).drop("idr", axis=1)
events_df = events_df.assign(created_at=1715439600)

events_df


user events

Să cântărim acțiunile specifice pentru a înregistra nivelul de interes al utilizatorului pentru un anumit produs și să ajustăm setarea pentru a ține seama de evenimente atunci când efectuați recuperarea.

event_weights = {
   "clicked_on": 0.2,
   "buy": 1,
   "put_to_cart": 0.5,
   "removed_from_cart": -0.5,
}

# adjust the setup to events
product_index_with_events = Index(
    spaces=[
        description_space,
        category_space,
        name_space,
        price_space,
        review_count_space,
        review_rating_space,
    ],
    effects=[
        Effect(
            description_space,
            event.user,
            event_weight * event.product,
            event.event_type == event_type,
        )
        for event_type, event_weight in event_weights.items()
    ]
    + [
        Effect(
            category_space,
            event.user,
            event_weight * event.product,
            event.event_type == event_type,
        )
        for event_type, event_weight in event_weights.items()
    ]
    + [
        Effect(
            name_space,
            event.user,
            event_weight * event.product,
            event.event_type == event_type,
        )
        for event_type, event_weight in event_weights.items()
    ],
)
event_df_parser: DataFrameParser = DataFrameParser(schema=event)
source_event: InMemorySource = InMemorySource(schema=event, parser=event_df_parser)
executor_with_events: InMemoryExecutor = InMemoryExecutor(
    sources=[source_product, source_user, source_event],
    indices=[product_index_with_events],
)
app_with_events: InMemoryApp = executor_with_events.run()


Acum creăm un nou index pentru a ține cont de evenimentele utilizatorilor și apoi personalizăm recomandările fiecărui utilizator în consecință.

# for a new index, all data has to be put into the source again
source_product.put([products_df])
source_user.put([user_df])
source_event.put([events_df])

# a query only searching with the user's vector the preferences are now much more personalised thanks to the events
personalised_query = (
   Query(
       product_index_with_events,
       weights={
           description_space: Param("description_weight"),
           category_space: Param("category_weight"),
           name_space: Param("name_weight"),
           price_space: Param("price_weight"),
           review_count_space: Param("review_count_weight"),
           review_rating_space: Param("review_rating_weight"),
       },
   )
   .find(product)
   .with_vector(user, Param("user_id"))
   .limit(Param("limit"))
)


Putem observa impactul încorporării evenimentelor în RecSys prin ponderarea personalizăriidoar uşorsaugreațăMai întâi, să vedem efectul (în comparație cu baza) de cântărire a spațiilor care sunt influențate de aceste (date comportamentale) evenimente.

# with small weight on event-affected spaces, we mainly just alter the results below position 4
general_event_result = app_with_events.query(
   personalised_query,
   user_id="user_1",
   description_weight=1,
   category_weight=1,
   name_weight=1,
   price_weight=1,
   review_count_weight=1,
   review_rating_weight=1,
   limit=TOP_N,
)

general_event_result.to_pandas().join(
   simple_result.to_pandas(), lsuffix="", rsuffix="_base"
)[["description", "id", "description_base", "id_base"]]


Cu foarte puțină greutate pusă pe Spații afectate de evenimente, observăm o schimbare, dar în principal numai în a doua jumătate a top 10, în comparație cu rezultatele anterioare ("id_base", în dreapta).


Slightly weighted events-affected spaces vs baseline


Dar dacă cântărim mai mult spațiile afectate de evenimente, vom înfățișa elemente complet noi în lista noastră de recomandări.


# with larger weight on the the event-affected spaces, more totally new items appear in the TOP10
event_weighted_result = app_with_events.query(
   personalised_query,
   user_id="user_1",
   query_text="",
   description_weight=5,
   category_weight=1,
   name_weight=1,
   price_weight=1,
   review_count_weight=1,
   review_rating_weight=1,
   limit=TOP_N,
)

event_weighted_result.to_pandas().join(
   simple_result.to_pandas(), lsuffix="", rsuffix="_base"
)[["description", "id", "description_base", "id_base"]]


More heavily weighted events-affected spaces vs baseline


De asemenea, putem, desigur, să folosim ponderile pentru a personaliza recomandările noastre pe baza comportamentului unui anumit utilizator (date despre evenimente) șiprioritizează în același timp alte atribute ale produsuluiDe exemplu, prețul (a se vedeaCelulă 31) din

Concluzie

Implementarea eComm RecSys a bibliotecii Superlinked (de mai sus) vă arată cum să realizați puterea încorporărilor vectoriale prin încorporarea semnificației semantice a interogărilor utilizatorilor și a datelor comportamentale. Folosind spațiile noastre min_max de număr și text-similaritate, schema de evenimente și efecte și ponderile timpului de interogare, puteți aborda provocările de început rece, calitate și relevanță și scalabilitate ale RecSys și puteți oferi recomandări extrem de precise, personalizate de utilizator în producție.

Acum e rândul tău!Încercați să implementați biblioteca Superlinked folosind notebook-ul nostru. .

Try It Yourself – Get the Code & Demo!

Încercați-l singur - Obțineți codul și demo-ul!
  • Prindeți codul: Verificați implementarea completă în repo-ul nostru GitHub aici.Fork-o, ajustați-o și faceți-o pe a voastră!
  • Vezi în acțiune: Vrei să vezi acest lucru funcționând într-o setare reală? Rezervați o demonstrație rapidă și explorați cum Superlinked vă poate supraîncărca recomandările. Obțineți o demonstrație acum!
AiciAici. .

Motoarele de recomandare modelează modul în care descoperim conținutul, fie că este vorba de pantaloni populari, muzică sau alte produse,vector search is the future– și acum aveți instrumentele pentru a vă construi propriul.

Trending Topics

blockchaincryptocurrencyhackernoon-top-storyprogrammingsoftware-developmenttechnologystartuphackernoon-booksBitcoinbooks