Nova Història

Construeix un sistema d'IA per recomanar-te els pantalons Jazziest (o qualsevol altre vestit) del planeta

per Superlinked13m2025/04/25
Read on Terminal Reader

Massa Llarg; Per llegir

La majoria dels recomanadors de comerç electrònic són massa estàtics (basats en regles) o massa de caixa negra (models ML opacs). Superlinked ofereix un camí mitjà: recomanacions flexibles, en temps real que es poden adaptar als usuaris d'inici en fred combinant metadades amb el comportament en viu - tot sense haver de tornar a entrenar els models ML.
featured image - Construeix un sistema d'IA per recomanar-te els pantalons Jazziest (o qualsevol altre vestit) del planeta
Superlinked HackerNoon profile picture
0-item
1-item


El

Què passaria si la teva botiga en línia sabés què volia un client abans de fer-ho?

El

Què passaria si la teva botiga en línia sabés què volia un client abans de fer-ho?


Most recommendation engines are like helpful but slightly clueless assistants:suggereixen elements “populars” o “similars” basats en dades limitades i obsoletes.strugglequan els usuaris són nous (el problema d'inici fred), i rarament s'adapten prou ràpid quan les preferències d'un usuari canvien en temps real.


I si el sistema poguésDe fet, pensencom un merchandiser, combinant dades estàtiques del producte i el comportament de l'usuari en temps real a la superfícieEls elements adequatsEn el moment adequat?

De fet, pensen


This guide walks you through building a modern recommendation engineUtilitzacióSuperlinked, una que supera aquestes deficiències tradicionals convertint les seves dades en perfils d'usuari actuables i en evolució utilitzant una infraestructura vectorial nativa.


(Voleu saltar directament al codi? comproveu el codi de codi obert a GitHub aquí. Preparat per provar els sistemes de recomanació per al vostre propi cas d'ús?

AquíAquíAquíAquí


També podeu seguir el tutorial en el navegador amb el nostreCol·laboració


Títol: El Dr

La majoria dels recomanadors de comerç electrònic són massa estàtics (basats en regles) o massa de caixa negra (models ML opacs). Superlinked ofereix un camí mitjà: recomanacions flexibles, en temps real que es poden adaptar als usuaris d'inici en fred combinant metadades amb el comportament en viu - tot sense haver de tornar a entrenar els models ML.

Aconseguir la personalització malgrat els reptes de la incorporació vectorial de RecSys

Mentre que les incorporacions vectorials poden millorar enormement els sistemes de recomanació, implementar-los de manera efectiva requereix abordar diversos reptes, incloent:


    El
  • Qualitat i rellevància: El procés de generació d'embossos, l'arquitectura i les dades han de ser considerats acuradament.
  • El
  • Dades escasses i sorolloses: Les incorporacions són menys efectives quan tenen entrades incompletes o sorolloses.
  • El
  • Escalabilitat: es necessiten mètodes eficients per a grans conjunts de dades; en cas contrari, la latència serà un problema.
  • El


Superlinked us permet abordar aquests reptes combinant totes les dades disponibles sobre usuaris i productes en rics vectors multimodals. En el nostre exemple de comerç electrònic RecSys a continuació, fem això utilitzant els següents elements de la biblioteca Superlinked:


    El
  • min_max espais de nombre: per entendre les opinions dels clients i la informació de preus
  • El
  • text-similarity Espai: per a la comprensió semàntica de la informació del producte
  • El
  • Esquema d'esdeveniments i efectes per modificar vectors
  • El
  • pesos de temps de consulta: per definir com voleu que les dades siguin tractades quan executeu la consulta, permetent-vos optimitzar i escalar sense reincorporar tot el conjunt de dades (latència)
  • El


En incorporar les nostres inicialment escasses dades específiques de l'usuari (preferència inicial del producte de l'usuari), podem fer front al problema d'inici fred.Hipèrbiapersonalitzar les recomanacions incorporant aquestes dades d'esdeveniments, creant un bucle de retroalimentació que li permet actualitzar vectors amb preferències d'usuari en temps real.


Let's get started!

Construir un motor de recomanació de comerç electrònic amb Superlinked

A l’inici del desenvolupament tenim el següent:product data· :


    El
  • Nombre de revisors
  • El
  • Classificació de productes
  • El
  • Descripció textual
  • El
  • Nom del producte (normalment amb nom de marca)
  • El
  • Categoria
  • El

També tenim el següentdata about users and products· :


    El
  1. cada usuari tria un dels tres productes oferts en el moment de registrar-se (és a dir, dades de preferència del producte)
  2. El
  3. comportament de l'usuari (després del registre) proporciona dades d'esdeveniments addicionals - preferències per a les característiques textuals dels productes (descripció, nom, categoria)
  4. El

A més, l’economia clàssica ens diu que, de mitjana, tots els usuaris ceteris paribus prefereixen productes que:


    El
  • Costen menys
  • El
  • Tenen moltes crítiques
  • El
  • Tenen una qualificació més alta
  • El

Podem configurar els nostres espais per tenir en compte aquestes dades, de manera que els nostres RecSys funcionin en escenaris d'inici fred - recomanant articles per a usuaris sobre els quals sabem molt poc. Una vegada que els nostres RecSys estiguin en funcionament, també tindrem dades de comportament: els usuaris faran clic en determinats productes, compraran determinats productes, etc. Podem capturar i utilitzar aquestes dades d'esdeveniments per crear fluxos de retroalimentació, actualitzar els nostres vectors per reflectir les preferències dels usuaris i millorar la qualitat de la recomanació.

Instal·lació de superenllaços

En primer lloc, cal instal·lar la biblioteca Superlinked i importar les classes.


%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)


