Dela via


Lägga till ett filter i en vektorfråga i Azure AI Search

Du kan definiera en vektorfrågebegäran som innehåller ett filteruttryck för att lägga till inkluderings- eller exkluderingsvillkor i dina frågor. I den här artikeln lär du dig att:

Den här artikeln använder REST som illustration. Kodexempel på andra språk finns i GitHub-lagringsplatsen azure-search-vector-samples för lösningar från slutpunkt till slutpunkt som innehåller vektorfrågor.

Du kan också använda Sökutforskaren i Azure Portal för att fråga vektorinnehåll. Om du använder JSON-vyn kan du lägga till filter och ange filterläget.

Så här fungerar filtrering i en vektorfråga

Filter gäller för filterable icke-bevekbara fält, antingen ett strängfält eller numeriskt, för att inkludera eller exkludera sökdokument baserat på filtervillkor. Även om ett vektorfält inte kan filtreras kan filter tillämpas på andra fält i samma index, inklusive eller exkludera dokument som också innehåller vektorfält.

Filter tillämpas före eller efter frågekörning baserat på parametern vectorFilterMode .

Definiera ett filter

Filter avgör omfånget för en vektorfråga. Filter anges på och itereras över icke-sträng och numeriska fält som tillskrivs som filterable i indexet, men syftet med ett filter avgör vad vektorfrågan kör över: hela sökbart utrymme eller innehållet i ett sökresultat.

Om du inte har källfält med text eller numeriska värden kontrollerar du om det finns dokumentmetadata, till exempel LastModified- eller CreatedBy-egenskaper, som kan vara användbara i ett metadatafilter.

2024-07-01 är den stabila versionen för det här API:et. Den har:

  • vectorFilterModeför förfilter (standard) eller postfilterfiltreringslägen.
  • filter innehåller kriterierna.

I följande exempel är vektorn en representation av den här frågesträngen: "vilka Azure-tjänster stöder fulltextsökning". Frågan riktar sig mot fältet contentVector . Den faktiska vektorn har 1536 inbäddningar, så den trimmas i det här exemplet för läsbarhet.

Filtervillkoren tillämpas på ett filterbart textfält (category i det här exemplet) innan sökmotorn kör vektorfrågan.

POST https://{{search-service-name}}.search.windows.net/indexes/{{index-name}}/docs/search?api-version=2024-07-01
Content-Type: application/json
api-key: {{admin-api-key}}
{
    "count": true,
    "select": "title, content, category",
    "filter": "category eq 'Databases'",
    "vectorFilterMode": "preFilter",
    "vectorQueries": [
        {
            "kind": "vector",
            "vector": [
                -0.009154141,
                0.018708462,
                . . . 
                -0.02178128,
                -0.00086512347
            ],
            "exhaustive": true,
            "fields": "contentVector",
            "k": 5
        }
    ]
}

Ange vectorFilterMode

Frågeparametern vectorFilterMode avgör om filtret tillämpas före eller efter körning av vektorfrågor.

Använda förfilterläge

Förfiltrering tillämpar filter före frågekörning, vilket minskar sökytan som vektorsökningsalgoritmen söker efter liknande innehåll över.

I en vektorfråga preFilter är standardvärdet.

Diagram över förfilter.

Använda postfilterläge

Efterfiltrering tillämpas filter efter frågekörning, vilket begränsar sökresultaten.

Diagram över efterfilter.

Benchmark-testning av vektorfilterlägen

För att förstå under vilka förhållanden ett filterläge presterar bättre än det andra körde vi en serie tester för att utvärdera frågeresultat över små, medelstora och stora index.

  • Små (100 000 dokument, 2,5 GB index, 1 536 dimensioner)
  • Medel (1 miljon dokument, 25 GB index, 1 536 dimensioner)
  • Stort (1 miljard dokument, 1,9 TB index, 96 dimensioner)

För de små och medelstora arbetsbelastningarna använde vi en Standard 2-tjänst (S2) med en partition och en replik. För den stora arbetsbelastningen använde vi en Standard 3-tjänst (S3) med 12 partitioner och en replik.

