Een door AI aangestuurd leger van duisternis Het is spelletjesavond, je vrienden zitten rond de speltafel en wachten om te zien welk Dungeons & Dragons (D&D) personage ze worden en welke quest ze gaan doen. Vanavond ben jij Dungeon Master (verhalenverteller en gids), bedenker van spannende ontmoetingen om je spelers uit te dagen en te boeien. Je vertrouwde D&D Monster Manual bevat wezens. Het vinden van het perfecte monster voor elke situatie uit de talloze opties kan overweldigend zijn. De ideale vijand moet passen bij de setting, moeilijkheidsgraad en het verhaal van het moment. duizenden Wat als we een tool konden creëren die direct het monster vindt dat het meest geschikt is voor elk scenario? Een , en ervoor zorgt dat elke ontmoeting zo meeslepend en spannend mogelijk is? tool die meerdere factoren tegelijk overweegt Laten we zelf op zoek gaan: bouw het ultieme monsterzoeksysteem met behulp van de kracht van multi-attribuut vectorzoekopdrachten! Wezens creëren met vectorzoekfunctie, waarom zou je dat doen? vertegenwoordigt een revolutie in het ophalen van informatie. Vector embedding - door rekening te houden met context en semantische betekenis - stelt vector zoeken in staat om relevantere en nauwkeurigere resultaten te retourneren, niet alleen gestructureerde maar ook ongestructureerde data en meerdere talen te verwerken en te schalen. Maar om hoogwaardige antwoorden te genereren in real-world toepassingen, moeten we vaak verschillende gewichten toekennen aan specifieke kenmerken van onze data-objecten. Vector zoeken Er zijn twee gangbare benaderingen voor multi-attribute vector search. Beide beginnen met het afzonderlijk insluiten van elk attribuut van een data-object. Het belangrijkste verschil tussen deze twee benaderingen is hoe onze insluitingen worden en . opgeslagen doorzocht de aanpak: sla elke kenmerkvector op in aparte vectoropslagplaatsen (één per kenmerk), voer een aparte zoekopdracht uit voor elk kenmerk, combineer de zoekresultaten en voer indien nodig een nabewerking uit (bijv. gewicht). naïeve de -benadering - alle attribuutvectoren samenvoegen en opslaan in dezelfde vectoropslag (met behulp van de ingebouwde functionaliteit van Superlinked), waardoor we , met bijbehorende efficiëntiewinsten. van Superlinked laten ons elk attribuut wegen op het moment van de query om relevantere resultaten naar voren te brengen, zonder nabewerking. Superlinked slechts één keer hoeven te zoeken spaces ook Hieronder gebruiken we deze twee benaderingen om een multi-attribute vector search tool te implementeren - een Dungeons and Dragons monster finder! Onze eenvoudige implementaties, met name de tweede, illustreren hoe u krachtigere en flexibelere zoeksystemen kunt maken, systemen die complexe, veelzijdige zoekopdrachten met gemak aankunnen, ongeacht uw use case. Als u nieuw bent in vector similarity search, maak u dan geen zorgen! Wij hebben u gedekt - bekijk onze . bouwstenen artikelen Oké, laten we op monsterjacht gaan! Gegevensset Eerst genereren we een kleine synthetische dataset van monsters door een Large Language Model (LLM) op te starten: Generate two JSON lists: 'monsters' and 'queries'. 1. 'monsters' list: Create 20 unique monsters with the following properties: - name: A distinctive name - look: Brief description of appearance (2-3 sentences) - habitat: Where the monster lives (2-3 sentences) - behavior: How the monster acts (2-3 sentences) Ensure some monsters share similar features while remaining distinct. 2. 'queries' list: Create 5 queries to search for monsters: - Each query should be in the format: {look: "...", habitat: "...", behavior: "..."} - Use simple, brief descriptions (1-3 words per field) - Make queries somewhat general to match multiple monsters Output format: { "monsters": [ {"name": "...", "look": "...", "habitat": "...", "behavior": "..."}, ... ], "queries": [ {"look": "...", "habitat": "...", "behavior": "..."}, ... ] } Laten we eens kijken naar een voorbeeld van de dataset die onze LLM heeft gegenereerd. Let op: LLM-generatie is niet-deterministisch, dus uw resultaten kunnen afwijken. Hier zijn onze eerste vijf monsters: # naam Look leefgebied gedrag 0 Lichtgevend Motachtig wezen met gloeiende vleugels en antenne Dichte bossen en jungles met bioluminescente flora Zendt rustgevende lichtpatronen uit om te communiceren en prooien aan te trekken 1 Aqua-Wraith Doorschijnend humanoïde figuur gemaakt van stromend water Rivieren, meren en kustgebieden Verandert van vorm om zich aan te passen aan waterlichamen en controleert stromingen 2 Steenhart Golem Massieve humanoïde bestaande uit in elkaar grijpende rotsformaties Rotsachtige bergen en oude ruïnes Houdt eeuwenlang een winterslaap en ontwaakt om zijn territorium te beschermen 3 Fluisterende schaduw Schaduwrijk, amorf wezen met gloeiende ogen Donkere bossen en verlaten gebouwen Voedt zich met angst en fluistert verontrustende waarheden 4 Zephyr-danser Sierlijk vogelwezen met iriserende veren Hoge bergtoppen en door de wind geteisterde vlakten Creëert betoverende luchtshows om partners aan te trekken ...en onze gegenereerde query's: Kijk Leefgebied Gedrag 0 Gloeiend Donkere plekken Lichtmanipulatie 1 Elementair Extreme omgevingen Milieubeheersing 2 Vormverandering Gevarieerde landschappen Illusie creatie 3 Kristallijn Mineraalrijke gebieden Energieabsorptie 4 Etherisch Atmosferisch Invloed van de geest Bekijk de originele dataset en queryvoorbeelden. hier Ophalen Hieronder stellen we de parameters in die we in beide benaderingen gebruiken: Naïef en Superlinked. Wij genereren onze vector-embeddings met: sentence-transformers/all-mpnet-base-v2. Om het eenvoudig te houden, beperken we onze uitvoer tot de top 3 matches. (Voor de volledige code, inclusief de benodigde imports en helperfuncties, zie het .) notebook LIMIT = 3 MODEL_NAME = "sentence-transformers/all-mpnet-base-v2" Laten we nu beginnen met onze multi-attribute monster search! Eerst proberen we de aanpak. naïeve Naïeve benadering In onze naïeve aanpak embedden we attributen onafhankelijk en slaan ze op in verschillende indices. Tijdens de query voeren we meerdere kNN-zoekopdrachten uit op alle indices en combineren we vervolgens al onze gedeeltelijke resultaten tot één. We beginnen met het definiëren van een klasse NaiveRetriever om een op overeenkomsten gebaseerde zoekopdracht uit te voeren op onze dataset, met behulp van onze door gegenereerde insluitingen. all-mpnet-base-v2 class NaiveRetriever: def __init__(self, data: pd.DataFrame): self.model = SentenceTransformer(MODEL_NAME) self.data = data.copy() self.ids = self.data.index.to_list() self.knns = {} for key in self.data: embeddings = self.model.encode(self.data[key].values) knn = NearestNeighbors(metric="cosine").fit(embeddings) self.knns[key] = knn def search_key(self, key: str, value: str, limit: int = LIMIT) -> pd.DataFrame: embedding = self.model.encode(value) knn = self.knns[key] distances, indices = knn.kneighbors( [embedding], n_neighbors=limit, return_distance=True ) ids = [self.ids[i] for i in indices[0]] similarities = (1 - distances).flatten() # by definition: # cosine distance = 1 - cosine similarity result = pd.DataFrame( {"id": ids, f"score_{key}": similarities, key: self.data[key][ids]} ) result.set_index("id", inplace=True) return result def search(self, query: dict, limit: int = LIMIT) -> pd.DataFrame: results = [] for key, value in query.items(): if key not in self.knns: continue result_key = self.search_key(key, value, limit=limit) result_key.drop(columns=[key], inplace=True) results.append(result_key) merged_results = pd.concat(results, axis=1) merged_results["score"] = merged_results.mean(axis=1, skipna=False) merged_results.sort_values("score", ascending=False, inplace=True) return merged_results naive_retriever = NaiveRetriever(df.set_index("name")) Laten we de eerste query uit de hierboven gegenereerde lijst gebruiken en met behulp van onze naar monsters zoeken: naive_retriever query = { 'look': 'glowing', 'habitat': 'dark places', 'behavior': 'light manipulation' } naive_retriever.search(query) Ons naive_retriever retourneert de volgende zoekresultaten voor elk kenmerk: id score_kijken Look Fluisterende schaduw 0,503578 Schaduwrijk, amorf wezen met gloeiende ogen Zandstorm Djinn 0,407344 Wervelende zandwerveling met gloeiende symbolen Lichtgevend 0,378619 Motachtig wezen met gloeiende vleugels en antenne Geweldig! Onze geretourneerde monsterresultaten zijn relevant - ze hebben allemaal een "gloeiende" eigenschap. Laten we eens kijken wat de naïeve aanpak oplevert als we naar de andere twee kenmerken zoeken. id score_habitat leefgebied Fluisterende schaduw 0,609567 Donkere bossen en verlaten gebouwen Schimmelnetwerk 0,438856 Ondergrondse grotten en vochtige bossen Doornwijn Elementair 0,423421 Overwoekerde ruïnes en dichte jungles id score_gedrag gedrag Levende graffiti 0,385741 Verandert van vorm om op te gaan in de omgeving en absorbeert pigmenten Kristalvleugel Drake 0,385211 Verzamelt kostbare edelstenen en kan licht breken in krachtige stralen Lichtgevend 0,345566 Zendt rustgevende lichtpatronen uit om te communiceren en prooien aan te trekken Alle opgehaalde monsters bezitten de gewenste attributen. Op het eerste gezicht lijken de naïeve zoekresultaten veelbelovend. Maar we moeten monsters vinden die bezitten. Laten we onze resultaten samenvoegen om te zien hoe goed onze monsters dit doel bereiken: alle drie de attributen tegelijkertijd id score_kijken score_habitat score_gedrag Fluisterende schaduw 0,503578 0,609567 Zandstorm Djinn 0,407344 Lichtgevend 0,378619 0,345566 Schimmelnetwerk 0,438856 Doornwijn Elementair 0,423421 Levende graffiti 0,385741 Kristalvleugel Drake 0,385211 En hier worden de grenzen van de naïeve benadering duidelijk. Laten we evalueren: Relevantie per kenmerk: : Er zijn drie monsters teruggevonden (Whispering Shade, Sandstorm Djinn en Luminoth). look : Slechts één monster uit de was relevant (Whispering Shade). habitat look : Slechts één monster uit de was relevant (Luminoth), maar het is anders dan het monster dat relevant is voor . behavior look habitat Algemene relevantie: Er werd geen enkel monster gevonden dat alle drie de kenmerken tegelijk bezat. De resultaten zijn gefragmenteerd: verschillende monsters zijn relevant voor verschillende kenmerken. Kortom, de naïeve zoekbenadering slaagt er niet in om monsters te vinden die aan alle criteria tegelijk voldoen. Laten we het proberen met 6 monsters per kenmerk, in plaats van 3. Laten we eens kijken wat deze benadering genereert: Misschien kunnen we dit probleem oplossen door proactief meer monsters voor elk kenmerk op te halen? id score_kijken score_habitat score_gedrag Fluisterende schaduw 0,503578 0,609567 Zandstorm Djinn 0,407344 0,365061 Lichtgevend 0,378619 0,345566 Nevelkwal 0,36627 0,259969 Dreamweaver-octopus 0,315679 Kwantum vuurvliegje 0,288578 Schimmelnetwerk 0,438856 Doornwijn Elementair 0,423421 Mistfantoom 0,366816 0,236649 Steenhart Golem 0,342287 Levende graffiti 0,385741 Kristalvleugel Drake 0,385211 Aqua-Wraith 0,283581 We hebben inmiddels 13 monsters opgehaald (meer dan de helft van onze kleine dataset!), en hebben we hetzelfde probleem: geen enkel monster is voor alle drie de kenmerken opgehaald. nog steeds Het verhogen van het aantal teruggevonden monsters (meer dan 6) ons probleem kunnen oplossen, maar het creëert ook extra problemen: zou Bij productie zorgt het ophalen van meer resultaten (meerdere kNN-zoekopdrachten) ervoor dat de zoektijd merkbaar langer wordt. Voor elk nieuw kenmerk dat we introduceren, daalt onze kans om een "compleet" monster te vinden - met alle kenmerken in onze query - exponentieel. Om dit te voorkomen, moeten we veel meer dichtstbijzijnde buren (monsters) ophalen, waardoor het totale aantal opgehaalde monsters exponentieel groeit. We hebben nog steeds geen garantie dat we monsters zullen vinden die over alle gewenste eigenschappen beschikken. Als het ons lukt om monsters te vinden die aan alle criteria voldoen, moeten we extra overheadkosten maken om de resultaten te vergelijken. Kortom, de naïeve aanpak is te onzeker en inefficiënt voor een levensvatbare zoekopdracht met meerdere kenmerken, vooral in productie. Superlinked-benadering Laten we onze tweede aanpak eens toepassen om te zien of die beter werkt dan de naïeve aanpak. Eerst definiëren we het schema, de ruimtes, de index en de query: @schema class Monster: id: IdField look: String habitat: String behavior: String monster = Monster() look_space = TextSimilaritySpace(text=monster.look, model=MODEL_NAME) habitat_space = TextSimilaritySpace(text=monster.habitat, model=MODEL_NAME) behavior_space = TextSimilaritySpace(text=monster.behavior, model=MODEL_NAME) monster_index = Index([look_space, habitat_space, behavior_space]) monster_query = ( Query( monster_index, weights={ look_space: Param("look_weight"), habitat_space: Param("habitat_weight"), behavior_space: Param("behavior_weight"), }, ) .find(monster) .similar(look_space.text, Param("look")) .similar(habitat_space.text, Param("habitat")) .similar(behavior_space.text, Param("behavior")) .limit(LIMIT) ) default_weights = { "look_weight": 1.0, "habitat_weight": 1.0, "behavior_weight": 1.0 } Nu starten we de executor en uploaden de gegevens: monster_parser = DataFrameParser(monster, mapping={monster.id: "name"}) source: InMemorySource = InMemorySource(monster, parser=monster_parser) executor = InMemoryExecutor(sources=[source], indices=[monster_index]) app = executor.run() source.put([df]) Laten we dezelfde query uitvoeren als in onze naïeve aanpak-implementatie hierboven: query = { 'look': 'glowing', 'habitat': 'dark places', 'behavior': 'light manipulation' } app.query( monster_query, limit=LIMIT, **query, **default_weights ) id score Look leefgebied gedrag Fluisterende schaduw 0,376738 Schaduwrijk, amorf wezen met gloeiende ogen Donkere bossen en verlaten gebouwen Voedt zich met angst en fluistert verontrustende waarheden Lichtgevend 0,340084 Motachtig wezen met gloeiende vleugels en antenne Dichte bossen en jungles met bioluminescente flora Zendt rustgevende lichtpatronen uit om te communiceren en prooien aan te trekken Levende graffiti 0,330587 Tweedimensionaal, kleurrijk wezen dat op vlakke oppervlakken leeft Stedelijke gebieden, met name muren en billboards Verandert van vorm om op te gaan in de omgeving en absorbeert pigmenten Et voila! Deze keer scoort elk van onze best teruggekeerde monsters hoog in een score die een soort "gemiddelde" vertegenwoordigt van alle drie de kenmerken die we willen dat ons monster heeft. Laten we de score van elk monster in detail uitsplitsen: id Look leefgebied gedrag totaal Fluisterende schaduw 0,167859 0,203189 0,005689 0,376738 Lichtgevend 0,126206 0,098689 0,115189 0,340084 Levende graffiti 0,091063 0,110944 0,12858 0,330587 Onze tweede en derde resultaten, Luminoth en Living Graffiti, bezitten allebei alle drie de gewenste kenmerken. Het beste resultaat, Whispering Shade, is weliswaar minder relevant in termen van lichtmanipulatie - zoals blijkt uit de (0,006), maar heeft "gloeiende" kenmerken en een donkere omgeving waardoor zijn (0,168) en (0,203) erg hoog scoren, wat hem de hoogste totaalscore (0,377) oplevert, wat hem het meest relevante monster in het algemeen maakt. Wat een verbetering! behavior look habitat Kunnen we onze resultaten repliceren? Laten we een andere query proberen en erachter komen. query = { 'look': 'shapeshifting', 'habitat': 'varied landscapes', 'behavior': 'illusion creation' } id score Look leefgebied gedrag Mistfantoom 0,489574 Etherische, mistachtige humanoïde met veranderende kenmerken Moerassen, heidevelden en mistige kustlijnen Lokt reizigers op een dwaalspoor met illusies en gefluister Zephyr-danser 0,342075 Sierlijk vogelwezen met iriserende veren Hoge bergtoppen en door de wind geteisterde vlakten Creëert betoverende luchtshows om partners aan te trekken Fluisterende schaduw 0,337434 Schaduwrijk, amorf wezen met gloeiende ogen Donkere bossen en verlaten gebouwen Voedt zich met angst en fluistert verontrustende waarheden Geweldig! Onze resultaten zijn opnieuw uitstekend. Wat als we monsters willen vinden die lijken op een specifiek monster uit onze dataset? Laten we het proberen met een monster dat we nog niet hebben gezien - Harmonic Coral. We attributen voor dit monster extraheren en handmatig queryparameters maken. Maar Superlinked heeft een -methode die we kunnen gebruiken op het query-object. Omdat de id van elk monster zijn naam is, kunnen we onze aanvraag zo eenvoudig uitdrukken als: kunnen with_vector app.query( monster_query.with_vector(monster, "Harmonic Coral"), **default_weights, limit=LIMIT ) id score Look leefgebied gedrag Harmonisch koraal 1 Vertakte, muziekinstrumentachtige structuur met trillende ranken Ondiepe zeeën en getijdenpoelen Creëert complexe melodieën om emoties te communiceren en te beïnvloeden Dreamweaver-octopus 0,402288 Koppotigen met tentakels die glinsteren als poollicht Diepe oceaantroggen en onderwatergrotten Beïnvloedt de dromen van nabijgelegen wezens Aqua-Wraith 0,330869 Doorschijnend humanoïde figuur gemaakt van stromend water Rivieren, meren en kustgebieden Verandert van vorm om zich aan te passen aan waterlichamen en controleert stromingen Het bovenste resultaat is het meest relevante, Harmonic Coral zelf, zoals verwacht. De andere twee monsters die onze zoekopdracht ophaalt zijn Dreamweaver Octopus en Aqua Wraith. Beide delen belangrijke thematische ( ) elementen met Harmonic Coral: attribuut Waterhabitats ( ) habitat Vermogen om hun omgeving te beïnvloeden of te manipuleren ( ) behavior Dynamische of vloeiende visuele kenmerken ( ) look Attribuutweging Stel nu dat we meer belang willen hechten aan het kenmerk . Met het Superlinked-framework kunnen we gewichten eenvoudig aanpassen tijdens de query. Voor een eenvoudige vergelijking zoeken we naar monsters die lijken op Harmonic Coral, maar waarbij onze gewichten zijn aangepast om te bevoordelen. look look weights = { "look_weight": 1.0, "habitat_weight": 0, "behavior_weight": 0 } app.query( monster_query.with_vector(monster, "Harmonic Coral"), limit=LIMIT, **weights ) id score Look leefgebied gedrag Harmonisch koraal 0,57735 Vertakte, muziekinstrumentachtige structuur met trillende ranken Ondiepe zeeën en getijdenpoelen Creëert complexe melodieën om emoties te communiceren en te beïnvloeden Doornwijn Elementair 0,252593 Plantachtig wezen met een lichaam van gedraaide wijnranken en doornen Overwoekerde ruïnes en dichte jungles Groeit snel en beheerst het omringende plantenleven Plasma slang 0,243241 Slangachtig wezen gemaakt van knetterende energie Elektrische stormen en elektriciteitscentrales Voedt zich met elektrische stromen en kan technologie kortsluiten Onze resultaten lijken allemaal (passend genoeg) op elkaar: "Vertakt met trillende ranken", "Plant-achtig wezen met een lichaam van kronkelige wijnranken en doornen", "Slang-achtig". Laten we nu nog een zoekopdracht uitvoeren, waarbij we het uiterlijk negeren en in plaats daarvan op zoek gaan naar monsters die qua en op elkaar lijken: habitat behavior weights = { "look_weight": 0, "habitat_weight": 1.0, "behavior_weight": 1.0 } id score Look leefgebied gedrag Harmonisch koraal 0,816497 Vertakte, muziekinstrumentachtige structuur met trillende ranken Ondiepe zeeën en getijdenpoelen Creëert complexe melodieën om emoties te communiceren en te beïnvloeden Dreamweaver-octopus 0,357656 Koppotigen met tentakels die glinsteren als poollicht Diepe oceaantroggen en onderwatergrotten Beïnvloedt de dromen van nabijgelegen wezens Mistfantoom 0,288106 Etherische, mistachtige humanoïde met veranderende kenmerken Moerassen, heidevelden en mistige kustlijnen Lokt reizigers op een dwaalspoor met illusies en gefluister Opnieuw levert de Superlinked-aanpak geweldige resultaten op. Alle drie de monsters leven in waterige omgevingen en bezitten gedachtenbeheersende vermogens. Laten we tot slot nog een zoekopdracht uitvoeren, waarbij we alle drie de kenmerken anders wegen. Zo vinden we monsters die er, vergeleken met Harmonic Coral, enigszins hetzelfde uitzien, in heel andere habitats leven en zich heel vergelijkbaar gedragen: weights = { "look_weight": 0.5, "habitat_weight": -1.0, "behavior_weight": 1.0 } id score Look leefgebied gedrag Harmonisch koraal 0,19245 Vertakte, muziekinstrumentachtige structuur met trillende ranken Ondiepe zeeën en getijdenpoelen Creëert complexe melodieën om emoties te communiceren en te beïnvloeden Lichtgevend 0,149196 Motachtig wezen met gloeiende vleugels en antenne Dichte bossen en jungles met bioluminescente flora Zendt rustgevende lichtpatronen uit om te communiceren en prooien aan te trekken Zephyr-danser 0,136456 Sierlijk vogelwezen met iriserende veren Hoge bergtoppen en door de wind geteisterde vlakten Creëert betoverende luchtshows om partners aan te trekken Weer geweldige resultaten! Onze twee andere teruggevonden monsters — Luminoth en Zephyr Dancer — vertonen gedrag dat lijkt op Harmonic Coral en leven in andere habitats dan die van Harmonic Coral. Ze zien er ook heel anders uit dan Harmonic Coral. (Hoewel de ranken van Harmonic Coral en de antenne van Luminoth enigszins vergelijkbare kenmerken hebben, hebben we de slechts met 0,5 verlaagd, en daar houdt de gelijkenis tussen de twee monsters op.) look_weight Laten we eens kijken hoe de totale scores van deze monsters verdeeld zijn in termen van individuele eigenschappen: id Look leefgebied gedrag totaal Harmonisch koraal 0,19245 -0,3849 0,3849 0,19245 Lichtgevend 0,052457 -0,068144 0,164884 0,149196 Zephyr-danser 0,050741 -0,079734 0,165449 0,136456 Door negatief te wegen (-1.0), "duwen" we opzettelijk monsters met vergelijkbare habitats weg en in plaats daarvan komen er monsters aan de oppervlakte waarvan de omgevingen verschillen van die van Harmonic Coral - zoals te zien is in de negatieve van Luminoth en Zephyr Dancer. De van Luminoth en Zephyr Dancer zijn relatief hoog, wat hun gedragsgelijkenis met Harmonic Coral aangeeft. Hun zijn positief maar lager, wat maar geen extreme visuele gelijkenis met Harmonic Coral weerspiegelt. habitat_weight habitat behavior look enige Kortom, onze strategie om terug te brengen naar -1,0 en naar 0,5, maar op 1,0 te houden, blijkt effectief bij het aan de oppervlakte brengen van monsters die belangrijke gedragskenmerken delen met Harmonic Coral, maar die een heel andere omgeving hebben en er in ieder geval iets anders uitzien. habitat_weight look_weight behavior_weight Conclusie Multi-attribute vector search is een significante vooruitgang in information retrieval, en biedt meer nauwkeurigheid, contextueel begrip en flexibiliteit dan basic semantic similarity search. Toch is onze naïeve aanpak (hierboven) - het apart opslaan en doorzoeken van attribuutvectoren combineren van resultaten - beperkt in vermogen, subtiliteit en efficiëntie wanneer we objecten met meerdere gelijktijdige attributen moeten ophalen. (Bovendien nemen meerdere kNN-zoekopdrachten meer tijd in beslag dan een enkele zoekopdracht met geconcateneerde vectoren.) en het vervolgens Om dit soort scenario's te verwerken, is het beter om al uw attribuutvectoren in dezelfde vectoropslag op te slaan en uit te voeren, waarbij u uw attributen op het moment van de query weegt. De Superlinked-benadering is nauwkeuriger, efficiënter en schaalbaarder dan de naïeve benadering voor elke toepassing die snelle, betrouwbare, genuanceerde, multi-attribuut vectoropvraging vereist - of uw use case nu gaat over het aanpakken van echte data-uitdagingen in uw e-commerce- of aanbevelingssysteem... of iets heel anders, zoals het bestrijden van monsters. één zoekopdracht Medewerkers Andrey Pikunov, auteur Mór Kapronczay, redacteur Oorspronkelijk gepubliceerd. hier