Buat aplikasi konsol dengan menggunakan pustaka klien Azure.Search.Documents untuk menambahkan peringkat semantik ke indeks pencarian yang ada.
Atau, Anda dapat mengunduh kode sumber untuk memulai dengan proyek yang sudah selesai.
Menyiapkan lingkungan Anda
Mulai Visual Studio dan buat proyek baru untuk aplikasi konsol.
Pada Tools>Paket Pengelolah NuGet , Pilih Kelola Paket NuGet Packages untuk Solusi....
Pilih Telusur.
Cari paket Azure.Search.Documents dan pilih versi stabil terbaru.
Pilih Instal untuk menambahkan rakitan ke proyek dan solusi Anda.
Buat klien pencarian
Di Program.cs, tambahkan arahan berikut using
.
using Azure;
using Azure.Search.Documents;
using Azure.Search.Documents.Indexes;
using Azure.Search.Documents.Indexes.Models;
using Azure.Search.Documents.Models;
Buat dua klien: SearchIndexClient membuat indeks, dan SearchClient memuat dan menanyakan indeks yang ada.
Kedua klien memerlukan titik akhir layanan dan kunci API admin untuk autentikasi dengan hak buat/hapus. Namun, kode membangun URI untuk Anda, jadi tentukan hanya nama layanan pencarian untuk serviceName
properti . Jangan sertakan https://
atau .search.windows.net
.
static void Main(string[] args)
{
string serviceName = "<YOUR-SEARCH-SERVICE-NAME>";
string apiKey = "<YOUR-SEARCH-ADMIN-API-KEY>";
string indexName = "hotels-quickstart";
// Create a SearchIndexClient to send create/delete index commands
Uri serviceEndpoint = new Uri($"https://{serviceName}.search.windows.net/");
AzureKeyCredential credential = new AzureKeyCredential(apiKey);
SearchIndexClient adminClient = new SearchIndexClient(serviceEndpoint, credential);
// Create a SearchClient to load and query documents
SearchClient srchclient = new SearchClient(serviceEndpoint, indexName, credential);
. . .
}
Buat indeks
Buat atau perbarui skema indeks untuk menyertakan SemanticConfiguration
. Jika Anda memperbarui indeks yang ada, modifikasi ini tidak memerlukan pengindeksan ulang karena struktur dokumen Anda tidak berubah.
// Create hotels-quickstart index
private static void CreateIndex(string indexName, SearchIndexClient adminClient)
{
FieldBuilder fieldBuilder = new FieldBuilder();
var searchFields = fieldBuilder.Build(typeof(Hotel));
var definition = new SearchIndex(indexName, searchFields);
var suggester = new SearchSuggester("sg", new[] { "HotelName", "Category", "Address/City", "Address/StateProvince" });
definition.Suggesters.Add(suggester);
definition.SemanticSearch = new SemanticSearch
{
Configurations =
{
new SemanticConfiguration("my-semantic-config", new()
{
TitleField = new SemanticField("HotelName"),
ContentFields =
{
new SemanticField("Description"),
new SemanticField("Description_fr")
},
KeywordsFields =
{
new SemanticField("Tags"),
new SemanticField("Category")
}
})
}
};
adminClient.CreateOrUpdateIndex(definition);
}
Kode berikut membuat indeks pada layanan pencarian Anda:
// Create index
Console.WriteLine("{0}", "Creating index...\n");
CreateIndex(indexName, adminClient);
SearchClient ingesterClient = adminClient.GetSearchClient(indexName);
Muat dokumen
Pencarian Azure AI mencari konten yang disimpan dalam layanan. Kode untuk mengunggah dokumen identik dengan mulai cepat C# untuk pencarian teks lengkap sehingga kita tidak perlu menduplikasinya di sini. Anda harus memiliki empat hotel dengan nama, alamat, dan deskripsi. Solusi Anda harus memiliki jenis untuk Hotel dan Alamat.
Mencari indeks
Berikut adalah kueri yang memanggil pemeringkat semantik, dengan opsi pencarian untuk menentukan parameter:
Console.WriteLine("Example of a semantic query.");
options = new SearchOptions()
{
QueryType = Azure.Search.Documents.Models.SearchQueryType.Semantic,
SemanticSearch = new()
{
SemanticConfigurationName = "my-semantic-config",
QueryCaption = new(QueryCaptionType.Extractive)
}
};
options.Select.Add("HotelName");
options.Select.Add("Category");
options.Select.Add("Description");
// response = srchclient.Search<Hotel>("*", options);
response = srchclient.Search<Hotel>("what hotel has a good restaurant on site", options);
WriteDocuments(response);
Sebagai perbandingan, berikut adalah hasil dari kueri yang menggunakan peringkat BM25 default, berdasarkan frekuensi istilah dan kedekatan. Mengingat kueri "hotel apa yang memiliki restoran yang bagus di situs", algoritma peringkat BM25 mengembalikan kecocokan dalam urutan yang ditunjukkan dalam cuplikan layar ini:
Sebaliknya, ketika peringkat semantik diterapkan ke kueri yang sama ("hotel apa yang memiliki restoran yang bagus di situs"), hasilnya dirank ulang berdasarkan relevansi semantik dengan kueri. Kali ini, hasil teratas adalah hotel dengan restoran, yang lebih selaras dengan harapan pengguna.
Jalankan program
Tekan F5 untuk membangun kembali aplikasi dan menjalankan program secara keseluruhan.
Output mencakup pesan dari Console.WriteLine, dengan penambahan informasi dan hasil permintaan.
Gunakan buku catatan Jupyter dan pustaka azure-search-documents di Azure SDK untuk Python untuk mempelajari tentang peringkat semantik.
Atau, Anda dapat mengunduh dan menjalankan buku catatan yang sudah selesai.
Menyiapkan lingkungan Anda
Gunakan Visual Studio Code dengan ekstensi Python, atau IDE yang setara, dengan Python 3.10 atau yang lebih baru.
Kami merekomendasikan lingkungan virtual untuk mulai cepat ini:
Memulai Visual Studio Code.
Buat file ipynb baru.
Buka Palet Perintah dengan menggunakan Ctrl+Shift+P.
Cari Python: Buat Lingkungan.
Pilih Venv.
Pilih interpreter Python. Pilih 3.10 atau yang lebih baru.
Dibutuhkan waktu satu menit untuk mengatur. Jika Anda mengalami masalah, lihat lingkungan Python di Visual Studio Code.
Menginstal paket dan mengatur variabel
Instal paket, termasuk azure-search-documents.
! pip install azure-search-documents==11.6.0b1 --quiet
! pip install azure-identity --quiet
! pip install python-dotenv --quiet
Berikan titik akhir dan kunci API Anda:
search_endpoint: str = "PUT-YOUR-SEARCH-SERVICE-ENDPOINT-HERE"
search_api_key: str = "PUT-YOUR-SEARCH-SERVICE-ADMIN-API-KEY-HERE"
index_name: str = "hotels-quickstart"
Buat indeks
Buat atau perbarui skema indeks untuk menyertakan SemanticConfiguration
. Jika Anda memperbarui indeks yang ada, modifikasi ini tidak memerlukan pengindeksan ulang karena struktur dokumen Anda tidak berubah.
from azure.search.documents.indexes import SearchIndexClient
from azure.search.documents import SearchClient
from azure.search.documents.indexes.models import (
ComplexField,
SimpleField,
SearchFieldDataType,
SearchableField,
SearchIndex,
SemanticConfiguration,
SemanticField,
SemanticPrioritizedFields,
SemanticSearch
)
# Create a search schema
index_client = SearchIndexClient(
endpoint=search_endpoint, credential=credential)
fields = [
SimpleField(name="HotelId", type=SearchFieldDataType.String, key=True),
SearchableField(name="HotelName", type=SearchFieldDataType.String, sortable=True),
SearchableField(name="Description", type=SearchFieldDataType.String, analyzer_name="en.lucene"),
SearchableField(name="Description_fr", type=SearchFieldDataType.String, analyzer_name="fr.lucene"),
SearchableField(name="Category", type=SearchFieldDataType.String, facetable=True, filterable=True, sortable=True),
SearchableField(name="Tags", collection=True, type=SearchFieldDataType.String, facetable=True, filterable=True),
SimpleField(name="ParkingIncluded", type=SearchFieldDataType.Boolean, facetable=True, filterable=True, sortable=True),
SimpleField(name="LastRenovationDate", type=SearchFieldDataType.DateTimeOffset, facetable=True, filterable=True, sortable=True),
SimpleField(name="Rating", type=SearchFieldDataType.Double, facetable=True, filterable=True, sortable=True),
ComplexField(name="Address", fields=[
SearchableField(name="StreetAddress", type=SearchFieldDataType.String),
SearchableField(name="City", type=SearchFieldDataType.String, facetable=True, filterable=True, sortable=True),
SearchableField(name="StateProvince", type=SearchFieldDataType.String, facetable=True, filterable=True, sortable=True),
SearchableField(name="PostalCode", type=SearchFieldDataType.String, facetable=True, filterable=True, sortable=True),
SearchableField(name="Country", type=SearchFieldDataType.String, facetable=True, filterable=True, sortable=True),
])
]
semantic_config = SemanticConfiguration(
name="my-semantic-config",
prioritized_fields=SemanticPrioritizedFields(
title_field=SemanticField(field_name="HotelName"),
keywords_fields=[SemanticField(field_name="Category")],
content_fields=[SemanticField(field_name="Description")]
)
)
# Create the semantic settings with the configuration
semantic_search = SemanticSearch(configurations=[semantic_config])
scoring_profiles = []
suggester = [{'name': 'sg', 'source_fields': ['Tags', 'Address/City', 'Address/Country']}]
# Create the search index with the semantic settings
index = SearchIndex(name=index_name, fields=fields, suggesters=suggester, scoring_profiles=scoring_profiles, semantic_search=semantic_search)
result = index_client.create_or_update_index(index)
print(f' {result.name} created')
Membuat payload dokumen
Anda dapat mendorong dokumen JSON ke indeks pencarian. Dokumen harus cocok dengan skema indeks.
documents = [
{
"@search.action": "upload",
"HotelId": "1",
"HotelName": "Stay-Kay City Hotel",
"Description": "The hotel is ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Time's Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.",
"Description_fr": "L'hôtel est idéalement situé sur la principale artère commerciale de la ville en plein cœur de New York. A quelques minutes se trouve la place du temps et le centre historique de la ville, ainsi que d'autres lieux d'intérêt qui font de New York l'une des villes les plus attractives et cosmopolites de l'Amérique.",
"Category": "Boutique",
"Tags": [ "pool", "air conditioning", "concierge" ],
"ParkingIncluded": "false",
"LastRenovationDate": "1970-01-18T00:00:00Z",
"Rating": 3.60,
"Address": {
"StreetAddress": "677 5th Ave",
"City": "New York",
"StateProvince": "NY",
"PostalCode": "10022",
"Country": "USA"
}
},
{
"@search.action": "upload",
"HotelId": "2",
"HotelName": "Old Century Hotel",
"Description": "The hotel is situated in a nineteenth century plaza, which has been expanded and renovated to the highest architectural standards to create a modern, functional and first-class hotel in which art and unique historical elements coexist with the most modern comforts.",
"Description_fr": "L'hôtel est situé dans une place du XIXe siècle, qui a été agrandie et rénovée aux plus hautes normes architecturales pour créer un hôtel moderne, fonctionnel et de première classe dans lequel l'art et les éléments historiques uniques coexistent avec le confort le plus moderne.",
"Category": "Boutique",
"Tags": [ "pool", "free wifi", "concierge" ],
"ParkingIncluded": "false",
"LastRenovationDate": "1979-02-18T00:00:00Z",
"Rating": 3.60,
"Address": {
"StreetAddress": "140 University Town Center Dr",
"City": "Sarasota",
"StateProvince": "FL",
"PostalCode": "34243",
"Country": "USA"
}
},
{
"@search.action": "upload",
"HotelId": "3",
"HotelName": "Gastronomic Landscape Hotel",
"Description": "The Hotel stands out for its gastronomic excellence under the management of William Dough, who advises on and oversees all of the Hotel's restaurant services.",
"Description_fr": "L'hôtel est situé dans une place du XIXe siècle, qui a été agrandie et rénovée aux plus hautes normes architecturales pour créer un hôtel moderne, fonctionnel et de première classe dans lequel l'art et les éléments historiques uniques coexistent avec le confort le plus moderne.",
"Category": "Resort and Spa",
"Tags": [ "air conditioning", "bar", "continental breakfast" ],
"ParkingIncluded": "true",
"LastRenovationDate": "2015-09-20T00:00:00Z",
"Rating": 4.80,
"Address": {
"StreetAddress": "3393 Peachtree Rd",
"City": "Atlanta",
"StateProvince": "GA",
"PostalCode": "30326",
"Country": "USA"
}
},
{
"@search.action": "upload",
"HotelId": "4",
"HotelName": "Sublime Palace Hotel",
"Description": "Sublime Palace Hotel is located in the heart of the historic center of Sublime in an extremely vibrant and lively area within short walking distance to the sites and landmarks of the city and is surrounded by the extraordinary beauty of churches, buildings, shops and monuments. Sublime Palace is part of a lovingly restored 1800 palace.",
"Description_fr": "Le Sublime Palace Hotel est situé au coeur du centre historique de sublime dans un quartier extrêmement animé et vivant, à courte distance de marche des sites et monuments de la ville et est entouré par l'extraordinaire beauté des églises, des bâtiments, des commerces et Monuments. Sublime Palace fait partie d'un Palace 1800 restauré avec amour.",
"Category": "Boutique",
"Tags": [ "concierge", "view", "24-hour front desk service" ],
"ParkingIncluded": "true",
"LastRenovationDate": "1960-02-06T00:00:00Z",
"Rating": 4.60,
"Address": {
"StreetAddress": "7400 San Pedro Ave",
"City": "San Antonio",
"StateProvince": "TX",
"PostalCode": "78216",
"Country": "USA"
}
}
]
Mengunggah dokumen ke indeks
search_client = SearchClient(endpoint=search_endpoint,
index_name=index_name,
credential=credential)
try:
result = search_client.upload_documents(documents=documents)
print("Upload of new document succeeded: {}".format(result[0].succeeded))
except Exception as ex:
print (ex.message)
index_client = SearchIndexClient(
endpoint=search_endpoint, credential=credential)
Menjalankan kueri pertama Anda
Mulailah dengan kueri kosong sebagai langkah verifikasi, membuktikan bahwa indeks beroperasi. Anda harus mendapatkan daftar nama dan deskripsi hotel yang tidak diurutkan, dengan hitungan 4 yang menunjukkan bahwa ada empat dokumen dalam indeks.
# Run an empty query (returns selected fields, all documents)
results = search_client.search(query_type='simple',
search_text="*" ,
select='HotelName,Description',
include_total_count=True)
print ('Total Documents Matching Query:', results.get_count())
for result in results:
print(result["@search.score"])
print(result["HotelName"])
print(f"Description: {result['Description']}")
Menjalankan kueri teks
Untuk tujuan perbandingan, jalankan kueri teks dengan penilaian relevansi BM25. Pencarian teks lengkap dipanggil saat Anda menyediakan string kueri. Respons terdiri dari hasil peringkat, di mana skor yang lebih tinggi diberikan kepada dokumen yang memiliki lebih banyak instans istilah yang cocok, atau istilah yang lebih penting.
Dalam kueri ini untuk hotel apa yang memiliki restoran yang bagus di tempat, Sublime Palace Hotel muncul di atas karena deskripsinya termasuk situs. Istilah yang jarang terjadi menaikkan skor pencarian dokumen.
# Run a text query (returns a BM25-scored result set)
results = search_client.search(query_type='simple',
search_text="what hotel has a good restaurant on site" ,
select='HotelName,HotelId,Description',
include_total_count=True)
for result in results:
print(result["@search.score"])
print(result["HotelName"])
print(f"Description: {result['Description']}")
Menjalankan kueri semantik
Sekarang tambahkan peringkat semantik. Parameter baru meliputi query_type
dan semantic_configuration_name
.
Ini adalah kueri yang sama, tetapi perhatikan bahwa ranker semantik dengan benar mengidentifikasi Gastronomic Landscape Hotel sebagai hasil yang lebih relevan mengingat kueri awal. Kueri ini juga mengembalikan keterangan yang dihasilkan oleh model. Input terlalu minimal dalam sampel ini untuk membuat keterangan menarik, tetapi contohnya berhasil menunjukkan sintaks.
# Runs a semantic query (runs a BM25-ranked query and promotes the most relevant matches to the top)
results = search_client.search(query_type='semantic', semantic_configuration_name='my-semantic-config',
search_text="what hotel has a good restaurant on site",
select='HotelName,Description,Category', query_caption='extractive')
for result in results:
print(result["@search.reranker_score"])
print(result["HotelName"])
print(f"Description: {result['Description']}")
captions = result["@search.captions"]
if captions:
caption = captions[0]
if caption.highlights:
print(f"Caption: {caption.highlights}\n")
else:
print(f"Caption: {caption.text}\n")
Mengembalikan jawaban semantik
Dalam kueri akhir ini, kembalikan jawaban semantik.
Pemeringkat semantik dapat menghasilkan jawaban atas string kueri yang memiliki karakteristik pertanyaan. Jawaban yang dihasilkan diekstrak verbatim dari konten Anda. Untuk mendapatkan jawaban semantik, pertanyaan dan jawaban harus selaras erat, dan model harus menemukan konten yang menjawab pertanyaan dengan jelas. Jika potensi jawaban gagal memenuhi ambang keyakinan, model tidak mengembalikan jawaban. Untuk tujuan demonstrasi, pertanyaan dalam contoh ini dirancang untuk mendapatkan respons sehingga Anda dapat melihat sintaks.
# Run a semantic query that returns semantic answers
results = search_client.search(query_type='semantic', semantic_configuration_name='my-semantic-config',
search_text="what hotel is in a historic building",
select='HotelName,Description,Category', query_caption='extractive', query_answer="extractive",)
semantic_answers = results.get_answers()
for answer in semantic_answers:
if answer.highlights:
print(f"Semantic Answer: {answer.highlights}")
else:
print(f"Semantic Answer: {answer.text}")
print(f"Semantic Answer Score: {answer.score}\n")
for result in results:
print(result["@search.reranker_score"])
print(result["HotelName"])
print(f"Description: {result['Description']}")
captions = result["@search.captions"]
if captions:
caption = captions[0]
if caption.highlights:
print(f"Caption: {caption.highlights}\n")
else:
print(f"Caption: {caption.text}\n")