Für den Zweck dieses Beitrags verwende ich die Newsgroup-Datensatz als mein Korpus, a T5-kleines Modell zu bekommen Dokumentebene Einbettungen und ein lokal ausgeführter Elasticsearch-Cluster. Das komplette Notizbuch liegt bei mir GitHub.
Bitte beachten Sie, dass Sie jederzeit ein besseres Modell auswählen können (z. B FLAN-T5) und optimieren Sie das ausgewählte Modell auf Ihrem eigenen Korpus, um bessere Ergebnisse zu erzielen. Sie sollten sich auch mit Rangfolge-Abrufmetriken befassen, z nDCG um zu messen, wie intestine Ihr semantisches Suchsystem funktioniert.
1. Richten Sie einen Elasticsearch-Cluster mit einem Knoten in Ihrer lokalen Umgebung ein
Sie können diesen Abschnitt überspringen, wenn Sie bereits einen haben.
- Ziehen Sie das Elasticsearch Docker-Picture
docker pull docker.elastic.co/elasticsearch/elasticsearch:8.7.0
- Erstellen Sie ein neues Docker-Netzwerk für Elasticsearch und Kibana
docker community create elastic
- Starten Sie Elasticsearch in Docker
docker run --name es01 --net elastic -p 9200:9200 -it docker.elastic.co/elasticsearch/elasticsearch:8.7.0
- Kopieren Sie das Sicherheitszertifikat http_ca.crt aus Ihrem Docker-Container auf Ihren lokalen Pc
docker cp es01:/usr/share/elasticsearch/config/certs/http_ca.crt .
- [optional] Kibana einrichten:
docker run --name kibana --net elastic -p 5601:5601 docker.elastic.co/kibana/kibana:8.2.2
Beachten Sie, dass Sie das Registrierungstoken aus Schritt 3 benötigen - Testen Sie, ob Sie über Ihr Pocket book Zugriff auf Ihren Cluster haben. Weitere Informationen zu Elasticsearch Python-CLI.
2. Erstellen Sie einen Elasticsearch-Index
from elasticsearch import ElasticsearchELASTIC_PASSWORD = "PASSWORD"
ES_HOST = "https://localhost:9200/"
index_name = "semantic-search"
# Create the shopper occasion
shopper = Elasticsearch(
hosts=ES_HOST,
ca_certs='./http_ca.crt',
basic_auth=("elastic", ELASTIC_PASSWORD)
)
# get cluster info
shopper.data()
# outline index config
config = {
"mappings": {
"properties": {
"textual content": {"sort": "textual content"},
"embeddings": {
"sort": "dense_vector",
"dims": 512,
"index": True
}
}
},
"settings": {
"number_of_shards": 2,
"number_of_replicas": 1
}
}
# create an index in elasticsearch
attempt:
shopper.indices.create(
index=index_name,
settings=config["settings"],
mappings=config["mappings"],
)
besides:
print(f"Index already exists: {shopper.indices.exists(index=[index_name])}")
3. Holen Sie sich die Einbettungsvektoren
import torch
from datasets import load_dataset
from transformers import T5Model, T5Tokenizer# load the dataset
dataset = load_dataset('newsgroup', '18828_alt.atheism')
# examine an instance of knowledge
dataset['train'][0]['text']
# load the pre-trained mannequin
tokenizer = T5Tokenizer.from_pretrained("t5-small")
mannequin = T5Model.from_pretrained("t5-small")
# operate to get embeddings
def get_embeddings(input_text, mannequin=mannequin, tokenizer=tokenizer, max_length=512):
inputs = tokenizer.encode_plus(input_text,
max_length=max_length,
pad_to_max_length=True,
return_tensors="pt")
outputs = mannequin(input_ids=inputs['input_ids'], decoder_input_ids=inputs['input_ids'])
last_hidden_states = torch.imply(outputs[0], dim=1)
return last_hidden_states.tolist()
# index paperwork and their embedding in Elasticsearch
for i in vary(small_dataset.num_rows):
doc = {"textual content": small_dataset['text'][i],
"embeddings": get_embeddings(small_dataset['text'][i])[0]
}
shopper.index(index= index_name, doc=doc)
# examine the variety of saved paperwork
end result = shopper.depend(index=index_name)
print(end result.physique['count'])
4. Suchen!
Nachdem die Indizierung abgeschlossen ist, können wir unsere Daten durchsuchen. Elasticsearch nutzt Kosinusähnlichkeit, bietet aber auch einen Python-Wrapper zur Durchführung der KNN-Suche. Sie haben auch die Möglichkeit, eine benutzerdefinierte Ähnlichkeitsfunktion zu verwenden.
Ich habe einen Codeausschnitt für KNN mit ok=5 bereitgestellt. Denken Sie daran, dass Sie auch Einbettungen für Ihren Abfragebegriff bereitstellen müssen.
query_embedding = get_embeddings(dataset['train']['text'][20])[0]
query_dict = {
"discipline": "embeddings",
"query_vector": query_embedding,
"ok": 5,
"num_candidates": 5
}
res = shopper.knn_search(index=index_name, knn=query_dict, supply=["text"])