Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
W rozwiązaniach wyszukiwania ciągi, które mają złożone wzorce lub znaki specjalne, mogą być trudne do pracy, ponieważ domyślny analizator usuwa lub błędnie interpretuje istotne części wzorca. Powoduje to słabe środowisko wyszukiwania, w którym użytkownicy nie mogą znaleźć oczekiwanych informacji. Numery telefonów to klasyczny przykład ciągów, które są trudne do przeanalizowania. Są one w różnych formatach i zawierają znaki specjalne ignorowane przez analizator domyślny.
Ten samouczek dotyczacy numerow telefonow pokazuje, jak rozwiązać problemy ze wzorzystymi danymi przy użyciu analizatora niestandardowego. Takie podejście może być używane w przypadku numerów telefonów lub dostosowane do pól o takich samych cechach (wzorzec ze znakami specjalnymi), takich jak adresy URL, wiadomości e-mail, kody pocztowe i daty.
W tym samouczku używasz klienta REST i REST API Azure AI Search do:
- Omówienie problemu
- Opracuj wstępny analizator niestandardowy do obsługi numerów telefonów
- Testowanie analizatora niestandardowego
- Iterowanie projektu analizatora niestandardowego w celu dalszego ulepszania wyników
Wymagania wstępne
Konto Azure z aktywną subskrypcją. Utwórz konto bezpłatnie.
Azure AI Search. Utwórz usługę lub znajdź istniejącą usługę w bieżącej subskrypcji. Na potrzeby tego samouczka możesz skorzystać z bezpłatnej usługi.
Pobieranie plików
Kod źródłowy tego samouczka znajduje się w pliku custom-analyzer.rest w repozytorium GitHub Azure-Samples/azure-search-rest-samples .
Kopiowanie klucza administratora i adresu URL
Wywołania REST w tym samouczku wymagają punktu końcowego usługi wyszukiwania oraz klucza interfejsu API administratora. Te wartości można uzyskać w witrynie Azure Portal.
Zaloguj się do witryny Azure Portal, przejdź do strony Przegląd i skopiuj adres URL. Przykładowy punkt końcowy może wyglądać podobnie jak
https://mydemo.search.windows.net
.W obszarze Klucze ustawień>skopiuj klucz administratora. Klucze administracyjne służą do dodawania, modyfikowania i usuwania obiektów. Istnieją dwa zamienne klucze administratora. Skopiuj jedną z nich.
Prawidłowy klucz interfejsu API ustanawia relację zaufania dla poszczególnych żądań między aplikacją wysyłającą żądanie a usługą wyszukiwania, która go obsługuje.
Tworzenie indeksu początkowego
Otwórz nowy plik tekstowy w programie Visual Studio Code.
Przypisz zmiennym punkt końcowy wyszukiwania oraz klucz interfejsu API zebrany w poprzedniej sekcji.
@baseUrl = PUT-YOUR-SEARCH-SERVICE-URL-HERE @apiKey = PUT-YOUR-ADMIN-API-KEY-HERE
Zapisz plik z
.rest
rozszerzeniem pliku.Wklej poniższy przykład, aby utworzyć mały indeks o nazwie
phone-numbers-index
z dwoma polami:id
iphone_number
. Nie zdefiniowano jeszcze analizatora, więcstandard.lucene
analizator jest używany domyślnie.### Create a new index POST {{baseUrl}}/indexes?api-version=2024-07-01 HTTP/1.1 Content-Type: application/json api-key: {{apiKey}} { "name": "phone-numbers-index", "fields": [ { "name": "id", "type": "Edm.String", "key": true, "searchable": true, "filterable": false, "facetable": false, "sortable": true }, { "name": "phone_number", "type": "Edm.String", "sortable": false, "searchable": true, "filterable": false, "facetable": false } ] }
Wybierz pozycję Wyślij wniosek. Powinieneś mieć odpowiedź
HTTP/1.1 201 Created
, a treść odpowiedzi powinna zawierać schemat indeksu w formacie JSON.Załaduj dane do indeksu przy użyciu dokumentów zawierających różne formaty numerów telefonów. Są to dane testowe.
### Load documents POST {{baseUrl}}/indexes/phone-numbers-index/docs/index?api-version=2024-07-01 HTTP/1.1 Content-Type: application/json api-key: {{apiKey}} { "value": [ { "@search.action": "upload", "id": "1", "phone_number": "425-555-0100" }, { "@search.action": "upload", "id": "2", "phone_number": "(321) 555-0199" }, { "@search.action": "upload", "id": "3", "phone_number": "+1 425-555-0100" }, { "@search.action": "upload", "id": "4", "phone_number": "+1 (321) 555-0199" }, { "@search.action": "upload", "id": "5", "phone_number": "4255550100" }, { "@search.action": "upload", "id": "6", "phone_number": "13215550199" }, { "@search.action": "upload", "id": "7", "phone_number": "425 555 0100" }, { "@search.action": "upload", "id": "8", "phone_number": "321.555.0199" } ] }
Spróbuj wykonać zapytania podobne do tego, co użytkownik może wpisać. Na przykład użytkownik może wyszukiwać
(425) 555-0100
w dowolnej liczbie formatów i nadal oczekiwać wyników. Rozpocznij od wyszukania(425) 555-0100
.### Search for a phone number GET {{baseUrl}}/indexes/phone-numbers-index/docs/search?api-version=2024-07-01&search=(425) 555-0100 HTTP/1.1 Content-Type: application/json api-key: {{apiKey}}
Zapytanie zwraca trzy z czterech oczekiwanych wyników, ale także zwraca dwa nieoczekiwane wyniki.
{ "value": [ { "@search.score": 0.05634898, "phone_number": "+1 425-555-0100" }, { "@search.score": 0.05634898, "phone_number": "425 555 0100" }, { "@search.score": 0.05634898, "phone_number": "425-555-0100" }, { "@search.score": 0.020766128, "phone_number": "(321) 555-0199" }, { "@search.score": 0.020766128, "phone_number": "+1 (321) 555-0199" } ] }
Spróbuj ponownie bez żadnego formatowania:
4255550100
.### Search for a phone number GET {{baseUrl}}/indexes/phone-numbers-index/docs/search?api-version=2024-07-01&search=4255550100 HTTP/1.1 Content-Type: application/json api-key: {{apiKey}}
To zapytanie działa jeszcze gorzej, zwracając tylko jedno z czterech pasujących wyników.
{ "value": [ { "@search.score": 0.6015292, "phone_number": "4255550100" } ] }
Jeśli znajdziesz te wyniki mylące, nie jesteś sam. W następnej sekcji wyjaśniono, dlaczego otrzymujesz te wyniki.
Zapoznaj się ze sposobem działania analizatorów
Aby zrozumieć te wyniki wyszukiwania, musisz zrozumieć, co robi analizator. Z tego miejsca możesz przetestować domyślny analizator przy użyciu interfejsu API analizowania, zapewniając podstawę do projektowania analizatora, który lepiej spełnia Twoje potrzeby.
Analizator jest składnikiem wyszukiwarki pełnotekstowej odpowiedzialnej za przetwarzanie tekstu w ciągach zapytania i indeksowanych dokumentach. Różne analizatory manipulują tekstem na różne sposoby w zależności od scenariusza. W tym scenariuszu musimy utworzyć analizator dostosowany do numerów telefonów.
Analizatory składają się z trzech składników:
- Filtry znaków, które usuwają lub zamieniają poszczególne znaki z tekstu wejściowego.
- Tokenizator, który dzieli tekst wejściowy na tokeny, które stają się kluczami w indeksie wyszukiwania.
- Filtry tokenów , które manipulują tokenami utworzonymi przez tokenizatora.
Na poniższym diagramie pokazano, jak te trzy składniki współpracują ze sobą w celu tokenizowania zdania.
Te tokeny są następnie przechowywane w odwróconym indeksie, co umożliwia szybkie wyszukiwanie pełnotekstowe. Odwrócony indeks umożliwia wyszukiwanie pełnotekstowe przez mapowanie wszystkich unikatowych terminów wyodrębnionych podczas analizy leksykalnej do dokumentów, w których występują. Przykład można zobaczyć na poniższym diagramie:
Wyszukiwanie sprowadza się do wyszukiwania terminów przechowywanych w odwróconym indeksie. Gdy użytkownik wystawia zapytanie:
- Zapytanie jest analizowane, a terminy zapytania są analizowane.
- Odwrócony indeks jest skanowany pod kątem dokumentów z zgodnymi terminami.
- Algorytm oceniania klasyfikuje pobrane dokumenty.
Jeśli terminy zapytania nie są zgodne z terminami w odwróconym indeksie, wyniki nie są zwracane. Aby dowiedzieć się więcej o sposobie działania zapytań, zobacz Wyszukiwanie pełnotekstowe w usłudze Azure AI Search.
Uwaga
Zapytania dotyczące części terminów są ważnym wyjątkiem od tej reguły. W przeciwieństwie do zwykłych zapytań terminowych, te zapytania (zapytanie o prefiks, zapytanie z symbolem wieloznacznym i zapytanie rozszerzone o wyrażenia regularne) pomijają proces analizy leksykalnej. Częściowe terminy są pisane z małej litery tylko przed dopasowaniem do terminów w indeksie. Jeśli analizator nie jest skonfigurowany do obsługi tego typu zapytań, często otrzymujesz nieoczekiwane wyniki, ponieważ pasujące terminy nie istnieją w indeksie.
Testowanie analizatorów przy użyciu interfejsu API analizy
Usługa Azure AI Search udostępnia interfejs API analizowania, który umożliwia testowanie analizatorów w celu zrozumienia sposobu przetwarzania tekstu.
Wywołaj interfejs API analizowania przy użyciu następującego żądania:
POST {{baseUrl}}/indexes/phone-numbers-index/analyze?api-version=2024-07-01 HTTP/1.1
Content-Type: application/json
api-key: {{apiKey}}
{
"text": "(425) 555-0100",
"analyzer": "standard.lucene"
}
Interfejs API zwraca tokeny wyodrębnione z tekstu przy użyciu określonego analizatora. Standardowy analizator Lucene dzieli numer telefonu na trzy oddzielne tokeny.
{
"tokens": [
{
"token": "425",
"startOffset": 1,
"endOffset": 4,
"position": 0
},
{
"token": "555",
"startOffset": 6,
"endOffset": 9,
"position": 1
},
{
"token": "0100",
"startOffset": 10,
"endOffset": 14,
"position": 2
}
]
}
Z drugiej strony numer 4255550100
telefonu sformatowany bez żadnej interpunkcji jest tokenizowany na jeden token.
{
"text": "4255550100",
"analyzer": "standard.lucene"
}
Reakcja:
{
"tokens": [
{
"token": "4255550100",
"startOffset": 0,
"endOffset": 10,
"position": 0
}
]
}
Należy pamiętać, że zarówno terminy zapytania, jak i indeksowane dokumenty są analizowane. Po powrocie do wyników wyszukiwania z poprzedniego kroku możesz zacząć widzieć, dlaczego te wyniki są zwracane.
W pierwszym zapytaniu zwracane są nieoczekiwane numery telefonów, ponieważ jeden z ich tokenów jest 555
zgodny z jednym z wyszukiwanych terminów. W drugim zapytaniu zwracana jest tylko jedna liczba, ponieważ jest to jedyny rekord, który ma token pasujący 4255550100
.
Tworzenie analizatora niestandardowego
Gdy już zrozumiesz wyniki, które widzisz, stwórz analizator niestandardowy, aby ulepszyć logikę tokenizacji.
Celem jest zapewnienie intuicyjnego wyszukiwania numerów telefonów niezależnie od formatu zapytania lub indeksowanego ciągu. Aby osiągnąć ten wynik, określ filtr znaków, tokenizator i filtr tokenu.
Filtry znaków
Filtry znaków przetwarzają tekst, zanim zostanie on przekazany do tokenizatora. Typowe zastosowania filtrów znaków to filtrowanie elementów HTML i zastępowanie znaków specjalnych.
W przypadku numerów telefonów chcesz usunąć białe znaki i znaki specjalne, ponieważ nie wszystkie formaty numerów telefonów zawierają te same znaki specjalne i spacje.
"charFilters": [
{
"@odata.type": "#Microsoft.Azure.Search.MappingCharFilter",
"name": "phone_char_mapping",
"mappings": [
"-=>",
"(=>",
")=>",
"+=>",
".=>",
"\\u0020=>"
]
}
]
Filtr usuwa -
(
)
+
.
oraz spacje z danych wejściowych.
Dane wejściowe | Dane wyjściowe |
---|---|
(321) 555-0199 |
3215550199 |
321.555.0199 |
3215550199 |
Tokenizatory
Tokenizatory dzielą tekst na tokeny i odrzucają niektóre znaki, takie jak interpunkcja, po drodze. W wielu przypadkach celem tokenizacji jest podzielenie zdania na poszczególne wyrazy.
W tym scenariuszu użyj tokenizera słowa kluczowego , keyword_v2
aby przechwycić numer telefonu jako pojedynczy termin. Nie jest to jedyny sposób rozwiązania tego problemu, jak wyjaśniono w sekcji Alternatywne podejścia .
Tokenizery słów kluczowych zawsze wyświetlają dokładnie ten sam tekst, który otrzymują jako pojedynczy termin.
Dane wejściowe | Dane wyjściowe |
---|---|
The dog swims. |
[The dog swims.] |
3215550199 |
[3215550199] |
Filtry tokenów
Filtry tokenów modyfikują lub filtrują tokeny wygenerowane przez tokenizatora. Jednym z typowych zastosowań filtru tokenu jest zamiana wszystkich znaków na małe litery przy użyciu filtru tokenu zmieniającego na małe litery. Innym typowym zastosowaniem jest filtrowanie stopwords, takich jak the
, and
lub is
.
Chociaż w tym scenariuszu nie trzeba używać jednego z tych filtrów, użyj filtru tokenu nGram, aby umożliwić częściowe wyszukiwanie numerów telefonów.
"tokenFilters": [
{
"@odata.type": "#Microsoft.Azure.Search.NGramTokenFilterV2",
"name": "custom_ngram_filter",
"minGram": 3,
"maxGram": 20
}
]
NGramTokenFilterV2
Filtr tokenów nGram_v2 dzieli tokeny na n-gramy o określonym rozmiarze na podstawie parametrów minGram
i maxGram
.
Dla analizatora telefonu minGram
jest ustawione na 3
ponieważ jest to najkrótszy podciąg, który użytkownicy oczekują wyszukiwać.
maxGram
jest ustawiona w taki sposób, 20
aby wszystkie numery telefonów, nawet z dodatkami, mogły się zmieścić w jednym n-gramie.
Niepożądany efekt uboczny n-gramów polega na tym, że zwracane są niektóre fałszywe wyniki dodatnie. Ten problem można rozwiązać w późniejszym kroku, tworząc oddzielny analizator wyszukiwania, który nie zawiera filtru tokenu n-gram.
Dane wejściowe | Dane wyjściowe |
---|---|
[12345] |
[123, 1234, 12345, 234, 2345, 345] |
[3215550199] |
[321, 3215, 32155, 321555, 3215550, 32155501, 321555019, 3215550199, 215, 2155, 21555, 215550, ... ] |
Analizator
Dzięki filtrom znaków, tokenizatorowi i filtrom tokenów możesz zdefiniować analizator.
"analyzers": [
{
"@odata.type": "#Microsoft.Azure.Search.CustomAnalyzer",
"name": "phone_analyzer",
"tokenizer": "keyword_v2",
"tokenFilters": [
"custom_ngram_filter"
],
"charFilters": [
"phone_char_mapping"
]
}
]
W interfejsie API analizowania, biorąc pod uwagę następujące dane wejściowe, dane wyjściowe z analizatora niestandardowego są następujące:
Dane wejściowe | Dane wyjściowe |
---|---|
12345 |
[123, 1234, 12345, 234, 2345, 345] |
(321) 555-0199 |
[321, 3215, 32155, 321555, 3215550, 32155501, 321555019, 3215550199, 215, 2155, 21555, 215550, ... ] |
Wszystkie tokeny w kolumnie wyjściowej istnieją w indeksie. Jeśli zapytanie zawiera dowolne z tych terminów, zwracany jest numer telefonu.
Ponowne kompilowanie przy użyciu nowego analizatora
Usuń bieżący indeks.
### Delete the index DELETE {{baseUrl}}/indexes/phone-numbers-index?api-version=2024-07-01 HTTP/1.1 api-key: {{apiKey}}
Utwórz ponownie indeks przy użyciu nowego analizatora. Ten schemat indeksu dodaje definicję analizatora niestandardowego i przypisanie analizatora niestandardowego w polu numer telefonu.
### Create a new index POST {{baseUrl}}/indexes?api-version=2024-07-01 HTTP/1.1 Content-Type: application/json api-key: {{apiKey}} { "name": "phone-numbers-index-2", "fields": [ { "name": "id", "type": "Edm.String", "key": true, "searchable": true, "filterable": false, "facetable": false, "sortable": true }, { "name": "phone_number", "type": "Edm.String", "sortable": false, "searchable": true, "filterable": false, "facetable": false, "analyzer": "phone_analyzer" } ], "analyzers": [ { "@odata.type": "#Microsoft.Azure.Search.CustomAnalyzer", "name": "phone_analyzer", "tokenizer": "keyword_v2", "tokenFilters": [ "custom_ngram_filter" ], "charFilters": [ "phone_char_mapping" ] } ], "charFilters": [ { "@odata.type": "#Microsoft.Azure.Search.MappingCharFilter", "name": "phone_char_mapping", "mappings": [ "-=>", "(=>", ")=>", "+=>", ".=>", "\\u0020=>" ] } ], "tokenFilters": [ { "@odata.type": "#Microsoft.Azure.Search.NGramTokenFilterV2", "name": "custom_ngram_filter", "minGram": 3, "maxGram": 20 } ] }
Testowanie analizatora niestandardowego
Po ponownym utworzeniu indeksu przetestuj analizator przy użyciu następującego żądania:
POST {{baseUrl}}/indexes/tutorial-first-analyzer/analyze?api-version=2024-07-01 HTTP/1.1
Content-Type: application/json
api-key: {{apiKey}}
{
"text": "+1 (321) 555-0199",
"analyzer": "phone_analyzer"
}
Powinna zostać wyświetlona kolekcja tokenów wynikających z numeru telefonu.
{
"tokens": [
{
"token": "132",
"startOffset": 1,
"endOffset": 17,
"position": 0
},
{
"token": "1321",
"startOffset": 1,
"endOffset": 17,
"position": 0
},
{
"token": "13215",
"startOffset": 1,
"endOffset": 17,
"position": 0
},
...
...
...
]
}
Poprawianie analizatora niestandardowego w celu obsługi wyników fałszywie dodatnich
Po użyciu niestandardowego analizatora do wykonywania przykładowych zapytań w odniesieniu do indeksu, powinno być widoczne, że poprawiła się trafność wyszukiwania, a teraz zwracane są wszystkie odpowiadające numery telefonów. Jednak filtr tokenu n-gram powoduje również zwrócenie niektórych wyników fałszywie dodatnich. Jest to typowy efekt uboczny filtru tokenu n-gram.
Aby zapobiec wynikom fałszywie dodatnim, utwórz oddzielny analizator do wykonywania zapytań. Ten analizator jest identyczny z poprzednim, z tą różnicą, że pomija element custom_ngram_filter
.
{
"@odata.type": "#Microsoft.Azure.Search.CustomAnalyzer",
"name": "phone_analyzer_search",
"tokenizer": "custom_tokenizer_phone",
"tokenFilters": [],
"charFilters": [
"phone_char_mapping"
]
}
W definicji indeksu określ zarówno indexAnalyzer
i searchAnalyzer
.
{
"name": "phone_number",
"type": "Edm.String",
"sortable": false,
"searchable": true,
"filterable": false,
"facetable": false,
"indexAnalyzer": "phone_analyzer",
"searchAnalyzer": "phone_analyzer_search"
}
Dzięki tej zmianie wszystko jest gotowe. Oto następne kroki do wykonania:
Usuń indeks.
Utwórz ponownie indeks po dodaniu nowego analizatora niestandardowego (
phone_analyzer-search
) i przypisz ten analizator do pola właściwościphone-number
searchAnalyzer
.Załaduj ponownie dane.
Ponownie przetestuj zapytania, aby sprawdzić, czy wyszukiwanie działa zgodnie z oczekiwaniami. Jeśli używasz przykładowego pliku, ten krok tworzy trzeci indeks o nazwie
phone-number-index-3
.
Podejścia alternatywne
Analizator opisany w poprzedniej sekcji został zaprojektowany w celu zmaksymalizowania elastyczności wyszukiwania. Jednak odbywa się kosztem przechowywania wielu potencjalnie nieważnych terminów w indeksie.
W poniższym przykładzie przedstawiono alternatywny analizator, który jest bardziej wydajny w tokenizacji, ale ma wady.
Biorąc pod uwagę dane wejściowe 14255550100
, analizator nie może logicznie fragmentować numeru telefonu. Na przykład nie może oddzielić kodu kraju , 1
od kodu 425
obszaru , . Ta rozbieżność prowadzi do braku zwracanego numeru telefonu, jeśli użytkownik nie uwzględni kodu kraju w wyszukiwaniu.
"analyzers": [
{
"@odata.type": "#Microsoft.Azure.Search.CustomAnalyzer",
"name": "phone_analyzer_shingles",
"tokenizer": "custom_tokenizer_phone",
"tokenFilters": [
"custom_shingle_filter"
]
}
],
"tokenizers": [
{
"@odata.type": "#Microsoft.Azure.Search.StandardTokenizerV2",
"name": "custom_tokenizer_phone",
"maxTokenLength": 4
}
],
"tokenFilters": [
{
"@odata.type": "#Microsoft.Azure.Search.ShingleTokenFilter",
"name": "custom_shingle_filter",
"minShingleSize": 2,
"maxShingleSize": 6,
"tokenSeparator": ""
}
]
W poniższym przykładzie numer telefonu jest podzielony na części, których użytkownik zwykle szuka.
Dane wejściowe | Dane wyjściowe |
---|---|
(321) 555-0199 |
[321, 555, 0199, 321555, 5550199, 3215550199] |
W zależności od wymagań może to być bardziej wydajne podejście do problemu.
Wnioski
W tym poradniku przedstawiono, jak zbudować i przetestować niestandardowy analizator. Utworzyłeś indeks, zindeksowałeś dane, a następnie wykonałeś zapytanie względem indeksu, aby zobaczyć, jakie wyniki wyszukiwania zostały otrzymane. W tym miejscu użyłeś interfejsu API analizy, aby zobaczyć proces analizy leksykalnej w praktyce.
Chociaż analizator zdefiniowany w tym samouczku oferuje łatwe rozwiązanie do wyszukiwania numerów telefonów, ten sam proces może służyć do tworzenia analizatora niestandardowego dla dowolnego scenariusza, który ma podobne cechy.
Czyszczenie zasobów
Gdy pracujesz we własnej subskrypcji, dobrym pomysłem jest usunięcie zasobów, które nie są już potrzebne po zakończeniu projektu. Pozostawione bez nadzoru uruchomione zasoby mogą generować koszty. Zasoby możesz usuwać pojedynczo lub jako grupę zasobów, usuwając cały zestaw zasobów.
Zasoby można znaleźć w witrynie Azure Portal i zarządzać nimi, korzystając z linku Wszystkie zasoby lub Grupy zasobów w okienku nawigacji po lewej stronie.
Następne kroki
Teraz, gdy wiesz już, jak utworzyć analizator niestandardowy, przyjrzyj się wszystkim różnym filtrom, tokenizatorom i analizatorom dostępnym do tworzenia zaawansowanego środowiska wyszukiwania: