Vytvořte konzolovou aplikaci pomocí klientské knihovny Azure.Search.Documents a přidejte do existujícího indexu vyhledávání sémantické řazení.
Případně si můžete stáhnout zdrojový kód , abyste mohli začít s hotovým projektem.
Nastavení prostředí
Spusťte Visual Studio a vytvořte nový projekt pro konzolovou aplikaci.
V nástrojích>NuGet Správce balíčků vyberte Spravovat balíčky NuGet pro řešení....
Vyberte Procházet.
Vyhledejte balíček Azure.Search.Documents a vyberte nejnovější stabilní verzi.
Vyberte Nainstalovat a přidejte sestavení do projektu a řešení.
Vytvoření vyhledávacího klienta
Do Program.cs přidejte následující using
direktivy.
using Azure;
using Azure.Search.Documents;
using Azure.Search.Documents.Indexes;
using Azure.Search.Documents.Indexes.Models;
using Azure.Search.Documents.Models;
Vytvořte dva klienty: SearchIndexClient vytvoří index a SearchClient načte a dotazuje existující index.
Oba klienti potřebují koncový bod služby a klíč rozhraní API pro správu pro ověřování s právy k vytvoření nebo odstranění. Kód však sestaví identifikátor URI za vás, takže zadejte pouze název vyhledávací služby pro serviceName
vlastnost. Nezahrnujte https://
ani .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);
. . .
}
Vytvoření indexu
Vytvořte nebo aktualizujte schéma indexu tak, aby zahrnovalo SemanticConfiguration
. Pokud aktualizujete existující index, tato změna nevyžaduje přeindexování, protože struktura dokumentů se nezmění.
// 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);
}
Následující kód vytvoří index ve vyhledávací službě:
// Create index
Console.WriteLine("{0}", "Creating index...\n");
CreateIndex(indexName, adminClient);
SearchClient ingesterClient = adminClient.GetSearchClient(indexName);
Nahrání dokumentů
Azure AI Search vyhledá obsah uložený ve službě. Kód pro nahrávání dokumentů je shodný s rychlým startem jazyka C# pro fulltextové vyhledávání , takže ho tady nemusíme duplikovat. Měli byste mít čtyři hotely se jmény, adresami a popisy. Vaše řešení by mělo mít typy hotelů a adres.
Prohledání indexu
Tady je dotaz, který vyvolá sémantický ranker s možnostmi hledání pro zadání parametrů:
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);
Tady jsou výsledky dotazu, který používá výchozí řazení BM25 na základě četnosti termínů a blízkosti. Vzhledem k dotazu "jaký hotel má dobrou restauraci na místě", algoritmus hodnocení BM25 vrátí shodu v pořadí uvedeném na tomto snímku obrazovky:
Pokud se na stejný dotaz použije sémantické řazení ("jaký hotel má na místě dobrou restauraci"), výsledky se přeřadí na základě sémantické relevance dotazu. Tentokrát je nejlepší výsledek hotel s restaurací, která odpovídá očekáváním uživatelů.
Spuštění programu
Stisknutím klávesy F5 znovu sestavíte aplikaci a spustíte program v plném rozsahu.
Výstup obsahuje zprávy z Console.WriteLine s přidáním informací o dotazu a výsledků.
Pomocí poznámkového bloku Jupyter a knihovny azure-search-documents v sadě Azure SDK pro Python se dozvíte o sémantickém řazení.
Případně si můžete stáhnout a spustit hotový poznámkový blok.
Nastavení prostředí
Použijte Visual Studio Code s rozšířením Pythonu nebo ekvivalentním integrovaným vývojovém prostředím (IDE) s Pythonem 3.10 nebo novějším.
Pro účely tohoto rychlého startu doporučujeme virtuální prostředí:
Spusťte Visual Studio Code.
Vytvořte nový soubor ipynb.
Otevřete paletu příkazů pomocí kombinace kláves Ctrl+Shift+P.
Vyhledejte Python: Vytvoření prostředí.
Vyberte Venv.
Vyberte interpret Pythonu. Zvolte 3.10 nebo novější.
Nastavení může trvat minutu. Pokud narazíte na problémy, prohlédni si prostředí Pythonu ve VS Code.
Instalace balíčků a nastavení proměnných
Nainstalujte balíčky, včetně azure-search-documents.
! pip install azure-search-documents==11.6.0b1 --quiet
! pip install azure-identity --quiet
! pip install python-dotenv --quiet
Zadejte svůj koncový bod a klíče rozhraní API:
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"
Vytvoření indexu
Vytvořte nebo aktualizujte schéma indexu tak, aby zahrnovalo SemanticConfiguration
. Pokud aktualizujete existující index, tato změna nevyžaduje přeindexování, protože struktura dokumentů se nezmění.
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')
Vytvoření datové části dokumentů
Dokumenty JSON můžete odeslat do indexu vyhledávání. Dokumenty musí odpovídat schématu indexu.
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"
}
}
]
Nahrání dokumentů do indexu
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)
Spuštění prvního dotazu
Začněte prázdným dotazem jako ověřovacím krokem a ověřte, že je index funkční. Měli byste získat neuspořádaný seznam názvů a popisů hotelů s počtem 4 označujících, že v indexu jsou čtyři dokumenty.
# 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']}")
Spuštění textového dotazu
Pro účely porovnání spusťte textový dotaz s vyhodnocováním relevance BM25. Fulltextové vyhledávání se vyvolá při zadání řetězce dotazu. Odpověď se skládá z seřazených výsledků, kdy jsou udělena vyšší skóre dokumentům s více instancemi odpovídajících termínů nebo důležitějších termínů.
V tomto dotazu na to, co hotel má dobrou restauraci na místě, Sublime Palace Hotel je nahoře, protože jeho popis zahrnuje web. Termíny, ke kterým dochází zřídka, zvýší skóre hledání dokumentu.
# 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']}")
Spuštění sémantického dotazu
Teď přidejte sémantické hodnocení. Nové parametry zahrnují query_type
a semantic_configuration_name
.
Je to stejný dotaz, ale všimněte si, že sémantický ranker správně identifikuje Gastronomic Landscape Hotel jako relevantnější výsledek vzhledem k počátečnímu dotazu. Tento dotaz také vrátí titulky generované modely. Vstupy jsou v této ukázce příliš minimální, aby se vytvořily zajímavé titulky, ale příklad úspěšně demonstruje syntaxi.
# 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")
Vrácení sémantických odpovědí
V tomto posledním dotazu vrátíte sémantické odpovědi.
Sémantický ranker může generovat odpovědi na řetězec dotazu, který má charakteristiky otázky. Vygenerovaná odpověď se extrahuje doslovně z vašeho obsahu. Aby bylo možné získat sémantickou odpověď, musí být otázka a odpověď úzce sladěná a model musí najít obsah, který jasně odpovídá na otázku. Pokud potenciální odpovědi nesplní prahovou hodnotu spolehlivosti, model nevrátí odpověď. Pro demonstrační účely je otázka v tomto příkladu navržená tak, aby získala odpověď, abyste viděli syntaxi.
# 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")