Blog

Wie man Daten über LlamaIndex in Elasticsearch einliest

Eine Schritt-für-Schritt-Anleitung zur Datenaufnahme und -suche mit RAG und LlamaIndex.

In diesem Artikel implementieren wir eine Suchmaschine für FAQs, wobei wir LlamaIndex zur Datenindizierung verwenden. Elasticsearch dient als unsere Vektordatenbank und ermöglicht die Vektorsuche, während RAG (Retrieval-Augmented Generation) den Kontext anreichert und so genauere Antworten liefert.

LlamaIndex & Elasticsearch: Dokumente einlesen und FAQ-Suche erstellen

Was ist LlamaIndex?

LlamaIndex ist ein Framework, das die Erstellung von Agenten und Workflows erleichtert, die auf großen Sprachmodellen (LLMs) basieren und mit spezifischen oder privaten Daten interagieren. Es ermöglicht die Integration von Daten aus verschiedenen Quellen (APIs, PDFs, Datenbanken) in LLMs und ermöglicht so Aufgaben wie Recherche, Informationsgewinnung und die Generierung kontextbezogener Antworten.

Schlüsselkonzepte:

  • Agenten: Intelligente Assistenten, die LLMs verwenden, um Aufgaben auszuführen, die von einfachen Antworten bis hin zu komplexen Aktionen reichen.

  • Workflows: Mehrstufige Prozesse, die Agenten, Datenkonnektoren und Tools für fortgeschrittene Aufgaben kombinieren.

  • Kontexterweiterung: Eine Technik, die das LLM mit externen Daten anreichert und so seine Trainingsbeschränkungen überwindet.

LlamaIndex- Integration mit Elasticsearch:

Elasticsearch kann auf verschiedene Weise mit LlamaIndex verwendet werden:

  • Datenquelle: Verwenden Sie den Elasticsearch Reader, um Dokumente zu extrahieren.

  • Einbettungsmodell: Daten werden für semantische Suchen in Vektoren kodiert.

  • Vektorspeicherung: Verwenden Sie Elasticsearch als Repository für die Suche nach vektorisierten Dokumenten.

  • Erweiterter Speicher: Konfigurieren Sie Strukturen wie Dokumentzusammenfassungen oder Wissensgraphen.

Verwendung von LlamaIndex und Elasticsearch zum Erstellen einer FAQ-Suche

Datenaufbereitung

Wir werden die FAQ zum Elasticsearch-Dienst als Beispiel verwenden. Jede Frage wurde von der Webseite extrahiert und in einer separaten Textdatei gespeichert. Sie können jeden beliebigen Ansatz zur Organisation der Daten verwenden; in diesem Beispiel haben wir uns dafür entschieden, die Dateien lokal zu speichern.

Beispieldatei:

File Name: what-is-elasticsearch-service.txt
Content: Elasticsearch Service is hosted and managed Elasticsearch and Kibana brought to you by the creators of Elasticsearch. Elasticsearch Service is part of Elastic Cloud and ships with features that you can only get from the company behind Elasticsearch, Kibana, Beats, and Logstash. Elasticsearch is a full text search engine that suits a range of uses, from search on websites to big data analytics and more.

Nach dem Speichern aller Fragen sieht das Verzeichnis folgendermaßen aus:

Installation der Abhängigkeiten

Die Datenerfassung und -suche werden wir mit Hilfe der Programmiersprache Python implementieren; ich habe Version 3.9 verwendet. Als Voraussetzung müssen die folgenden Abhängigkeiten installiert werden:

llama-index-vector-stores-elasticsearch
llama-index
openai

Elasticsearch und Kibana werden mit Docker erstellt und über docker-compose.yml so konfiguriert, dass sie in Version 8.16.2 ausgeführt werden. Dadurch wird die Schaffung der lokalen Umgebung erleichtert.

version: '3.8'
services:

 elasticsearch:
   image: docker.elastic.co/elasticsearch/elasticsearch:8.16.2
   container_name: elasticsearch-8.16.2
   environment:
     - node.name=elasticsearch
     - xpack.security.enabled=false
     - discovery.type=single-node
     - "ES_JAVA_OPTS=-Xms1024m -Xmx1024m"
   ports:
     - 9200:9200
   networks:
     - shared_network

 kibana:
   image: docker.elastic.co/kibana/kibana:8.16.2
   container_name: kibana-8.16.2
   restart: always
   environment:
     - ELASTICSEARCH_URL=http://elasticsearch:9200
   ports:
     - 5601:5601
   depends_on:
     - elasticsearch
   networks:
     - shared_network