Index hade en identisk konstruktion: ett nyckelfält, ett vektorfält, ett textfält och ett numeriskt filterbart fält. Följande index definieras med syntaxen 2023-11-03.

def get_index_schema(self, index_name, dimensions):
    return {
        "name": index_name,
        "fields": [
            {"name": "id", "type": "Edm.String", "key": True, "searchable": True},
            {"name": "content_vector", "type": "Collection(Edm.Single)", "dimensions": dimensions,
              "searchable": True, "retrievable": True, "filterable": False, "facetable": False, "sortable": False,
              "vectorSearchProfile": "defaulthnsw"},
            {"name": "text", "type": "Edm.String", "searchable": True, "filterable": False, "retrievable": True,
              "sortable": False, "facetable": False},
            {"name": "score", "type": "Edm.Double", "searchable": False, "filterable": True,
              "retrievable": True, "sortable": True, "facetable": True}
        ],
      "vectorSearch": {
        "algorithms": [
            {
              "name": "defaulthnsw",
              "kind": "hnsw",
              "hnswParameters": { "metric": "euclidean" }
            }
          ],
          "profiles": [
            {
              "name": "defaulthnsw",
              "algorithm": "defaulthnsw"
            }
        ]
      }
    }

I frågor använde vi ett identiskt filter för både förfilter- och postfilteråtgärder. Vi använde ett enkelt filter för att säkerställa att variationer i prestanda berodde på filtreringsläge och inte på att filtrera komplexitet.

Utfall mättes i frågor per sekund (QPS).

Lärdomar

  • Förfiltrering är nästan alltid långsammare än efterfiltrering, förutom för små index där prestandan är ungefär lika med.

  • För större datamängder är förfiltrering en storleksordning som är långsammare.

  • Så varför är förfilter standardvärdet om det nästan alltid är långsammare? Förfiltrering garanterar att k resultaten returneras om de finns i indexet, där biasen gynnar återkallande och precision framför hastighet.

  • Postfiltering är till för kunder som:

    • värdehastighet över markering (postfiltering kan returnera färre än k resultat)
    • använda filter som inte är alltför selektiva
    • har index av tillräcklig storlek så att förfilterprestanda är oacceptabla

Details

  • Givet en datauppsättning med 100 000 vektorer med 1 536 dimensioner:

    • Vid filtrering av mer än 30 % av datamängden var förfiltrering och postfiltrering jämförbara.
    • Vid filtrering av mindre än 0,1 % av datamängden var förfiltrering ungefär 50 % långsammare än efterfiltrering.
  • Givet en datamängd med 1 miljon vektorer vid 1536 dimensioner:

    • Vid filtrering av mer än 30 % av datamängden var förfiltreringen cirka 30 % långsammare.
    • Vid filtrering av mindre än 2 % av datamängden var förfiltrering ungefär sju gånger långsammare.
  • Givet en datamängd med 1 miljard vektorer vid 96 dimensioner:

    • Vid filtrering av mer än 5 % av datamängden var förfiltreringen cirka 50 % långsammare.
    • Vid filtrering av mindre än 10 % av datamängden var förfiltrering ungefär sju gånger långsammare.

Följande diagram visar förfilter relativ QPS, beräknad som förfilter QPS dividerat med postfilter QPS.

Diagram som visar QPS-prestanda för små, medelstora och stora index för relativ QPS.

Den lodräta axeln är QPS för förfiltrering över QPS för postfiltering. Ett värde på 0,0 innebär till exempel att förfiltrering är 100 % långsammare, 0,5 på den lodräta axeln innebär att förfiltrering är 50 % långsammare, 1,0 innebär att förfiltrering och efterfiltrering är likvärdiga.

Den vågräta axeln representerar filtreringshastigheten eller procentandelen kandidatdokument efter att filtret har tillämpats. Innebär till exempel 1.00% att en procent av sök corpus valdes av filtervillkoren.