Verwenden von Ollama mit der Inference-API
Erfahren Sie, wie Sie Ollama mithilfe der Inference API in Elasticsearch integrieren.
In diesem Artikel erfahren Sie, wie Sie lokale Modelle mithilfe von Ollama mit dem Elasticsearch-Inferenzmodell verbinden und Ihren Dokumenten dann mithilfe von Playground Fragen stellen.
Elasticsearch ermöglicht Benutzern die Verbindung mit LLMs über die Open Inference API und unterstützt Anbieter wie Amazon Bedrock, Cohere, Google AI, Azure AI Studio, HuggingFace – als Service und andere.
Ollama ist ein Tool, mit dem Sie LLM-Modelle mithilfe Ihrer eigenen Infrastruktur (Ihrem lokalen Computer/Server) herunterladen und ausführen können. Hier finden Sie eine Liste der verfügbaren Modelle, die mit Ollama kompatibel sind.
Ollama ist eine großartige Option, wenn Sie verschiedene Open-Source-Modelle hosten und testen möchten, ohne sich Gedanken über die unterschiedlichen Einrichtungsmöglichkeiten der einzelnen Modelle oder über die Erstellung einer API für den Zugriff auf die Modellfunktionen machen zu müssen, da Ollama sich um alles kümmert.
Da die Ollama-API mit der OpenAI-API kompatibel ist, können wir das Inferenzmodell problemlos integrieren und mit Playground eine RAG-Anwendung erstellen.
Voraussetzungen
Elasticsearch 8.17
Kibana 8.17
Python
Schritte
Einrichten des Ollama LLM-Servers
Wir werden einen LLM-Server einrichten, um ihn mithilfe von Ollama mit unserer Playground-Instanz zu verbinden. Wir müssen:
Laden Sie Ollama herunter und führen Sie es aus.
Verwenden Sie ngrok, um über das Internet auf Ihren lokalen Webserver zuzugreifen, der Ollama hostet
Laden Sie Ollama herunter und führen Sie es aus
Um Ollama zu verwenden, müssen wir es zuerst herunterladen. Ollama bietet Unterstützung für Linux, Windows und macOS. Laden Sie hier einfach die mit Ihrem Betriebssystem kompatible Ollama-Version herunter. Sobald Ollama installiert ist, können wir aus dieser Liste unterstützter LLMs ein Modell auswählen. In diesem Beispiel verwenden wir das Modell llama3.2, ein allgemeines mehrsprachiges Modell. Im Setup-Prozess aktivieren Sie das Befehlszeilentool für Ollama. Sobald das heruntergeladen ist, können Sie die folgende Zeile ausführen:
ollama pull llama3.2Das Ergebnis lautet:
pulling manifest
pulling dde5aa3fc5ff... 100% ▕█████████████████████████████████████████████████████████████████████████████████████████▏ 2.0 GB
pulling 966de95ca8a6... 100% ▕█████████████████████████████████████████████████████████████████████████████████████████▏ 1.4 KB
pulling fcc5a6bec9da... 100% ▕█████████████████████████████████████████████████████████████████████████████████████████▏ 7.7 KB
pulling a70ff7e570d9... 100% ▕█████████████████████████████████████████████████████████████████████████████████████████▏ 6.0 KB
pulling 56bb8bd477a5... 100% ▕█████████████████████████████████████████████████████████████████████████████████████████▏ 96 B
pulling 34bb5ab01051... 100% ▕█████████████████████████████████████████████████████████████████████████████████████████▏ 561 B
verifying sha256 digest
writing manifest
successNach der Installation können Sie es mit diesem Befehl testen:
ollama run llama3.2Stellen wir eine Frage:

