Hozzon létre egy konzolalkalmazást az Azure.Search.Documents ügyfélkódtár használatával, hogy szemantikai rangsorolást adjon hozzá egy meglévő keresési indexhez.
Másik lehetőségként letöltheti a forráskódot, hogy egy befejezett projekttel kezdjen.
Saját környezet beállítása
Indítsa el a Visual Studiót, és hozzon létre egy új projektet egy konzolalkalmazáshoz.
A NuGet-Csomagkezelő eszközökben >válassza a Megoldáshoz készült NuGet-csomagok kezelése... lehetőséget.
Válassza a Tallózás lehetőséget.
Keresse meg az Azure.Search.Documents csomagot , és válassza ki a legújabb stabil verziót.
Válassza a Telepítés lehetőséget a szerelvény projekthez és megoldáshoz való hozzáadásához.
Keresési ügyfél létrehozása
A Program.cs adja hozzá a következő using
irányelveket.
using Azure;
using Azure.Search.Documents;
using Azure.Search.Documents.Indexes;
using Azure.Search.Documents.Indexes.Models;
using Azure.Search.Documents.Models;
Hozzon létre két ügyfelet: a SearchIndexClient létrehozza az indexet, a SearchClient pedig betölt és lekérdez egy meglévő indexet.
Mindkét ügyfélnek szüksége van a szolgáltatásvégpontra és egy rendszergazdai API-kulcsra a létrehozási/törlési jogosultságokkal történő hitelesítéshez. A kód azonban létrehozza az URI-t, ezért csak a keresési szolgáltatás nevét adja meg a serviceName
tulajdonsághoz. Ne tartalmazza https://
vagy .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);
. . .
}
Index létrehozása
Hozzon létre vagy frissítsen egy indexsémát egy SemanticConfiguration
. Meglévő index frissítésekor ez a módosítás nem igényel újraindexelést, mert a dokumentumok szerkezete nem változik.
// 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);
}
A következő kód létrehozza az indexet a keresési szolgáltatásban:
// Create index
Console.WriteLine("{0}", "Creating index...\n");
CreateIndex(indexName, adminClient);
SearchClient ingesterClient = adminClient.GetSearchClient(indexName);
Dokumentumok betöltése
Az Azure AI Search a szolgáltatásban tárolt tartalmakon keres. A dokumentumok feltöltésének kódja megegyezik a teljes szöveges keresés C# rövid útmutatójával, így itt nem kell duplikálni. Négy hotelnek kell lennie névvel, címmel és leírással. A megoldásnak a Szállodák és címek típusokkal kell rendelkeznie.
Keresés az indexekben
Az alábbi lekérdezés a szemantikai rangsorolót hívja meg a paraméterek megadására szolgáló keresési lehetőségekkel:
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);
Összehasonlításként az alábbi eredmények egy olyan lekérdezés eredményei, amelyek a kifejezés gyakorisága és közelsége alapján az alapértelmezett BM25 rangsorolást használják. A "melyik szálloda rendelkezik jó étteremmel a helyszínen", a BM25 rangsorolási algoritmus az alábbi képernyőképen látható sorrendben adja vissza a találatokat:
Ezzel szemben, ha a szemantikai rangsorolást ugyanarra a lekérdezésre alkalmazzák ("melyik szálloda rendelkezik egy jó étteremmel a helyszínen"), az eredmények a lekérdezés szemantikai relevanciája alapján lesznek újraformázva. Ezúttal a legjobb eredmény a szálloda és az étterem, amely jobban igazodik a felhasználói elvárásokhoz.
A program futtatása
Nyomja le az F5 billentyűt az alkalmazás újraépítéséhez és a program teljes futtatásához.
A kimenet tartalmazza a Console.WriteLine üzeneteit, a lekérdezési információk és eredmények hozzáadásával.
A szemantikai rangsorolás megismeréséhez használjon Jupyter-jegyzetfüzetet és az Azure SDK for Python azure-search-documents kódtárát.
Másik lehetőségként letöltheti és futtathatja a kész jegyzetfüzetet.
Saját környezet beállítása
Használja a Visual Studio Code-ot a Python-bővítménnyel vagy azzal egyenértékű IDE-vel a Python 3.10 vagy újabb verziójával.
Ebben a rövid útmutatóban egy virtuális környezetet ajánlunk:
Indítsa el a Visual Studio Code-ot.
Hozzon létre egy új ipynb-fájlt.
Nyissa meg a parancskatalógust a Ctrl+Shift+P billentyűkombinációval.
Python keresése : Környezet létrehozása.
A következők szerint válasszon: Venv.
Válasszon egy Python-értelmezőt. Válassza a 3.10-et vagy újabb verziót.
A beállítás eltarthat egy percig. Ha problémákba ütközik, tekintse meg a Python-környezeteket a VS Code-ban.
Csomagok telepítése és változók beállítása
Telepítse a csomagokat, beleértve az azure-search-documentst is.
! pip install azure-search-documents==11.6.0b1 --quiet
! pip install azure-identity --quiet
! pip install python-dotenv --quiet
Adja meg a végpontot és az API-kulcsokat:
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"
Index létrehozása
Hozzon létre vagy frissítsen egy indexsémát egy SemanticConfiguration
. Meglévő index frissítésekor ez a módosítás nem igényel újraindexelést, mert a dokumentumok szerkezete nem változik.
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')
Hasznos dokumentumok létrehozása
JSON-dokumentumokat leküldhet egy keresési indexbe. A dokumentumoknak meg kell egyeznie az indexsémával.
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"
}
}
]
Dokumentumok feltöltése az indexbe
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)
Az első lekérdezés futtatása
Kezdje egy üres lekérdezéssel ellenőrzési lépésként, amely igazolja, hogy az index működőképes. A szállodanevek és leírások rendezetlen listáját kell kapnia, amely 4-et tartalmaz, ami azt jelzi, hogy négy dokumentum található az indexben.
# 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']}")
Szöveges lekérdezés futtatása
Összehasonlítás céljából futtasson egy szöveges lekérdezést BM25 relevanciapontozással. A lekérdezési sztring megadásakor a teljes szöveges keresés meg lesz hívva. A válasz rangsorolt eredményekből áll, ahol magasabb pontszámot kapnak azoknak a dokumentumoknak, amelyek több egyező kifejezéssel vagy fontosabb kifejezésekkel rendelkeznek.
Ebben a lekérdezésben , hogy melyik szálloda rendelkezik egy jó étterem a helyszínen, a Sublime Palace Hotel felül jelenik meg, mert a leírás tartalmazza a webhelyet. A ritkán előforduló kifejezések növelik a dokumentum keresési pontszámát.
# 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']}")
Szemantikai lekérdezés futtatása
Most adja hozzá a szemantikai rangsorolást. Az új paraméterek közé tartozik query_type
az és semantic_configuration_name
a .
Ez ugyanaz a lekérdezés, de figyelje meg, hogy a szemantikai rangsoroló helyesen azonosítja a Gastronomic Landscape Hotelt relevánsabb eredményként a kezdeti lekérdezés alapján. Ez a lekérdezés a modellek által létrehozott feliratokat is visszaadja. A bemenetek túl minimálisak ebben a mintában ahhoz, hogy érdekes feliratokat hozzanak létre, de a példa sikeres a szintaxis szemléltetésében.
# 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")
Szemantikai válaszok visszaadva
Ebben a végső lekérdezésben szemantikai válaszokat ad vissza.
A szemantikai rangsoroló olyan lekérdezési sztringekre adhat választ, amelyek a kérdés jellemzőivel rendelkeznek. A létrehozott válasz szó szerint ki lesz nyerve a tartalomból. Ahhoz, hogy szemantikai választ kapjon, a kérdést és a választ szorosan össze kell hangolni, és a modellnek olyan tartalmat kell találnia, amely egyértelműen megválaszolja a kérdést. Ha a lehetséges válaszok nem felelnek meg a megbízhatósági küszöbértéknek, a modell nem ad vissza választ. Bemutató célokra a jelen példában szereplő kérdés úgy van kialakítva, hogy választ kapjon, hogy láthassa a szintaxist.
# 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")