networks:
 shared_network:

Dokumentenaufnahme mit LlamaIndex

Die Dokumente werden mithilfe von LlamaIndex in Elasticsearch indexiert. Zuerst laden wir die Dateien mit SimpleDirectoryReader, das das Laden von Dateien aus einem lokalen Verzeichnis ermöglicht. Nach dem Laden der Dokumente werden wir sie mithilfe des VectorStoreIndex indizieren.

documents = SimpleDirectoryReader("./faq").load_data()

storage_context = StorageContext.from_defaults(vector_store=es)
index = VectorStoreIndex(documents, storage_context=storage_context, embed_model=embed_model)

Die Vektorspeicher in LlamaIndex sind für das Speichern und Verwalten von Dokumenteneinbettungen zuständig. LlamaIndex unterstützt verschiedene Arten von Vektorspeichern, und in diesem Fall verwenden wir Elasticsearch. Im StorageContext konfigurieren wir die Elasticsearch-Instanz. Da der Kontext lokal ist, waren keine zusätzlichen Parameter erforderlich. Für Konfigurationen in anderen Umgebungen konsultieren Sie bitte die Dokumentation, um die erforderlichen Parameter zu überprüfen: ElasticsearchStore-Konfiguration.

Standardmäßig verwendet LlamaIndex das OpenAI text-embedding-ada-002- Modell zur Generierung von Einbettungen. In diesem Beispiel verwenden wir jedoch das Modell text-embedding-3-small . Wichtig zu beachten ist, dass für die Nutzung des Modells ein OpenAI-API-Schlüssel erforderlich ist.

Nachfolgend finden Sie den vollständigen Code für die Dokumentenaufnahme.

import openai
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, StorageContext
from llama_index.embeddings.openai import OpenAIEmbedding
from llama_index.vector_stores.elasticsearch import ElasticsearchStore

openai.api_key = os.environ["OPENAI_API_KEY"]

es = ElasticsearchStore(
   index_name="faq",
   es_url="http://localhost:9200"
)

def format_title(filename):
   filename_without_ext = filename.replace('.txt', '')
   text_with_spaces = filename_without_ext.replace('-', ' ')
   formatted_text = text_with_spaces.title()

   return formatted_text


embed_model = OpenAIEmbedding(model="text-embedding-3-small")

documents = SimpleDirectoryReader("./faq").load_data()

for doc in documents:
   doc.metadata['title'] = format_title(doc.metadata['file_name'])

storage_context = StorageContext.from_defaults(vector_store=es)
index = VectorStoreIndex(documents, storage_context=storage_context, embed_model=embed_model)

Nach der Ausführung werden die Dokumente wie unten dargestellt im FAQ- Index indexiert:

Suche mit RAG

Um Suchvorgänge durchzuführen, konfigurieren wir den ElasticsearchStore- Client, indem wir die Felder index_name und es_url mit der Elasticsearch-URL belegen. In retrieval_strategy haben wir die AsyncDenseVectorStrategy für Vektorsuchen definiert. Es stehen auch andere Strategien zur Verfügung, wie zum Beispiel AsyncBM25Strategy (Stichwortsuche) und AsyncSparseVectorStrategy (dünnbesetzte Vektoren). Weitere Einzelheiten finden Sie in der offiziellen Dokumentation.

es = ElasticsearchStore(
   index_name="faq",
   es_url="http://localhost:9200",
   retrieval_strategy=AsyncDenseVectorStrategy(
   )
)

Als nächstes wird ein VectorStoreIndex- Objekt erstellt, in dem wir den vector_store mithilfe des ElasticsearchStore-Objekts konfigurieren. Mit der Methode as_retriever führen wir die Suche nach den relevantesten Dokumenten für eine Anfrage durch und legen die Anzahl der zurückgegebenen Ergebnisse über den Parameter similarity_top_k auf 5 fest.

   index = VectorStoreIndex.from_vector_store(vector_store=es)
   retriever = index.as_retriever(similarity_top_k=5)
   results = retriever.retrieve(query)

Der nächste Schritt ist RAG. Die Ergebnisse der Vektorsuche werden in eine formatierte Eingabeaufforderung für das LLM integriert, wodurch eine kontextbezogene Antwort auf Basis der abgerufenen Informationen ermöglicht wird.

