paint-brush
Een revolutie in monsterjachten: AI-verbeterde D&D-ontmoetingendoor@superlinked
Nieuwe geschiedenis

Een revolutie in monsterjachten: AI-verbeterde D&D-ontmoetingen

door Superlinked17m2025/01/31
Read on Terminal Reader

Te lang; Lezen

Het artikel onderzoekt multi-attribute vector search, waarbij twee belangrijke benaderingen worden vergeleken. De naïeve methode houdt in dat de vector van elk attribuut apart wordt opgeslagen, dat er individuele zoekopdrachten worden uitgevoerd en dat de resultaten vervolgens worden samengevoegd via post-processing. De Superlinked-benadering combineert daarentegen alle attribuutvectoren in één vectoropslag, waardoor een uniforme zoekopdracht mogelijk is waarbij attributen dynamisch kunnen worden gewogen op het moment van de query, waardoor post-processing niet meer nodig is. Een Dungeons & Dragons-voorbeeld illustreert de voordelen van deze methode en laat zien hoe het efficiënt monsters vindt die voldoen aan specifieke criteria, zoals uiterlijk, habitat en gedrag. Door attribuutgewichten aan te passen, levert deze benadering nauwkeurigere en flexibelere zoekresultaten op dan traditionele methoden.
featured image - Een revolutie in monsterjachten: AI-verbeterde D&D-ontmoetingen
Superlinked HackerNoon profile picture
0-item
1-item

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 duizenden 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.


Wat als we een tool konden creëren die direct het monster vindt dat het meest geschikt is voor elk scenario? Een tool die meerdere factoren tegelijk overweegt , en ervoor zorgt dat elke ontmoeting zo meeslepend en spannend mogelijk is?


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?

Vector zoeken 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.

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 opgeslagen en doorzocht .

  1. de naïeve 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).
  2. de Superlinked -benadering - alle attribuutvectoren samenvoegen en opslaan in dezelfde vectoropslag (met behulp van de ingebouwde functionaliteit van Superlinked), waardoor we slechts één keer hoeven te zoeken , met bijbehorende efficiëntiewinsten. spaces van Superlinked laten ons ook elk attribuut wegen op het moment van de query om relevantere resultaten naar voren te brengen, zonder nabewerking.

Twee benaderingen voor multi-attribuut vectoronderzoek

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 hier de originele dataset en queryvoorbeelden.

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 naïeve aanpak.

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 all-mpnet-base-v2 gegenereerde insluitingen.

 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 naive_retriever naar monsters zoeken:

 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 alle drie de attributen tegelijkertijd bezitten. Laten we onze resultaten samenvoegen om te zien hoe goed onze monsters dit doel bereiken:

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:

  1. Relevantie per kenmerk:
    • look : Er zijn drie monsters teruggevonden (Whispering Shade, Sandstorm Djinn en Luminoth).
    • habitat : Slechts één monster uit de look was relevant (Whispering Shade).
    • behavior : Slechts één monster uit de look was relevant (Luminoth), maar het is anders dan het monster dat relevant is voor habitat .
  2. 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. Misschien kunnen we dit probleem oplossen door proactief meer monsters voor elk kenmerk op te halen? Laten we het proberen met 6 monsters per kenmerk, in plaats van 3. Laten we eens kijken wat deze benadering genereert:

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 nog steeds hebben we hetzelfde probleem: geen enkel monster is voor alle drie de kenmerken opgehaald.


Het verhogen van het aantal teruggevonden monsters (meer dan 6) zou ons probleem kunnen oplossen, maar het creëert ook extra problemen:

  1. Bij productie zorgt het ophalen van meer resultaten (meerdere kNN-zoekopdrachten) ervoor dat de zoektijd merkbaar langer wordt.
  2. 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.
  3. We hebben nog steeds geen garantie dat we monsters zullen vinden die over alle gewenste eigenschappen beschikken.
  4. 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 behavior (0,006), maar heeft "gloeiende" kenmerken en een donkere omgeving waardoor zijn look (0,168) en habitat (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!

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 kunnen attributen voor dit monster extraheren en handmatig queryparameters maken. Maar Superlinked heeft een with_vector -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:

 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 ( attribuut ) elementen met Harmonic Coral:

  1. Waterhabitats ( habitat )
  2. Vermogen om hun omgeving te beïnvloeden of te manipuleren ( behavior )
  3. Dynamische of vloeiende visuele kenmerken ( look )

Attribuutweging

Stel nu dat we meer belang willen hechten aan het kenmerk look . 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 look te bevoordelen.

 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 habitat en behavior op elkaar lijken:

 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 look_weight slechts met 0,5 verlaagd, en daar houdt de gelijkenis tussen de twee monsters op.)

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 habitat_weight 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 habitat van Luminoth en Zephyr Dancer. De behavior van Luminoth en Zephyr Dancer zijn relatief hoog, wat hun gedragsgelijkenis met Harmonic Coral aangeeft. Hun look zijn positief maar lager, wat enige maar geen extreme visuele gelijkenis met Harmonic Coral weerspiegelt.

Kortom, onze strategie om habitat_weight terug te brengen naar -1,0 en look_weight naar 0,5, maar behavior_weight 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.

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 en het vervolgens 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.)

Om dit soort scenario's te verwerken, is het beter om al uw attribuutvectoren in dezelfde vectoropslag op te slaan en één zoekopdracht 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.

Medewerkers


Oorspronkelijk hier gepubliceerd.