També definim els nostres conjunts de dades i creem una constant per emmagatzemar els 10 primers elements.Cèl·lula 3En el notebook.

Ara que s'han identificat les ubicacions instal·lades de la biblioteca, les classes importades i els conjunts de dades, podem fer una ullada al nostre conjunt de dades per informar de la manera com configurem els nostres espais. Inicialment, tenim dades de registre d'usuari - és a dir, quin dels tres productes usuaris_1 i usuaris_2 han triat.


# 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


També podem establir un examen detallat de les dades de distribució dels nostres productes - vegeuCèl·lula 5Això li dóna una idea de quants productes estan en diferents punts de preu, tenen diferents recomptes i tenen diferents qualificacions (inclòs on la majoria dels productes es troben en aquests rangs).


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


Els preus dels productes estan majoritàriament per sota del punt de preu de 1.000 dòlars. Pot ser que vulguem establir el rang d'espai a 25-1000 per fer-lo representatiu, sense distorsions per valors externs. Els comptes de revisió de productes es distribueixen de manera uniforme, i les qualificacions de revisió es distribueixen relativament uniformement, de manera que no es requereix cap tractament addicional.Cèl·lules 7-9. el

Creació de l'índex per a la cerca vectorial

La biblioteca de Superlinked conté un conjunt de blocs de construcció del nucli que utilitzem per construir l'índex i gestionar la recuperació.Aquí. el


Posem els blocs de construcció d'aquesta biblioteca per utilitzar-los en el nostre EComm RecSys.define your SchemaPer informar el sistema sobre les seves dades.


# 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()


A continuació, utilitzeu els espais per dir com voleu tractar cada part de les dades quan s'integren. En les definicions d'espai, descriu com incrustar les entrades perquè reflecteixin les relacions semàntiques de les nostres dades. Cada espai està optimitzat per incrustar les dades per retornar la màxima qualitat possible dels resultats de recuperació.


# 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])


Ara que teniu les vostres dades definides en espais, esteu a punt per jugar amb les vostres dades i optimitzar els resultats.Què podem fer sense esdevenimentsLa nostra solució d’inici fred.

Resoldre el problema d'inici fred de RecSys

Aquí, definim una consulta d'usuari que cerca només amb el vector de preferència de l'usuari. Tenim control de configuració sobre la importància (peses) de cada tipus d'entrada (Espai).


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()


Els resultats d'aquesta consulta reflecteixen el fet que user_1 va triar una bossa de mà quan es va registrar per primera vegada al nostre lloc de ecomm.


User 1 registration product choice-based recs


