que que Que pasaría se a túa tenda en liña soubese o que un cliente quería antes de que o fixesen? Que pasaría se a túa tenda en liña soubese o que un cliente quería antes de que o fixesen? suxiren elementos "populares" ou "similares" baseados en datos limitados e desactualizados. cando os usuarios son novos (o problema de inicio frío), e raramente se adaptan rápido o suficiente cando as preferencias dun usuario cambian en tempo real. Most recommendation engines are like helpful but slightly clueless assistants: struggle E se o sistema puidese como un merchandiser - combinando datos estáticos de produtos e comportamento do usuario en tempo real á superficie No momento axeitado? En realidade pensamos Os elementos correctos En realidade pensamos Utilización , un que supera estas deficiencias tradicionais ao converter os seus datos en perfís de usuario actuables e en evolución utilizando infraestruturas vector-nativas. This guide walks you through building a modern recommendation engine Superlinked (Queres ir directamente ao código? comproba o código de código aberto en GitHub aquí. listo para probar sistemas de recomendación para o seu propio caso de uso? aquí aquí aquí aquí Tamén podes seguir o tutorial no navegador co noso Unha colab. TD e DR: A maioría das recomendacións de comercio electrónico son demasiado estáticas (baseadas en regras) ou demasiado negras (modelos ML opacos). Superlinked ofrece un camiño medio: recomendacións flexibles en tempo real que se poden adaptar aos usuarios de inicio frío combinando metadatos con comportamento en directo - todo sen retraer modelos ML. Conseguir a personalización a pesar dos retos da incorporación vectorial de RecSys Aínda que as incorporacións vectoriales poden mellorar enormemente os sistemas de recomendación, a súa implementación efectiva require abordar varios retos, incluíndo: que que que que Calidade e relevancia: O proceso de xeración de embudo, a arquitectura e os datos deben considerarse coidadosamente. Datos escasos e ruidosos: As incorporacións son menos eficaces cando teñen entradas incompletas ou ruidosas. Escalabilidade: son necesarios métodos eficientes para grandes conxuntos de datos; doutro xeito, a latencia será un problema. Superlinked permite abordar estes retos combinando todos os datos dispoñibles sobre usuarios e produtos en vectores multimodales ricos. No noso exemplo de comercio electrónico RecSys a continuación, facémolo usando os seguintes elementos da biblioteca Superlinked: que que que que que espazos de número min_max: para comprender as opinións dos clientes e a información de prezos texto-similaridade Espazo: para a comprensión semántica da información do produto Esquema de eventos e efectos para modificar vectores pesos de tempo de consulta - para definir como desexa que os datos sexan tratados cando execute a consulta, permitíndolle optimizar e escalar sen reencher o conxunto de datos enteiro (latencia) Ao incorporar os nosos inicialmente escasos datos específicos do usuario (preferencia inicial do produto do usuario), podemos xestionar o problema de inicio frío. -Personalizar recomendacións mediante a incorporación destes datos de eventos, creando un loop de retroceso que lle permite actualizar vectores con preferencias de usuario en tempo real.Ademais, os pesos de tempo de consulta de Superlinked permítenlle axustar os seus resultados de búsqueda, biasándoos para coincidir con preferencias de usuario específicas. Hipérbole Let's get started! Construír un motor de recomendación de comercio electrónico con Superlinked Ao comezo do desenvolvemento, temos o seguinte : de product data que que que que que que Número de revisores Avaliacións de produtos Descrición textual Nome do produto (xeralmente contén o nome da marca) Categoría Tamén temos o seguinte : de data about users and products que que que cada usuario elixe un dos tres produtos ofrecidos ao rexistrarse (é dicir, datos de preferencias de produtos) comportamento do usuario (despois do rexistro) proporciona datos adicionais de evento - preferencias para características textuais dos produtos (descrición, nome, categoría) Ademais, a economía clásica dinos que, en media, todos os usuarios ceteris paribus prefiren produtos que: que que que que Custa menos Teñen moitas revisións Teñen ratings máis altos Podemos configurar os nosos espazos para ter en conta estes datos, de xeito que o noso RecSys funcione en escenarios de inicio frío - recomendando elementos para usuarios que coñecemos moi pouco. Unha vez que o noso RecSys estea en funcionamento, tamén teremos datos de comportamento: os usuarios farán clic en certos produtos, mercar determinados produtos, etc. Podemos capturar e usar estes datos de eventos para crear fluxos de feedback, actualizar os nosos vectores para reflectir as preferencias do usuario e mellorar a calidade da recomendación. Introdución ao Superlink Primeiro, necesitamos instalar a biblioteca Superlinked e importar as clases. %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) Tamén definimos os nosos conxuntos de datos e creamos unha constante para almacenar os 10 principais elementos - ver no seu caderno. Célula 3 Agora que se identificaron as localizacións instaladas da biblioteca, as clases importadas e os conxuntos de datos, podemos botar unha ollada ao noso conxunto de datos para informar de como configuramos os nosos espazos. Inicialmente, temos datos do rexistro do usuario - é dicir, cal dos tres produtos usuaria_1 e usuaria_2 elixiu. # 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 Tamén podemos establecer un exame detallado dos datos de distribución dos nosos produtos - ver Isto dálle unha idea de cantos produtos están en diferentes puntos de prezo, teñen diferentes contas de revisións e teñen diferentes clasificacións (incluíndo onde a maioría dos produtos atópanse nestes rangos). Célula 5 Os prezos dos produtos están xeralmente por baixo do punto de prezo de $1.000. Pode que queiramos poñer o rango de espazo a 25-1000 para facelo representativo, sen distorsionar os valores exteriores. As contas de revisión dos produtos distribúense uniformemente e as clasificacións de revisión distribúense relativamente uniformemente, polo que non se require ningún tratamento adicional. . . Células 7-9 Construír o índice para a busca de vectores A biblioteca de Superlinked contén un conxunto de bloques de construción de núcleo que usamos para construír o índice e xestionar a recuperación. . . aquí Imos poñer os bloques de construción desta biblioteca para usar no noso EComm RecSys. Para informar ao sistema sobre os seus datos. 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ón, usa Espazos para dicir como quere tratar cada parte dos datos ao incorporar. En Definicións de Espazos, describimos como incorporar entradas para que reflictan as relacións semánticas nos nosos datos. Cada Espazos está optimizado para incorporar os datos para devolver a maior calidade posible de resultados de recuperación. # 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]) Agora que tes os teus datos definidos en Espazos, estás listo para xogar cos teus datos e optimizar os resultados. A nosa solución de inicio frío. O que podemos facer sen eventos Solución ao problema de inicio frío de RecSys Aquí definimos unha consulta de usuario que busca só co vector de preferencia do usuario.Temos control de configuración sobre a importancia (pesos) de cada tipo de entrada (Espazo). 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() Os resultados desta consulta reflicten o feito de que user_1 elixiu unha bolsa cando se rexistrou por primeira vez no noso sitio de ecomm. Tamén é posible recomendar produtos para o usuario_1 que son atractivo - é dicir, baseado no seu prezo sendo baixo, e ter unha morea de boas opinións.Os nosos resultados agora reflectirán tanto a elección de produto de user_1 no momento do rexistro a popularidade xeral dos produtos. (Tamén podemos xogar con estes pesos para distorsionar os resultados na dirección dun espazo ou outro.) En xeral e 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() A busca dun novo usuario introduce texto de consulta como unha entrada para os nosos resultados de recomendación - ver . . Célula 20 No noso exemplo, user_1 buscou "camisetas de roupa feminina". Podemos optimizar os nosos resultados dando (por exemplo ), para recomendar máis produtos de "xatos de roupa feminina". 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() O noso peso de categoría adicional produce máis resultados de roupa feminina. Tamén podemos bias as nosas recomendacións para produtos de primeira clasificación ( Os resultados reflicten agora a preferencia inicial do usuario_1 por bolsas e elementos que son xeralmente populares, mentres que os produtos con clasificacións baixas son eliminados por completo. . . review_rating_weight=5 Páxina 22 Usar datos de eventos para crear experiencias personalizadas Os nosos usuarios interactúan coa nosa plataforma - user_1 máis, user_2 menos. (ver abaixo), representados como eventos: behavioral data que que que un usuario interesado en produtos casual e de lecer (user_2) un usuario interesado en produtos elegantes para saír e ocasións de traballo formais (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 Imos pesar accións específicas para rexistrar o nivel de interese do usuario nun determinado produto, e axustar a configuración para ter en conta os eventos ao realizar a recuperación. 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() Agora creamos un novo índice para ter en conta os eventos do usuario e, a continuación, personalizamos as recomendacións a cada usuario en consecuencia. # 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")) ) Podemos observar o impacto da incorporación de eventos nos nosos RecSys ponderando a personalización ou Primeiro, imos ver o efecto (en comparación coa base) de pesar os espazos que son influenciados por estes eventos (datos de comportamento). só un pouco pesado # 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"]] Con moi pouco peso colocado nos espazos afectados por eventos, observamos un cambio pero principalmente só na segunda metade do noso top 10, en comparación cos resultados anteriores ("id_base", á dereita). Pero se pesamos máis os espazos afectados polo evento, superamos elementos completamente novos na nosa lista de recomendacións. # 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"]] Tamén podemos, por suposto, usar pesos para personalizar as nosas recomendacións baseadas no comportamento dun usuario en particular (datos de eventos) e - Por exemplo, o prezo (ver ) da Prioriza simultaneamente outros atributos do produto Páxina 31 Conclusión A implementación de eComm RecSys da biblioteca Superlinked (abaixo) móstralle como realizar o poder das incorporacións de vectores incorporando o significado semántico de consultas de usuarios e datos de comportamento. Usando os nosos espazos de número min_max e semellanza de texto, esquema de eventos e efectos e pesos de tempo de consulta, pode abordar os retos de inicio frío, calidade e relevancia e escalabilidade de RecSys e proporcionar recomendacións altamente precisas e personalizadas para o usuario na produción. Agora é a túa vez! . . Probe implementar a biblioteca Superlinked vostede mesmo usando o noso notebook Try It Yourself – Get the Code & Demo! Probe-o vostede mesmo - Obter o código & Demo! que que que Grab the Code: Consulte a implementación completa no noso repo de GitHub aquí.Fork, axusta-lo e fai-lo seu! Ver en acción: Queres ver isto funcionando nunha configuración do mundo real? Reserva unha demostración rápida e explora como Superlinked pode superchargar as túas recomendacións. aquí aquí . . Os motores de recomendación están a modelar a forma en que descubrimos o contido, xa sexan pantalóns populares, música ou outros produtos, - e agora tes as ferramentas para construír a túa propia. vector search is the future