Wenn das Modell ausgeführt wird, aktiviert Ollama eine API, die standardmäßig auf Port „11434“ ausgeführt wird. Lassen Sie uns eine Anfrage an diese API stellen und dabei der offiziellen Dokumentation folgen:
curl http://localhost:11434/api/generate -d '{
"model": "llama3.2",
"prompt": "What is the capital of France?"
}'Dies ist die Antwort, die wir erhalten haben:
{"model":"llama3.2","created_at":"2024-11-28T21:48:42.152817532Z","response":"The","done":false}
{"model":"llama3.2","created_at":"2024-11-28T21:48:42.251884485Z","response":" capital","done":false}
{"model":"llama3.2","created_at":"2024-11-28T21:48:42.347365913Z","response":" of","done":false}
{"model":"llama3.2","created_at":"2024-11-28T21:48:42.446837322Z","response":" France","done":false}
{"model":"llama3.2","created_at":"2024-11-28T21:48:42.542367394Z","response":" is","done":false}
{"model":"llama3.2","created_at":"2024-11-28T21:48:42.644580384Z","response":" Paris","done":false}
{"model":"llama3.2","created_at":"2024-11-28T21:48:42.739865362Z","response":".","done":false}
{"model":"llama3.2","created_at":"2024-11-28T21:48:42.834347518Z","response":"","done":true,"done_reason":"stop","context":[128006,9125,128007,271,38766,1303,33025,2696,25,6790,220,2366,18,271,128009,128006,882,128007,271,3923,374,279,6864,315,9822,30,128009,128006,78191,128007,271,791,6864,315,9822,374,12366,13],"total_duration":6948567145,"load_duration":4386106503,"prompt_eval_count":32,"prompt_eval_duration":1872000000,"eval_count":8,"eval_duration":684000000}Beachten Sie, dass die spezifische Antwort für diesen Endpunkt ein Streaming ist.
Endpunkt mit ngrok dem Internet aussetzen
Da unser Endpunkt in einer lokalen Umgebung arbeitet, kann von einem anderen Punkt – wie unserer Elastic Cloud-Instanz – nicht über das Internet darauf zugegriffen werden. ngrok ermöglicht es uns, einen Port mit einer öffentlichen IP freizugeben. Erstellen Sie ein Konto in ngrok und folgen Sie der offiziellen Einrichtungsanleitung.
Sobald der ngrok-Agent installiert und konfiguriert wurde, können wir den von Ollama verwendeten Port verfügbar machen:
ngrok http 11434 --host-header="localhost:11434"Hinweis: Der Header --host-header="localhost:11434" garantiert, dass der Header „Host“ in den Anfragen mit „localhost:11434“ übereinstimmt.
Durch Ausführen dieses Befehls wird ein öffentlicher Link zurückgegeben, der funktioniert, solange ngrok und der Ollama-Server lokal ausgeführt werden.
Session Status online
Account xxxx@yourEmailProvider.com (Plan: Free)
Version 3.18.4
Region United States (us)
Latency 561ms
Web Interface http://127.0.0.1:4040
Forwarding https://your-ngrok-url.ngrok-free.app -> http://localhost:11434
Connections ttl opn rt1 rt5 p50 p90
0 0 0.00 0.00 0.00 0.00 ```Unter „Weiterleitung“ können wir sehen, dass ngrok eine URL generiert hat. Speichern Sie es für später.
Versuchen wir erneut, eine HTTP-Anfrage an den Endpunkt zu senden, diesmal unter Verwendung der von ngrok generierten URL:
curl https://your-ngrok-endpoint.ngrok-free.app/api/generate -d '{
"model": "llama3.2",
"prompt": "What is the capital of France?"
}'Die Antwort sollte der vorherigen ähnlich sein.
Erstellen von Zuordnungen
ELSER-Endpunkt
Für dieses Beispiel erstellen wir einen Inferenzendpunkt mithilfe der Elasticsearch-Inferenz-API. Zusätzlich verwenden wir ELSER , um die Einbettungen zu generieren.
PUT _inference/sparse_embedding/medicines-inference
{
"service": "elasticsearch",
"service_settings": {
"num_allocations": 1,
"num_threads": 1,
"model_id": ".elser_model_2_linux-x86_64"
}
}Stellen wir uns für dieses Beispiel vor, Sie haben eine Apotheke, die zwei Arten von Medikamenten verkauft:
Medikamente, für die ein Rezept erforderlich ist.
Medikamente, für die KEIN Rezept erforderlich ist.
Diese Informationen würden in das Beschreibungsfeld jedes Medikaments aufgenommen.
Das LLM muss dieses Feld interpretieren, daher verwenden wir folgende Datenzuordnungen:
PUT medicines
{
"mappings": {
"properties": {
"name": {
"type": "text",
"copy_to": "semantic_field"
},
"semantic_field": {
"type": "semantic_text",
"inference_id": "medicines-inference"
},
"text_description": {
"type": "text",
"copy_to": "semantic_field"
}
}
}
}Das Feld text_description speichert den Klartext der Beschreibungen, während semantic_field, ein Feldtyp vom Typ „semantic_text“ , die von ELSER generierten Einbettungen speichert.
Die Eigenschaft copy_to kopiert den Inhalt aus den Feldern name und text_description in das semantische Feld, sodass die Einbettungen für diese Felder generiert werden.
Indizierung von Daten
Lassen Sie uns nun die Daten mithilfe der _bulk-API indizieren.
POST _bulk
{"index":{"_index":"medicines"}}
{"id":1,"name":"Paracetamol","text_description":"An analgesic and antipyretic that does NOT require a prescription."}
{"index":{"_index":"medicines"}}
{"id":2,"name":"Ibuprofen","text_description":"A nonsteroidal anti-inflammatory drug (NSAID) available WITHOUT a prescription."}
{"index":{"_index":"medicines"}}
{"id":3,"name":"Amoxicillin","text_description":"An antibiotic that requires a prescription."}
{"index":{"_index":"medicines"}}
{"id":4,"name":"Lorazepam","text_description":"An anxiolytic medication that strictly requires a prescription."}
{"index":{"_index":"medicines"}}
{"id":5,"name":"Omeprazole","text_description":"A medication for stomach acidity that does NOT require a prescription."}
{"index":{"_index":"medicines"}}
{"id":6,"name":"Insulin","text_description":"A hormone used in diabetes treatment that requires a prescription."}
{"index":{"_index":"medicines"}}
{"id":7,"name":"Cold Medicine","text_description":"A compound formula to relieve flu symptoms available WITHOUT a prescription."}
{"index":{"_index":"medicines"}}
{"id":8,"name":"Clonazepam","text_description":"An antiepileptic medication that requires a prescription."}
{"index":{"_index":"medicines"}}
{"id":9,"name":"Vitamin C","text_description":"A dietary supplement that does NOT require a prescription."}
{"index":{"_index":"medicines"}}
{"id":10,"name":"Metformin","text_description":"A medication used for type 2 diabetes that requires a prescription."}Abwehr:
{
"errors": false,
"took": 34732020848,
"items": [
{
"index": {
"_index": "medicines",
"_id": "mYoeMpQBF7lnCNFTfdn2",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 2,
"failed": 0
},
"_seq_no": 0,
"_primary_term": 1,
"status": 201
}
},
{
"index": {
"_index": "medicines",
"_id": "mooeMpQBF7lnCNFTfdn2",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 2,
"failed": 0
},
"_seq_no": 1,
"_primary_term": 1,
"status": 201
}
},
{
"index": {
"_index": "medicines",
"_id": "m4oeMpQBF7lnCNFTfdn2",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 2,
"failed": 0
},
"_seq_no": 2,
"_primary_term": 1,
"status": 201
}
},
{
"index": {
"_index": "medicines",
"_id": "nIoeMpQBF7lnCNFTfdn2",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 2,
"failed": 0
},
"_seq_no": 3,
"_primary_term": 1,
"status": 201
}
},
{
"index": {
"_index": "medicines",
"_id": "nYoeMpQBF7lnCNFTfdn2",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 2,
"failed": 0
},
"_seq_no": 4,
"_primary_term": 1,
"status": 201
}
},
{
"index": {
"_index": "medicines",
"_id": "nooeMpQBF7lnCNFTfdn2",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 2,
"failed": 0
},
"_seq_no": 5,
"_primary_term": 1,
"status": 201
}
},
{
"index": {
"_index": "medicines",
"_id": "n4oeMpQBF7lnCNFTfdn2",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 2,
"failed": 0
},
"_seq_no": 6,
"_primary_term": 1,
"status": 201
}
},
{
"index": {
"_index": "medicines",
"_id": "oIoeMpQBF7lnCNFTfdn2",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 2,
"failed": 0
},
"_seq_no": 7,
"_primary_term": 1,
"status": 201
}
},
{
"index": {
"_index": "medicines",
"_id": "oYoeMpQBF7lnCNFTfdn2",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 2,
"failed": 0
},
"_seq_no": 8,
"_primary_term": 1,
"status": 201
}
},
{
"index": {
"_index": "medicines",
"_id": "oooeMpQBF7lnCNFTfdn2",
"_version": 1,
"result": "created",
"_shards": {
"total": 2,
"successful": 2,
"failed": 0
},
"_seq_no": 9,
"_primary_term": 1,
"status": 201
}
}
]
}Fragen stellen mit Playground
Playground ist ein Kibana-Tool, mit dem Sie mithilfe von Elasticsearch-Indizes und einem LLM-Anbieter schnell ein RAG-System erstellen können. Sie können diesen Artikel lesen, um mehr darüber zu erfahren.
Verbinden des lokalen LLM mit Playground
Wir müssen zunächst einen Connector erstellen, der die soeben erstellte öffentliche URL verwendet. Gehen Sie in Kibana zu „Suchen > Playground“ und klicken Sie dann auf „Mit einem LLM verbinden“.

Durch diese Aktion wird auf der linken Seite der Kibana-Oberfläche ein Menü angezeigt. Klicken Sie dort auf „OpenAI“.

Wir können jetzt mit der Konfiguration des OpenAI-Connectors beginnen.
Gehen Sie zu „Connector-Einstellungen“ und wählen Sie für den OpenAI-Anbieter „Andere (OpenAI-kompatible Dienste)“ aus:

Nun konfigurieren wir die übrigen Felder. In diesem Beispiel nennen wir unser Modell "medicines-llm". Verwenden Sie im URL-Feld die von ngrok generierte URL (/v1/chat/completions). Wählen Sie im Feld „Standardmodell“ die Option „llama3.2“ aus. Wir benötigen keinen API-Schlüssel, geben Sie einfach einen beliebigen Text ein, um fortzufahren:

Klicken Sie auf „Speichern“ und fügen Sie die Indexmedikamente hinzu, indem Sie auf „Datenquellen hinzufügen“ klicken:


Großartig! Wir haben jetzt Zugriff auf Playground mithilfe des LLM, das wir lokal als RAG-Engine ausführen.

Bevor wir es testen, fügen wir dem Agenten spezifischere Anweisungen hinzu und erhöhen die Anzahl der an das Modell gesendeten Dokumente auf 10, damit die Antwort möglichst viele Dokumente enthält. Das Kontextfeld ist semantic_field und enthält dank der Eigenschaft „copy_to“ den Namen und die Beschreibung der Medikamente.

Stellen wir nun die Frage: Kann ich Clonazepam ohne Rezept kaufen? und sehen Sie, was passiert:

Wie erwartet haben wir die richtige Antwort erhalten.
Wie geht es weiter?
Der nächste Schritt besteht darin, Ihre eigene Anwendung zu erstellen! Playground bietet ein Code-Skript in Python, das Sie auf Ihrem Computer ausführen und an Ihre Anforderungen anpassen können. Beispielsweise indem Sie es hinter einen FastAPI -Server stellen, um einen QA-Medizin-Chatbot zu erstellen, der von Ihrer Benutzeroberfläche genutzt wird.
Sie finden diesen Code, indem Sie oben rechts im Playground auf die Schaltfläche „Code anzeigen“ klicken:

Und Sie verwenden die Endpunkte und API-Schlüssel, um die im Code erforderliche Umgebungsvariable ES_API_KEY zu generieren.
Für dieses spezielle Beispiel lautet der Code wie folgt:
## Install the required packages
## pip install -qU elasticsearch openai
import os
from elasticsearch import Elasticsearch
from openai import OpenAI
es_client = Elasticsearch(
"https://your-deployment.us-central1.gcp.cloud.es.io:443",
api_key=os.environ["ES_API_KEY"]
)
openai_client = OpenAI(
api_key=os.environ["OPENAI_API_KEY"],
)
index_source_fields = {
"medicines": [
"semantic_field"
]
}
def get_elasticsearch_results():
es_query = {
"retriever": {
"standard": {
"query": {
"nested": {
"path": "semantic_field.inference.chunks",
"query": {
"sparse_vector": {
"inference_id": "medicines-inference",
"field": "semantic_field.inference.chunks.embeddings",
"query": query
}
},
"inner_hits": {
"size": 2,
"name": "medicines.semantic_field",
"_source": [
"semantic_field.inference.chunks.text"
]
}
}
}
}
},
"size": 3
}
result = es_client.search(index="medicines", body=es_query)
return result["hits"]["hits"]
def create_openai_prompt(results):
context = ""
for hit in results:
inner_hit_path = f"{hit['_index']}.{index_source_fields.get(hit['_index'])[0]}"
## For semantic_text matches, we need to extract the text from the inner_hits
if 'inner_hits' in hit and inner_hit_path in hit['inner_hits']:
context += '\n --- \n'.join(inner_hit['_source']['text'] for inner_hit in hit['inner_hits'][inner_hit_path]['hits']['hits'])
else:
source_field = index_source_fields.get(hit["_index"])[0]
hit_context = hit["_source"][source_field]
context += f"{hit_context}\n"
prompt = f"""
Instructions:
- You are an assistant specializing in answering questions about the sale of medicines.
- Answer questions truthfully and factually using only the context presented.
- If you don't know the answer, just say that you don't know, don't make up an answer.
- You must always cite the document where the answer was extracted using inline academic citation style [], using the position.
- Use markdown format for code examples.
- You are correct, factual, precise, and reliable.
Context:
{context}
"""
return prompt
def generate_openai_completion(user_prompt, question):
response = openai_client.chat.completions.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": user_prompt},
{"role": "user", "content": question},
]
)
return response.choices[0].message.content
if __name__ == "__main__":
question = "my question"
elasticsearch_results = get_elasticsearch_results()
context_prompt = create_openai_prompt(elasticsearch_results)
openai_completion = generate_openai_completion(context_prompt, question)
print(openai_completion)Damit es mit Ollama funktioniert, müssen Sie den OpenAI-Client so ändern, dass er eine Verbindung zum Ollama-Server statt zum OpenAI-Server herstellt. Die vollständige Liste der OpenAI-Beispiele und kompatiblen Endpunkte finden Sie hier.
openai_client = OpenAI(
# you can use http://localhost:11434/v1/ if running this code locally.
base_url='https://your-ngrok-url.ngrok-free.app/v1/',
# required but ignored
api_key='ollama',
)Und ändern Sie das Modell auch in llama3.2, wenn Sie die Vervollständigungsmethode aufrufen:
def generate_openai_completion(user_prompt, question):
response = openai_client.chat.completions.create(
model="llama3.2",
messages=[
{"role": "system", "content": user_prompt},
{"role": "user", "content": question},
]
)
return response.choices[0].message.contentFügen wir unsere Frage hinzu: Kann ich Clonazepam ohne Rezept kaufen? Zur Elasticsearch-Abfrage:
def get_elasticsearch_results():
es_query = {
"retriever": {
"standard": {
"query": {
"nested": {
"path": "semantic_field.inference.chunks",
"query": {
"sparse_vector": {
"inference_id": "medicines-inference",
"field": "semantic_field.inference.chunks.embeddings",
"query": "Can I buy Clonazepam without a prescription?"
}
},
"inner_hits": {
"size": 2,
"name": "medicines.semantic_field",
"_source": [
"semantic_field.inference.chunks.text"
]
}
}
}
}
},
"size": 3
}
result = es_client.search(index="medicines", body=es_query)
return result["hits"]["hits"]Und auch zum Abschlussaufruf mit einigen Ausdrucken, damit wir bestätigen können, dass wir die Elasticsearch-Ergebnisse als Teil des Fragenkontexts senden:
if __name__ == "__main__":
question = "Can I buy Clonazepam without a prescription?"
elasticsearch_results = get_elasticsearch_results()
context_prompt = create_openai_prompt(elasticsearch_results)
print("========== Context Prompt START ==========")
print(context_prompt)
print("========== Context Prompt END ==========")
print("========== Ollama Completion START ==========")
openai_completion = generate_openai_completion(context_prompt, question)
print(openai_completion)
print("========== Ollama Completion END ==========")Lassen Sie uns nun den Befehl ausführen
pip install -qU elasticsearch openai
python main.py
Sie sollten ungefähr Folgendes sehen:
========== Context Prompt START ==========
Instructions:
- You are an assistant specializing in answering questions about the sale of medicines.
- Answer questions truthfully and factually using only the context presented.
- If you don't know the answer, just say that you don't know, don't make up an answer.
- You must always cite the document where the answer was extracted using inline academic citation style [], using the position.
- Use markdown format for code examples.
- You are correct, factual, precise, and reliable.
Context:
Clonazepam
---
An antiepileptic medication that requires a prescription.A nonsteroidal anti-inflammatory drug (NSAID) available WITHOUT a prescription.
---
IbuprofenAn anxiolytic medication that strictly requires a prescription.
---
Lorazepam
========== Context Prompt END ==========
========== Ollama Completion START ==========
No, you cannot buy Clonazepam over-the-counter (OTC) without a prescription [1]. It is classified as a controlled substance in the United States due to its potential for dependence and abuse. Therefore, it can only be obtained from a licensed healthcare provider who will issue a prescription for this medication.
========== Ollama Completion END ==========Fazit
In diesem Artikel können wir die Leistungsfähigkeit und Vielseitigkeit von Tools wie Ollama sehen, wenn wir sie zusammen mit der Elasticsearch-Inferenz-API und Playground verwenden.
Nach einigen einfachen Schritten hatten wir eine funktionierende RAG-Anwendung mit einem Chat, der ein LLM verwendete, das kostenlos in unserer eigenen Infrastruktur lief. Dies ermöglicht uns außerdem eine bessere Kontrolle über Ressourcen und vertrauliche Informationen und gibt uns außerdem Zugriff auf eine Vielzahl von Modellen für unterschiedliche Aufgaben.
Wie man Ollama mit der Elastic Inference API verwendet
Mit Ollama und der Elastic Inference API eine RAG-App mit Playground erstellen
1.
Ollama LLM-Server einrichten
2.
Zuordnungen erstellen
3.
Index-Daten
4.
Stellen Sie Ihre Fragen über den Spielplatz.
Häufige Fragen
Was ist Ollama?
Ollama ist ein Tool, mit dem Sie LLM-Modelle mithilfe Ihrer eigenen Infrastruktur (Ihres lokalen Rechners/Servers) herunterladen und ausführen können.