També és possible recomanar productes a l'usuari_1 que sónGeneralmentatractiu - és a dir, basat en el seu preu ser baix, i tenir un munt de bones crítiques. Els nostres resultats reflectiran ara tant l'elecció de producte de l'usuari_1 en el moment del registreila popularitat general dels productes. (També podem jugar amb aquests pesos per desviar els resultats en la direcció d'un espai o un altre.)


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

La cerca d'un nou usuari introdueix text de consulta com a entrada per als nostres resultats de recomanació - vegeuCèl·lula 20. el

En el nostre cas d'exemple, l'usuari_1 va cercar "pantalons per a dones". podem optimitzar els nostres resultats donantadditional weight to the category space(quecategory_weight = 10), per recomanar més productes de "jaquetes de roba femenina".


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()


El nostre pes de categoria addicional produeix més resultats de roba de dones.


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


També podem biar les nostres recomanacions als productes de la classificació superior (review_rating_weight=5Els resultats reflecteixen ara la preferència inicial de l'usuari_1 per les bosses i els articles que són generalment populars, mentre que els productes amb classificacions baixes s'eliminen completament.Cèl·lula 22. el

Utilitzar dades d'esdeveniments per crear experiències personalitzades

Els nostres usuaris han interactuat amb la nostra plataforma - user_1 més, user_2 menys.behavioral data(vegeu més avall), representats com a esdeveniments:

    El
  • un usuari interessat en productes casual i d'oci (user_2)
  • El
  • un usuari interessat en productes elegants per sortir i ocasions formals de treball (user_1)
  • El
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

Anem a ponderar accions específiques per registrar el nivell d'interès de l'usuari en un producte en particular, i ajustar la configuració per tenir en compte els esdeveniments en realitzar la recuperació.

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()


Ara creem un nou índex per tenir en compte els esdeveniments dels usuaris, i després personalitzem les recomanacions a cada usuari d'acord. Fins i tot les consultes basades només en el vector de l'usuari ara són molt més personalitzades que abans.

# 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"))
)


Podem observar l'impacte de la incorporació d'esdeveniments als nostres RecSys pesant la personalitzacióNomés una micaopesatPrimer, anem a veure l'efecte (en comparació amb la base) de pesar els espais que estan influïts per aquests (dades de comportament) esdeveniments.

# 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"]]


Amb molt poc pes posat en els espais afectats per esdeveniments, observem un canvi però principalment només en la segona meitat del nostre top 10, en comparació amb els resultats anteriors ("id_base", a la dreta).


Slightly weighted events-affected spaces vs baseline


Però si pesem més els espais afectats per l'esdeveniment, superposem elements completament nous a la nostra llista de recomanacions.


# 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


També podem, per descomptat, utilitzar pesos per personalitzar les nostres recomanacions basades en el comportament d'un usuari en particular (dades d'esdeveniments) iPrioritzar altres atributs del productePer exemple, el preu (veureCèl·lula 31) i

Conclusió

La implementació d'eComm RecSys de la biblioteca Superlinked (a dalt) us mostra com realitzar el poder de les incorporacions vectorials incorporant el significat semàntic de les consultes d'usuari i les dades de comportament. Utilitzant els nostres espais de nombre min_max i similitud de text, esquema d'esdeveniments i efectes i pesos de temps de consulta, podeu abordar els reptes d'inici fred, qualitat i rellevància i escalabilitat de RecSys i proporcionar recomanacions altament precises i personalitzades per a l'usuari en la producció.

Ara és el teu torn!Intenta implementar la biblioteca superenllaçada utilitzant el nostre bloc de notes. el

Try It Yourself – Get the Code & Demo!

Proveu-ho vosaltres mateixos - Get the Code & Demo!
    El
  • Grab the Code: Consulteu la implementació completa en el nostre repo de GitHub aquí.Fork-lo, ajusteu-lo i feu-lo vostre!
  • El
  • Veure-ho en acció: Vols veure que funciona en un món real? Reserva una demostració ràpida i explora com Superlinked pot sobrecarregar les teves recomanacions.
  • El
AquíAquí. el

Els motors de recomanació estan configurant la forma en què descobrim contingut, ja siguin pantalons populars, música o altres productes,vector search is the future—i ara tens les eines per construir la teva pròpia.

Trending Topics

blockchaincryptocurrencyhackernoon-top-storyprogrammingsoftware-developmenttechnologystartuphackernoon-booksBitcoinbooks