In der PromptTemplate definieren wir das Prompt-Format, das Folgendes umfasst:

  • Kontext ({context_str}): Vom Abrufer abgerufene Dokumente.

  • Anfrage ({query_str}): die Frage des Benutzers.

  • Anleitung: Richtlinien für das Modell, um kontextbezogen zu reagieren, ohne auf externes Wissen zurückzugreifen.

qa_prompt = PromptTemplate(
   "You are a helpful and knowledgeable assistant."
   "Your task is to answer the user's query based solely on the context provided below."
   "Do not use any prior knowledge or external information.\n"
   "---------------------\n"
   "Context:\n"
   "{context_str}\n"
   "---------------------\n"
   "Query: {query_str}\n"
   "Instructions:\n"
   "1. Carefully read and understand the context provided.\n"
   "2. If the context contains enough information to answer the query, provide a clear and concise answer.\n"
   "3. Do not make up or guess any information.\n"
   "Answer: "
)

Schließlich verarbeitet das LLM die Eingabeaufforderung und gibt eine präzise und kontextbezogene Antwort zurück.

llm = OpenAI(model="gpt-4o")
context_str = "\n\n".join([n.node.get_content() for n in results])
response = llm.complete(
   qa_prompt.format(context_str=context_str, query_str=query)
)

print("Answer:")
print(response)

Der vollständige Code ist unten aufgeführt:

es = ElasticsearchStore(
   index_name="faq",
   es_url="http://localhost:9200",
   retrieval_strategy=AsyncDenseVectorStrategy(
   )
)


def print_results(results):
   for rank, result in enumerate(results, start=1):
       title = result.metadata.get("title")
       score = result.get_score()
       text = result.get_text()
       print(f"{rank}. title={title} \nscore={score} \ncontent={text}")


def search(query: str):
   index = VectorStoreIndex.from_vector_store(vector_store=es)

   retriever = index.as_retriever(similarity_top_k=10)
   results = retriever.retrieve(QueryBundle(query_str=query))
   print_results(results)

   qa_prompt = PromptTemplate(
       "You are a helpful and knowledgeable assistant."
       "Your task is to answer the user's query based solely on the context provided below."
       "Do not use any prior knowledge or external information.\n"
       "---------------------\n"
       "Context:\n"
       "{context_str}\n"
       "---------------------\n"
       "Query: {query_str}\n"
       "Instructions:\n"
       "1. Carefully read and understand the context provided.\n"
       "2. If the context contains enough information to answer the query, provide a clear and concise answer.\n"
       "3. Do not make up or guess any information.\n"
       "Answer: "
   )

   llm = OpenAI(model="gpt-4o")
   context_str = "\n\n".join([n.node.get_content() for n in results])
   response = llm.complete(
       qa_prompt.format(context_str=context_str, query_str=query)
   )

   print("Answer:")
   print(response)


question = "Elastic services are free?"
print(f"Question: {question}")
search(question)

Nun können wir unsere Suche durchführen, zum Beispiel: „Sind Elastic-Dienste kostenlos?“, und erhalten eine kontextbezogene Antwort, die auf den FAQ-Daten selbst basiert.

Question: Elastic services are free?
Answer:
Elastic services are not entirely free. However, there is a 14-day free trial available for exploring Elastic solutions. After the trial, access to features and services depends on the subscription level.

Zur Erstellung dieser Antwort wurden folgende Dokumente verwendet:

1. title=Can I Try Elasticsearch Service For Free 
score=1.0 
content=Yes, sign up for a 14-day free trial. The trial starts the moment a cluster is created.
During the free trial period get access to a deployment to explore Elastic solutions for Enterprise Search, Observability, Security, or the latest version of the Elastic Stack.

2. title=Do You Offer Elastic S Commercial Products 
score=0.9941274512218439 
content=Yes, all Elasticsearch Service customers have access to basic authentication, role-based access control, and monitoring.
Elasticsearch Service Gold, Platinum and Enterprise customers get complete access to all the capabilities in X-Pack: Security, Alerting, Monitoring, Reporting, Graph Analysis & Visualization. Contact us to learn more.

3. title=What Is Elasticsearch Service 
score=0.9896776845746571 
content=Elasticsearch Service is hosted and managed Elasticsearch and Kibana brought to you by the creators of Elasticsearch. Elasticsearch Service is part of Elastic Cloud and ships with features that you can only get from the company behind Elasticsearch, Kibana, Beats, and Logstash. Elasticsearch is a full text search engine that suits a range of uses, from search on websites to big data analytics and more.

