Öğretici: Telefon numaraları için özel çözümleyici oluşturma
Arama çözümlerinde, karmaşık desenlere veya özel karakterlere sahip dizeler, varsayılan çözümleyici bir desenin anlamlı bölümlerini çıkardığından veya yanlış yorumladığından, kullanıcılar bekledikleri bilgileri bulamadıklarında kötü bir arama deneyimine neden olduğundan çalışmak zor olabilir. Telefon numaraları, analiz etmek zor olan dizelerin klasik bir örneğidir. Bunlar çeşitli biçimlerde gelir ve varsayılan çözümleyicinin yoksaydığını özel karakterler içerir.
Konusu telefon numaraları olan bu öğretici, desenli veri sorunlarına yakından bakar ve özel bir çözümleyici kullanarak bu sorunu çözmenizi gösterir. Burada özetlenen yaklaşım, telefon numaraları için olduğu gibi kullanılabilir veya URL'ler, e-postalar, posta kodları ve tarihler gibi aynı özelliklere (desenli, özel karakterlerle) sahip alanlara uyarlanabilir.
Bu öğreticide, aşağıdakileri yapmak için bir REST istemcisi ve Azure AI Arama REST API'lerini kullanacaksınız:
- Sorunu anlama
- Telefon numaralarını işlemek için ilk özel çözümleyici geliştirme
- Özel çözümleyiciyi test etme
- Sonuçları daha da geliştirmek için özel çözümleyici tasarımını yineleyin
Önkoşullar
Bu öğretici için aşağıdaki hizmetler ve araçlar gereklidir.
REST istemcisi ile Visual Studio Code.
Azure AI Arama. Geçerli aboneliğinizin altında mevcut bir Azure AI Search kaynağı oluşturun veya bulun. Bu hızlı başlangıç için ücretsiz bir hizmet kullanabilirsiniz.
Dosyaları indirme
Bu öğreticinin kaynak kodu, Azure-Samples/azure-search-rest-samples GitHub deposundaki custom-analyzer.rest dosyasıdır.
Anahtar ve URL kopyalama
Bu öğreticideki REST çağrıları için bir arama hizmeti uç noktası ve bir yönetici API anahtarı gerekir. Bu değerleri Azure portalından alabilirsiniz.
Azure portalında oturum açın, Genel Bakış sayfasına gidin ve URL'yi kopyalayın. Örnek uç nokta
https://mydemo.search.windows.net
şeklinde görünebilir.Ayarlar>Anahtarları'nın altında bir yönetici anahtarı kopyalayın. Yönetici anahtarları nesneleri eklemek, değiştirmek ve silmek için kullanılır. Değiştirilebilir iki yönetici anahtarı vardır. İkisini de kopyalayın.
Geçerli bir API anahtarı, isteği gönderen uygulama ile bunu işleyen arama hizmeti arasında istek temelinde güven oluşturur.
İlk dizin oluşturma
Visual Studio Code'da yeni bir metin dosyası açın.
Değişkenleri arama uç noktasına ve önceki adımda topladığınız API anahtarına ayarlayın.
@baseUrl = PUT-YOUR-SEARCH-SERVICE-URL-HERE @apiKey = PUT-YOUR-ADMIN-API-KEY-HERE
Dosyayı bir
.rest
dosya uzantısıyla kaydedin.adlı iki alan içeren küçük bir dizin
phone-numbers-index
oluşturmak için aşağıdaki örneği yapıştırın:id
vephone_number
. Henüz bir çözümleyici tanımlamadık, bu nedenlestandard.lucene
çözümleyici varsayılan olarak kullanılır.### 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 } ] }
İstek gönder’i seçin. Bir
HTTP/1.1 201 Created
yanıtınız olmalıdır ve yanıt gövdesi dizin şemasının JSON gösterimini içermelidir.Çeşitli telefon numarası biçimleri içeren belgeleri kullanarak dizine veri yükleyin. Bu sizin test verilerinizdir.
### 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" } ] }
Şimdi bir kullanıcının yazabileceğine benzer birkaç sorgu deneyelim. Kullanıcı herhangi bir sayıda biçimde arama
(425) 555-0100
yapabilir ve yine de sonuçların döndürülmesini bekleyebilir. öğesini arayarak(425) 555-0100
başlayın:### 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}}
Sorgu dört beklenen sonuçtan üç tane döndürür, ancak aynı zamanda iki beklenmeyen sonuç döndürür:
{ "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" } ] }
Biçimlendirme olmadan yeniden deneyelim:
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}}
Bu sorgu daha da kötü olur ve dört doğru eşleşmeden yalnızca birini döndürür.
{ "value": [ { "@search.score": 0.6015292, "phone_number": "4255550100" } ] }
Bu sonuçları kafa karıştırıcı bulursanız yalnız değilsiniz demektir. Sonraki bölümde bu sonuçları neden aldığımızı inceleyelim.
Çözümleyicilerin nasıl çalıştığını gözden geçirin
Bu arama sonuçlarını anlamak için çözümleyicinin ne yaptığını anlamamız gerekir. Buradan Analiz API'sini kullanarak varsayılan çözümleyiciyi test edebilir ve gereksinimlerimizi daha iyi karşılayan bir çözümleyici tasarlamaya yönelik bir temel sağlayabiliriz.
Çözümleyici, sorgu dizelerinde ve dizine alınan belgelerde metin işlemeden sorumlu tam metin arama altyapısının bir bileşenidir. Farklı çözümleyiciler, senaryoya bağlı olarak metni farklı şekillerde işliyor. Bu senaryo için telefon numaralarına göre uyarlanmış bir çözümleyici oluşturmamız gerekir.
Çözümleyiciler üç bileşenden oluşur:
- Giriş metnindeki karakterleri tek tek kaldıran veya değiştiren karakter filtreleri .
- Giriş metnini belirteçlere bölen ve arama dizininde anahtar haline gelen bir Belirteç Oluşturucu.
- Belirteç oluşturucu tarafından üretilen belirteçleri işleyen belirteç filtreleri .
Aşağıdaki diyagramda, bu üç bileşenin bir tümceyi belirteç haline getirmek için birlikte nasıl çalıştığını görebilirsiniz:
Bu belirteçler daha sonra, hızlı, tam metin aramalarına olanak tanıyan ters bir dizinde depolanır. Ters çevrilmiş dizin, sözcük temelli analiz sırasında ayıklanan tüm benzersiz terimleri bulundukları belgelere eşleyerek tam metin aramasına olanak tanır. Sonraki diyagramda bir örnek görebilirsiniz:
Tüm aramalar, ters dizinde depolanan terimleri aramaya kadar uzanır. Kullanıcı bir sorguyu sorunca:
- Sorgu ayrıştırılır ve sorgu terimleri analiz edilir.
- Ters dizin daha sonra eşleşen terimlere sahip belgeler için taranır.
- Son olarak, alınan belgeler puanlama algoritmasına göre sıralanır.
Sorgu terimleri ters dizininizdeki terimlere uymuyorsa sonuçlar döndürülür. Sorguların nasıl çalıştığı hakkında daha fazla bilgi edinmek için tam metin arama ile ilgili bu makaleye bakın.
Not
Kısmi terim sorguları bu kural için önemli bir istisnadır. Bu sorgular (ön ek sorgusu, joker karakter sorgusu, regex sorgusu) normal terim sorgularından farklı olarak sözcük temelli analiz işlemini atlar. Kısmi terimler, dizindeki terimlerle eşleşmeden önce yalnızca küçük harfle gösterilir. Çözümleyici bu tür sorguları destekleyecek şekilde yapılandırılmamışsa, dizinde eşleşen terimler olmadığından genellikle beklenmeyen sonuçlar alırsınız.
Çözümle API'sini kullanarak çözümleyicileri test etme
Azure AI Search, çözümleyicilerin metinleri nasıl işlediğini anlamak için test etmenizi sağlayan bir Analiz API'si sağlar.
Analiz API'si aşağıdaki istek kullanılarak çağrılır:
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"
}
API, belirttiğiniz çözümleyiciyi kullanarak metinden ayıklanan belirteçleri döndürür. Standart Lucene çözümleyicisi telefon numarasını üç ayrı belirteçe böler:
{
"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
}
]
}
Buna karşılık, noktalama işareti olmadan biçimlendirilmiş telefon numarası 4255550100
tek bir belirteçte belirteci oluşturulur.
{
"text": "4255550100",
"analyzer": "standard.lucene"
}
Yanıt:
{
"tokens": [
{
"token": "4255550100",
"startOffset": 0,
"endOffset": 10,
"position": 0
}
]
}
Hem sorgu terimlerinin hem de dizine alınan belgelerin analizden geçtiğini unutmayın. Önceki adımdaki arama sonuçlarına göz atarak bu sonuçların neden döndürüldiğini görmeye başlayabiliriz.
İlk sorguda beklenmeyen telefon numaraları döndürüldü çünkü belirteçlerinden biri, 555
arama yaptığımız terimlerden biriyle eşleşti. İkinci sorguda, belirteç eşleştirmesi 4255550100
olan tek kayıt olduğundan yalnızca bir sayı döndürüldü.
Özel çözümleyici oluşturma
Gördüğümüz sonuçları anladığımıza göre, belirteç oluşturma mantığını geliştirmek için özel bir çözümleyici oluşturalım.
Amaç, sorgunun veya dizine alınan dizenin biçimi ne olursa olsun telefon numaralarına karşı sezgisel arama sağlamaktır. Bu sonuca ulaşmak için bir karakter filtresi, belirteç oluşturucu ve belirteç filtresi belirteceğiz.
Karakter filtreleri
Karakter filtreleri, belirteç oluşturucuya beslenmeden önce metni işlemek için kullanılır. Karakter filtrelerinin yaygın kullanım alanları arasında HTML öğelerini filtreleme veya özel karakterleri değiştirme sayılabilir.
Tüm telefon numarası biçimleri aynı özel karakterleri ve boşlukları içermediğinden, telefon numaraları için boşluk ve özel karakterleri kaldırmak istiyoruz.
"charFilters": [
{
"@odata.type": "#Microsoft.Azure.Search.MappingCharFilter",
"name": "phone_char_mapping",
"mappings": [
"-=>",
"(=>",
")=>",
"+=>",
".=>",
"\\u0020=>"
]
}
]
Filtre girişten ve boşluklarını -
+
(
)
.
kaldırır.
Girdi | Çıktı |
---|---|
(321) 555-0199 |
3215550199 |
321.555.0199 |
3215550199 |
Belirteç Oluşturucular
Belirteç oluşturucular, metni belirteçlere böler ve yol boyunca noktalama işaretleri gibi bazı karakterleri atar. Çoğu durumda belirteç oluşturmanın amacı, tümceyi tek tek sözcüklere bölmektir.
Bu senaryoda, telefon numarasını tek bir terim olarak yakalamak istediğimizden anahtar keyword_v2
sözcük belirteci kullanacağız. Bu sorunu çözmenin tek yolunun bu olmadığını unutmayın.
Aşağıdaki Alternatif yaklaşımlar bölümüne bakın.
Anahtar sözcük belirteci belirteçleri her zaman tek terim olarak verilen metnin çıkışını verir.
Girdi | Çıktı |
---|---|
The dog swims. |
[The dog swims.] |
3215550199 |
[3215550199] |
Belirteç filtreleri
Belirteç filtreleri belirteç oluşturucu tarafından oluşturulan belirteçleri filtreler veya değiştirir. Belirteç filtresinin yaygın kullanımlarından biri, küçük harfli belirteç filtresi kullanarak tüm karakterleri küçük harfe döndürmektir. Başka bir yaygın kullanım, , and
veya is
gibi the
stopword'leri filtrelemektir.
Bu senaryo için bu filtrelerden herhangi birini kullanmamıza gerek olmasa da, telefon numaralarının kısmi aramalarına izin vermek için bir nGram belirteci filtresi kullanacağız.
"tokenFilters": [
{
"@odata.type": "#Microsoft.Azure.Search.NGramTokenFilterV2",
"name": "custom_ngram_filter",
"minGram": 3,
"maxGram": 20
}
]
NGramTokenFilterV2
nGram_v2 belirteci filtresi, belirteçleri ve maxGram
parametrelerine göre belirli bir boyutun n gramlarına minGram
böler.
Telefon çözümleyicisi için ayarımız minGram
3
, kullanıcıların arama yapmasını beklediğimiz en kısa alt dize olmasıdır.
maxGram
, uzantılarla birlikte tüm telefon numaralarının tek bir n grama sığmasını sağlamak için ayarlanır 20
.
N-gram'ın talihsiz yan etkisi, bazı hatalı pozitif sonuçların döndürüleceğidir. N gram belirteç filtresini içermeyen aramalar için ayrı bir çözümleyici oluşturarak bunu sonraki bir adımda düzelteceğiz.
Girdi | Çıktı |
---|---|
[12345] |
[123, 1234, 12345, 234, 2345, 345] |
[3215550199] |
[321, 3215, 32155, 321555, 3215550, 32155501, 321555019, 3215550199, 215, 2155, 21555, 215550, ... ] |
Çözümleyici
Karakter filtrelerimiz, belirteç oluşturucumuz ve belirteç filtrelerimiz mevcutken çözümleyicimizi tanımlamaya hazırız.
"analyzers": [
{
"@odata.type": "#Microsoft.Azure.Search.CustomAnalyzer",
"name": "phone_analyzer",
"tokenizer": "keyword_v2",
"tokenFilters": [
"custom_ngram_filter"
],
"charFilters": [
"phone_char_mapping"
]
}
]
Analiz API'sinden, aşağıdaki girişler göz önüne alındığında, özel çözümleyiciden alınan çıkışlar aşağıdaki tabloda gösterilmiştir.
Girdi | Çıktı |
---|---|
12345 |
[123, 1234, 12345, 234, 2345, 345] |
(321) 555-0199 |
[321, 3215, 32155, 321555, 3215550, 32155501, 321555019, 3215550199, 215, 2155, 21555, 215550, ... ] |
Çıkış sütunundaki tüm belirteçler dizinde bulunur. Sorgumuz bu terimlerden herhangi birini içeriyorsa, telefon numarası döndürülür.
Yeni çözümleyiciyi kullanarak yeniden oluşturma
Geçerli dizini silin:
### Delete the index DELETE {{baseUrl}}/indexes/phone-numbers-index?api-version=2024-07-01 HTTP/1.1 api-key: {{apiKey}}
Yeni çözümleyiciyi kullanarak dizini yeniden oluşturun. Bu dizin şeması, telefon numarası alanına özel bir çözümleyici tanımı ve özel çözümleyici ataması ekler.
### 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 } ] }
Özel çözümleyiciyi test etme
Dizini yeniden oluşturdıktan sonra aşağıdaki isteği kullanarak çözümleyiciyi test edebilirsiniz:
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"
}
Şimdi telefon numarasından kaynaklanan belirteç koleksiyonunu görmeniz gerekir:
{
"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
},
...
...
...
]
}
Hatalı pozitif sonuçları işlemek için özel çözümleyiciyi gözden geçirme
Özel çözümleyici ile dizinde bazı örnek sorgular yaptıktan sonra, geri çekme işleminin iyileştiğini ve eşleşen tüm telefon numaralarının döndürüldüğünü göreceksiniz. Ancak, n-gram belirteç filtresi de bazı hatalı pozitiflerin döndürülür neden olur. Bu, n gram belirteç filtresinin ortak bir yan etkisidir.
Hatalı pozitif sonuçları önlemek için sorgulama için ayrı bir çözümleyici oluşturacağız. Bu çözümleyici öncekiyle aynıdır, ancak atlarcustom_ngram_filter
.
{
"@odata.type": "#Microsoft.Azure.Search.CustomAnalyzer",
"name": "phone_analyzer_search",
"tokenizer": "custom_tokenizer_phone",
"tokenFilters": [],
"charFilters": [
"phone_char_mapping"
]
}
Dizin tanımında hem hem indexAnalyzer
searchAnalyzer
de belirteceğiz.
{
"name": "phone_number",
"type": "Edm.String",
"sortable": false,
"searchable": true,
"filterable": false,
"facetable": false,
"indexAnalyzer": "phone_analyzer",
"searchAnalyzer": "phone_analyzer_search"
}
Bu değişiklikle hazırsınız. Sonraki adımlarınız şunlardır:
Dizini silin.
Yeni özel çözümleyiciyi (
phone_analyzer-search
) ekledikten ve bu çözümleyiciyi alanınsearchAnalyzer
özelliğinephone-number
atadıktan sonra dizini yeniden oluşturun.Verileri yeniden yükleyin.
Aramanın beklendiği gibi çalıştığını doğrulamak için sorguları yeniden test edin. Örnek dosyayı kullanıyorsanız, bu adım adlı
phone-number-index-3
üçüncü dizini oluşturur.
Alternatif yaklaşımlar
Önceki bölümde açıklanan çözümleyici, arama esnekliğini en üst düzeye çıkarmak için tasarlanmıştır. Ancak, bunu birçok önemli olmayabilecek terimi dizinde depolama maliyetiyle yapar.
Aşağıdaki örnekte belirteç oluşturmada daha verimli olan ancak dezavantajları olan alternatif bir çözümleyici gösterilmektedir.
girdisi 14255550100
verüldüğünde çözümleyici telefon numarasını mantıksal olarak öbekleyemez. Örneğin, ülke kodu olan öğesini alan kodundan 1
425
ayıramaz. Bu tutarsızlık, bir kullanıcı aramasına ülke kodu eklemediyse telefon numarasının döndürülmemesine neden olabilir.
"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": ""
}
]
Aşağıdaki örnekte telefon numarasının normalde kullanıcının arama yapmasını beklediğiniz öbeklere ayrıldığını görebilirsiniz.
Girdi | Çıktı |
---|---|
(321) 555-0199 |
[321, 555, 0199, 321555, 5550199, 3215550199] |
Gereksinimlerinize bağlı olarak, bu sorun için daha verimli bir yaklaşım olabilir.
Paketler
Bu öğreticide özel çözümleyici oluşturma ve test etme işlemi gösterilmiştir. Bir dizin oluşturdunuz, verileri dizine yazdınız ve sonra hangi arama sonuçlarının döndürüldiğini görmek için dizine göre sorguladınız. Buradan, sözcük temelli analiz işleminin nasıl çalıştığını görmek için Çözümle API'sini kullandınız.
Bu öğreticide tanımlanan çözümleyici, telefon numaralarına karşı arama yapmak için kolay bir çözüm sunarken, benzer özellikleri paylaşan herhangi bir senaryo için özel bir çözümleyici oluşturmak için de aynı işlem kullanılabilir.
Kaynakları temizleme
Kendi aboneliğinizde çalışırken, bir projenin sonunda artık ihtiyacınız olmayan kaynakları kaldırmak iyi bir fikirdir. Çalışır durumda bırakılan kaynaklar maliyetlerin artmasına neden olabilir. Kaynakları teker teker silebilir veya tüm kaynak grubunu silerek kaynak kümesinin tamamını kaldırabilirsiniz.
Sol gezinti bölmesindeki Tüm kaynaklar veya Kaynak grupları bağlantısını kullanarak Kaynakları Azure portalında bulabilir ve yönetebilirsiniz.
Sonraki adımlar
Artık özel çözümleyici oluşturmayı bildiğinize göre, zengin bir arama deneyimi oluşturmak için kullanabileceğiniz tüm farklı filtrelere, belirteç oluşturuculara ve çözümleyicilere göz atalım.