El El Què passaria si la teva botiga en línia sabés què volia un client abans de fer-ho? Què passaria si la teva botiga en línia sabés què volia un client abans de fer-ho? suggereixen elements “populars” o “similars” basats en dades limitades i obsoletes. quan 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. Most recommendation engines are like helpful but slightly clueless assistants: struggle I si el sistema pogués com un merchandiser, combinant dades estàtiques del producte i el comportament de l'usuari en temps real a la superfície En el moment adequat? De fet, pensen Els elements adequats De fet, pensen Utilització , una que supera aquestes deficiències tradicionals convertint les seves dades en perfils d'usuari actuables i en evolució utilitzant una infraestructura vectorial nativa. This guide walks you through building a modern recommendation engine Superlinked (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 nostre Col·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 El El El Qualitat i rellevància: El procés de generació d'embossos, l'arquitectura i les dades han de ser considerats acuradament. Dades escasses i sorolloses: Les incorporacions són menys efectives quan tenen entrades incompletes o sorolloses. Escalabilitat: es necessiten mètodes eficients per a grans conjunts de dades; en cas contrari, la latència serà un problema. 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 El El El El min_max espais de nombre: per entendre les opinions dels clients i la informació de preus text-similarity Espai: per a la comprensió semàntica de la informació del producte Esquema d'esdeveniments i efectes per modificar vectors 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) 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. personalitzar 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. Hipèrbia 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 El El El El El Nombre de revisors Classificació de productes Descripció textual Nom del producte (normalment amb nom de marca) Categoria També tenim el següent · : data about users and products El El El cada usuari tria un dels tres productes oferts en el moment de registrar-se (és a dir, dades de preferència del producte) 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) A més, l’economia clàssica ens diu que, de mitjana, tots els usuaris ceteris paribus prefereixen productes que: El El El El Costen menys Tenen moltes crítiques Tenen una qualificació més alta 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. En el notebook. Cèl·lula 3 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 També podem establir un examen detallat de les dades de distribució dels nostres productes - vegeu Això 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). Cèl·lula 5 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. . el Cèl·lules 7-9 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ó. . el Aquí Posem els blocs de construcció d'aquesta biblioteca per utilitzar-los en el nostre EComm RecSys. Per informar el sistema sobre les seves dades. define your Schema # 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. La nostra solució d’inici fred. Què podem fer sense esdeveniments 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. També és possible recomanar productes a l'usuari_1 que són atractiu - é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 registre la popularitat general dels productes. (També podem jugar amb aquests pesos per desviar els resultats en la direcció d'un espai o un altre.) Generalment i 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() La cerca d'un nou usuari introdueix text de consulta com a entrada per als nostres resultats de recomanació - vegeu . el Cèl·lula 20 En el nostre cas d'exemple, l'usuari_1 va cercar "pantalons per a dones". podem optimitzar els nostres resultats donant (que ), per recomanar més productes de "jaquetes de roba femenina". additional weight to the category space category_weight = 10 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. També podem biar les nostres recomanacions als productes de la classificació superior ( Els 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. . el review_rating_weight=5 Cèl·lula 22 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. (vegeu més avall), representats com a esdeveniments: behavioral data El El El un usuari interessat en productes casual i d'oci (user_2) un usuari interessat en productes elegants per sortir i ocasions formals de treball (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 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ó o Primer, anem a veure l'efecte (en comparació amb la base) de pesar els espais que estan influïts per aquests (dades de comportament) esdeveniments. Només una mica pesat # 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). 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"]] També podem, per descomptat, utilitzar pesos per personalitzar les nostres recomanacions basades en el comportament d'un usuari en particular (dades d'esdeveniments) i Per exemple, el preu (veure ) i Prioritzar altres atributs del producte Cèl·lula 31 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! . el Intenta implementar la biblioteca superenllaçada utilitzant el nostre bloc de notes Try It Yourself – Get the Code & Demo! Proveu-ho vosaltres mateixos - Get the Code & Demo! El El El Grab the Code: Consulteu la implementació completa en el nostre repo de GitHub aquí.Fork-lo, ajusteu-lo i feu-lo vostre! 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. Aquí Aquí . el Els motors de recomanació estan configurant la forma en què descobrim contingut, ja siguin pantalons populars, música o altres productes, —i ara tens les eines per construir la teva pròpia. vector search is the future