4. title=Can I Run The Full Elastic Stack In Elasticsearch Service 
score=0.9880631561979476 
content=Many of the products that are part of the Elastic Stack are readily available in Elasticsearch Service, including Elasticsearch, Kibana, plugins, and features such as monitoring and security. Use other Elastic Stack products directly with Elasticsearch Service. For example, both Logstash and Beats can send their data to Elasticsearch Service. What is run is determined by the subscription level.

5. title=What Is The Difference Between Elasticsearch Service And The Amazon Elasticsearch Service 
score=0.9835054890793161 
content=Elasticsearch Service is the only hosted and managed Elasticsearch service built, managed, and supported by the company behind Elasticsearch, Kibana, Beats, and Logstash. With Elasticsearch Service, you always get the latest versions of the software. Our service is built on best practices and years of experience hosting and managing thousands of Elasticsearch clusters in the Cloud and on premise. For more information, check the following Amazon and Elastic Elasticsearch Service comparison page.
Please note that there is no formal partnership between Elastic and Amazon Web Services (AWS), and Elastic does not provide any support on the AWS Elasticsearch Service.

Fazit

Anhand von LlamaIndex haben wir demonstriert, wie man ein effizientes FAQ-Suchsystem mit Unterstützung für Elasticsearch als Vektordatenbank erstellt. Die Dokumente werden mithilfe von Einbettungen erfasst und indexiert, wodurch Vektorsuchen ermöglicht werden. Mithilfe einer PromptTemplate werden die Suchergebnisse in den Kontext eingebunden und an das LLM gesendet, das auf Basis der abgerufenen Dokumente präzise und kontextbezogene Antworten generiert.

Dieser Workflow integriert die Informationsabfrage mit der kontextbezogenen Antwortgenerierung, um genaue und relevante Ergebnisse zu liefern.

Referenzen

https://www.elastic.co/guide/en/cloud/current/ec-faq-getting-started.html

https://docs.llamaindex.ai/en/stable/api_reference/readers/elasticsearch/

https://docs.llamaindex.ai/en/stable/module_guides/indexing/vector_store_index/

https://docs.llamaindex.ai/en/stable/examples/query_engine/custom_query_engine/

https://www.elastic.co/search-labs/integrations/llama-index

Häufige Fragen

Was ist LlamaIndex?

LlamaIndex ist ein Framework, das die Erstellung von Agenten und Workflows erleichtert, die auf großen Sprachmodellen (LLMs) basieren und mit spezifischen oder privaten Daten interagieren.

Lässt sich LlamaIndex in Elasticsearch integrieren?

Ja, Elasticsearch kann mit LlamaIndex auf verschiedene Weise verwendet werden, unter anderem als Datenquelle (mithilfe des Elasticsearch Readers zum Extrahieren von Dokumenten), als Einbettungsmodell (Kodierung von Daten in Vektoren für semantische Suchen), als Vektorspeicher (Verwendung von Elasticsearch als Repository zum Durchsuchen vektorisierter Dokumente) und für die erweiterte Speicherung (Konfiguration von Strukturen wie Dokumentzusammenfassungen oder Wissensgraphen).

Zugehörige Inhalte

Anzeigen von Feldern in einem Elasticsearch-Index

Kofi Bartlett

Wie man Daten über Kafka in Elasticsearch einliest

Andre Luiz

Ruby-Skripting in Logstash

Dai Sugimori

Indexvorlagen in Elasticsearch: Wie man zusammensetzbare Vorlagen verwendet

Kofi Bartlett

Wie man Felder eines Elasticsearch-Index anzeigt

JD Armada

Sind Sie bereit, hochmoderne Sucherlebnisse zu schaffen?

Eine ausreichend fortgeschrittene Suche kann nicht durch die Bemühungen einer einzelnen Person erreicht werden. Elasticsearch wird von Datenwissenschaftlern, ML-Ops-Experten, Ingenieuren und vielen anderen unterstützt, die genauso leidenschaftlich an der Suche interessiert sind wie Sie. Lasst uns in Kontakt treten und zusammenarbeiten, um das magische Sucherlebnis zu schaffen, das Ihnen die gewünschten Ergebnisse liefert.

Probieren Sie es selbst aus