Erstellen Sie mithilfe der Clientbibliothek Azure.Search.Documents eine Konsolenanwendung, um einem vorhandenen Index semantische Rangfolge hinzuzufügen.
Alternativ können Sie den Quellcode herunterladen, um mit einem fertigen Projekt zu beginnen.
Einrichten Ihrer Umgebung
Starten Sie Visual Studio, und erstellen Sie ein neues Projekt für eine Konsolen-App.
Wählen Sie unter Tools>NuGet-Paket-Manager die Option NuGet-Pakete für Projektmappe verwalten... aus.
Wählen Sie Durchsuchen aus.
Suchen Sie nach dem Azure.Search.Documents-Paket, und wählen Sie die neueste stabile Version aus.
Wählen Sie Installieren aus, um die Assembly Ihrem Projekt und Ihrer Projektmappe hinzuzufügen.
Erstellen eines Suchclients
Fügen Sie in Program.cs die folgenden using
-Anweisungen hinzu.
using Azure;
using Azure.Search.Documents;
using Azure.Search.Documents.Indexes;
using Azure.Search.Documents.Indexes.Models;
using Azure.Search.Documents.Models;
Erstellen Sie zwei Clients: SearchIndexClient erstellt den Index und SearchClient lädt und fragt einen vorhandenen Index ab.
Beide Clients benötigen den Dienstendpunkt und einen Administrator-API-Schlüssel für die Authentifizierung mit Berechtigungen zum Erstellen/Löschen. Der Code erstellt jedoch den URI für Sie. Geben Sie daher nur den Suchdienstnamen in der Eigenschaft serviceName
an. Nehmen Sie https://
oder .search.windows.net
nicht auf.
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);
. . .
}
Erstellen eines Index
Erstellen oder aktualisieren Sie ein Indexschema, um eine SemanticConfiguration
einzuschließen. Wenn Sie einen vorhandenen Index aktualisieren, ist für diese Änderung keine Neuindizierung erforderlich, da die Struktur Ihrer Dokumente unverändert bleibt.
// 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);
}
Der folgende Code erstellt den Index für Ihren Suchdienst:
// Create index
Console.WriteLine("{0}", "Creating index...\n");
CreateIndex(indexName, adminClient);
SearchClient ingesterClient = adminClient.GetSearchClient(indexName);
Laden von Dokumenten
Azure KI Search durchsucht im Dienst gespeicherte Inhalte. Der Code zum Hochladen von Dokumenten ist identisch mit dem im C#-Schnellstart für die Volltextsuche , sodass wir ihn hier nicht duplizieren müssen. Sie sollten über vier Hotels mit Namen, Adressen und Beschreibungen verfügen. Ihre Lösung sollte Typen für Hotels und Adressen aufweisen.
Durchsuchen eines Index
Hier sehen Sie eine Abfrage, die den semantischen Sortierer mit Suchoptionen zum Angeben von Parametern aufruft:
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);
Hier finden Sie die Ergebnisse einer Abfrage, die die BM25-Standardrangfolge basierend auf der Begriffshäufigkeit und -nähe verwendet. Bei der Abfrage „What hotel has a good restaurant on site“ (Welches Hotel verfügt über ein gutes Restaurant), gibt der BM25-Bewertungsalgorithmus Übereinstimmungen in der Reihenfolge zurück, die in diesem Screenshot gezeigt wird:
Wenn die semantische Rangfolge auf dieselbe Abfrage („Welches Hotel verfügt über ein gutes Restaurant“) angewendet wird, werden die Ergebnisse hingegen basierend auf der semantischen Relevanz für die Abfrage neu bewertet. Dieses Mal ist das Top-Ergebnis das Hotel mit dem Restaurant, was den Erwartungen der Nutzer am besten entspricht.
Ausführen des Programms
Drücken Sie F5, um die App neu zu erstellen und das fertige Programm auszuführen.
Die Ausgabe umfasst Nachrichten aus Console.WriteLine, wobei Abfrageinformationen und -ergebnisse hinzugefügt werden.
Verwenden Sie ein Jupyter-Notebook und die Bibliothek azure-search-documents im Azure SDK für Python um mehr über die semantische Rangfolge zu erfahren.
Alternativ können Sie auch ein fertiges Notebook herunterladen und ausführen.
Erstellen Ihrer Umgebung
Verwenden Sie Visual Studio Code mit der Python-Erweiterung oder einer entsprechenden IDE, mit Python 3.10 oder höher
Wir empfehlen eine virtuelle Umgebung für diesen Schnellstart:
Starten Sie Visual Studio Code.
Erstellen Sie eine neue IPYNB-Datei.
Öffnen Sie die Befehlspalette mithilfe von STRG+UMSCHALT+P.
Suchen Sie nach Python: Umgebung erstellen.
Wählen Sie Venv.
aus.
Wählen Sie einen Python-Interpreter aus. Wählen Sie 3.10 oder höher aus.
Die Einrichtung kann eine Minute dauern. Wenn Probleme auftreten, sehen Sie unter Python-Umgebungen in VS Code nach.
Installieren von Paketen und Festlegen von Variablen
Installieren Sie Pakete, einschließlich azure-search-documents.
! pip install azure-search-documents==11.6.0b1 --quiet
! pip install azure-identity --quiet
! pip install python-dotenv --quiet
Geben Sie den Endpunkt und API-Schlüssel an:
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"
Erstellen eines Index
Erstellen oder aktualisieren Sie ein Indexschema, um eine SemanticConfiguration
einzuschließen. Wenn Sie einen vorhandenen Index aktualisieren, ist für diese Änderung keine Neuindizierung erforderlich, da die Struktur Ihrer Dokumente unverändert bleibt.
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])
semantic_settings = 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')
Erstellen von Dokumentnutzdaten
Sie können JSON-Dokumente in einen Suchindex pushen. Dokumente müssen mit dem Indexschema übereinstimmen.
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"
}
}
]
Hochladen von Dokumenten in den Index
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)
Ausführen der ersten Abfrage
Beginnen Sie mit einer leeren Abfrage als Überprüfungsschritt, um nachzuweisen, dass der Index betriebsbereit ist. Sie sollten eine ungeordnete Liste von Hotelnamen und -beschreibungen mit der Anzahl 4 erhalten, die angibt, dass der Index vier Dokumente enthält.
# 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']}")
Ausführen einer Textabfrage
Führen Sie zu Vergleichszwecken eine Textabfrage mit BM25-Relevanzbewertung durch. Die Volltextsuche wird aufgerufen, wenn Sie eine Abfragezeichenfolge angeben. Die Antwort besteht aus bewerteten Ergebnissen, bei denen Dokumenten mit mehr übereinstimmenden Begriffen oder wichtigeren Begriffen höhere Bewertungen zugewiesen werden.
In dieser Abfrage für Welches Hotel verfügt über ein gutes Restaurant vor Ort, steht das Sublime Palace Hotel an erster Stelle, da seine Beschreibung vor Ort enthält. Begriffe, die selten vorkommen, erhöhen die Suchbewertung des Dokuments.
# 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']}")
Ausführen einer Semantikabfrage
Fügen Sie nun eine semantische Rangfolge hinzu. Zu den neuen Parametern zählen query_type
und semantic_configuration_name
.
Es handelt sich um dieselbe Suchanfrage, aber der semantische Bewerter identifiziert das Gastronomic Landscape Hotel korrekt als das relevantere Ergebnis im Vergleich zur ursprünglichen Suchanfrage. Diese Abfrage gibt auch von den Modellen generierte Beschriftungen zurück. Die Eingaben in diesem Beispiel sind zu spärlich, um interessante Beschriftungen zu erstellen, aber im Beispiel wird die Syntax gut demonstriert.
# 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")
Zurückgeben semantischer Antworten
Geben Sie in dieser letzten Abfrage semantische Antworten zurück.
Der semantische Sortierer kann Antworten auf eine Abfragezeichenfolge generieren, die die Merkmale einer Frage aufweist. Die generierte Antwort wird wörtlich aus Ihren Inhalten extrahiert. Um eine semantische Antwort zu erhalten, müssen Frage und Antwort eng aufeinander abgestimmt sein, und das Modell muss Inhalte finden, die die Frage eindeutig beantworten. Wenn potenzielle Antworten einen Konfidenzschwellenwert nicht erreichen, gibt das Modell keine Antwort zurück. Zur Veranschaulichung ist die Frage in diesem Beispiel so gestaltet, dass Sie eine Antwort erhalten, damit Sie die Syntax sehen können.
# 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")