So richten Sie LangChain mit der VectorAI-Datenbank für On-Prem-RAG ein
Zusammenfassung
- Das Tutorial zeigt, wie man mit LangChain eine lokale RAG-Pipeline aufbaut, wobei VectorAI DB als Vektorspeicher dient.
- Dank der VectorStore-Abstraktion von LangChain können Teams Vektor-Backends austauschen, ohne die Abrufkette neu schreiben zu müssen.
- Entwickler können OpenAI-Embeddings verwenden oder mit HuggingFace-Embeddings und Ollama vollständig lokal arbeiten.
- Der Workflow umfasst die Einrichtung von Docker, die Aufteilung von Dokumenten in Blöcke, die Speicherung von Vektoren, die Ähnlichkeitssuche sowie eine vollständige RAG-Kette.
- Das Muster eignet sich für Anwendungsfälle in lokalen Umgebungen, Air-Gap-Umgebungen, am Netzwerkrand sowie bei der Datenlokalisierung, bei denen Vektorspeicher vom Typ „ Cloud “ nicht ideal sind.
LangChain’s VectorStore Durch die Abstraktion wird die Abrufkette von der Datenbank getrennt, in der Ihre Embeddings gespeichert sind. Das bedeutet, dass Sie einen gehosteten Vektorspeicher durch VectorAI DB ersetzen können, während die Struktur aus Retriever, Prompt und LLM weitgehend unverändert bleibt.
In diesem Tutorial wird diese Pipeline von Grund auf aufgebaut. Sie werden VectorAI DB lokal mit Docker ausführen, Dokumente laden und in Chunks aufteilen, Embeddings generieren, diese in einer lokalen Vektordatenbank speichern und den Speicher mit einer LangChain-RAG-Kette verbinden. Das Tutorial behandelt sowohl OpenAI- als auch lokale HuggingFace-Embeddings und zeigt, wie Sie das OpenAI-LLM durch Ollama ersetzen können, um eine vollständig lokale Pipeline zu erhalten.
Am Ende verfügen Sie über eine funktionsfähige RAG-Anwendung (Retrieval-Augmented Generation), die ohne eine „ Cloud “-Vektordatenbank läuft. Wenn Sie von Pinecone, einem gehosteten Qdrant-Dienst Deployment oder einem anderen verwalteten Vektorspeicher migrieren, ist der Umstieg weniger aufwendig, als es zunächst den Anschein haben mag. Hintergrundinformationen dazu, warum Entwickler von gehosteten Vektorspeichern auf lokale Alternativen umsteigen, finden Sie im Artikel „ eingebettet “ zum Vergleich von Vektordatenbanken.

Die Architektur der LangChain + VectorAI DB-Pipeline. Erfassungspfad (oben): Dokumente durchlaufen den Loader, den Textaufteiler und das Embedding-Modell und gelangen schließlich in die VectorAI DB. Abfragepfad (unten): Die Frage „ Nutzer “ wird als „ eingebettet “ an dasselbe Modell übermittelt, die VectorAI DB ruft die am besten passenden Chunks ab, und die Ergebnisse durchlaufen die Prompt-Vorlage und das LLM, um eine zitierte Antwort zu generieren.
Voraussetzungen.
Bitte überprüfen Sie vor dem Start Folgendes.
- Docker ist installiert und läuft.
- Python .10 oder höher.
- VectorAI DB Community Edition wird lokal ausgeführt. Falls Sie die Software noch nicht eingerichtet haben, befolgen Sie bitte die Anweisungen in der VectorAI DB-Installationsanleitung, bevor Sie fortfahren.
- Ollama wurde installiert mit
llama3.2gezogen. Ausführenollama pull llama3.2auf einem Computer mit Internetzugang.
So funktioniert die VectorStore-Schnittstelle von LangChain
LangChain’s VectorStore Die Basisklasse definiert eine Standardschnittstelle, die jedes konforme Backend implementiert. Die Schnittstelle umfasst vier Kernoperationen: from_documents() um in einem einzigen Aufruf einen Speicher anzulegen und Dokumente einzulesen, add_texts() um Inhalte zu einem bestehenden Shop hinzuzufügen, similarity_search() um die Dokumente abzurufen, die am nächsten an einem abfragen liegen, und as_retriever() um den Speicher in einen Abrufer für die Verwendung in einer LangChain Expression Language (LCEL)-Kette umzuwandeln.
Jedes kompatible Backend kann in den gemeinsamen LangChain-Abrufpfad eingebunden werden, wobei backendspezifische Funktionen wie Filtersyntax, Abstandsmetriken und hybride Suche weiterhin variieren. Was sich nicht ändert, ist die Abrufkette selbst. Der Retriever, die Prompt-Vorlage, das Large Language Model (LLM) und der Ausgabeparser bleiben unverändert, unabhängig davon, welches Backend die Vektoren speichert.
Das folgende Diagramm veranschaulicht dies. Der linke Teil zeigt eine Instanziierung des Vektorspeichers „ Cloud “. Der rechte Teil zeigt das entsprechende „VectorAI DB“-Äquivalent. Der Import in Zeile 1 sowie der Klassenname und die Verbindungsparameter in Zeile 7 ändern sich. Die Zeilen 8 bis 17 (die Dokumente, die Einbettung, der Retriever-Aufruf und die LCEL-Kette) sind auf beiden Seiten identisch.

Cloud Vector-Store-Instanziierung im direkten Vergleich zur VectorAI-DB-Instanziierung. Der Import und der Klassenname ändern sich. Die Kettenlogik in den Zeilen 15 bis 17 ist identisch.
Schritt 1: VectorAI DB starten
Führen Sie VectorAI DB als Docker-Container aus. Laden Sie das Image herunter und starten Sie es mit einem persistenten Volume:
docker pull actian/vectorai:latest
docker run -d --name vectorai \
-v ./local_data:/var/lib/actian-vectorai \
-p 6573-6575:6573-6575 \
-e ACTIAN_VECTORAI_ACCEPT_EULA=YES \
actian/vectorai:latest
Der Container stellt REST am Port 6573, gRPC am Port 6574 und eine lokale Web-Benutzeroberfläche am Port 6575 bereit. Die LangChain-Integration stellt eine Verbindung über gRPC her unter localhost:6574. Die Community Edition reicht für dieses Tutorial aus und unterstützt bis zu 5.000 gespeicherte Vektoren.
Überprüfen Sie, ob der Container ordnungsgemäß gestartet wurde:
docker logs vectorai
Das solltest du sehen Ready to accept connections... am Ende der Ausgabe, bevor Sie fortfahren.

Terminalausgabe des Verbindungstests, die die Version und den Status des VectorAI-DB-Servers bestätigt.
Schritt 2: Installieren Sie die Abhängigkeiten von „ Python “
Installieren Sie alle erforderlichen Pakete mit einem einzigen Befehl:
pip install langchain langchain-core langchain-text-splitters \
langchain-actian-vectorai langchain-openai \
langchain-huggingface langchain-ollama \
actian-vectorai-client sentence-transformers
LangChain hat seine Integrationen in eigenständige Pakete aufgeteilt. langchain-huggingface ersetzt die HuggingFace-Klassen, die zuvor in langchain-community, und langchain-ollama ersetzt die Ollama-Klassen. In diesem Tutorial werden durchgehend die aktuellen eigenständigen Pakete verwendet. Bei Verwendung der veralteten langchain-community Diese Pfade führen in neueren LangChain-Versionen zu Verwendungswarnungen.
Wenn Sie in Schritt 5 den OpenAI-Embedding-Pfad verwenden möchten, legen Sie Ihren API-Schlüssel fest, bevor Sie den Embedding-Code ausführen:
export OPENAI_API_KEY="your-api-key-here"
Schritt 3: Stellen Sie eine Verbindung zur VectorAI-Datenbank her von Python
Überprüfen Sie die Verbindung, bevor Sie Dokumente hochladen. Erstellen Sie eine Testsammlung, vergewissern Sie sich, dass sie in der Sammlungsliste angezeigt wird, und löschen Sie sie anschließend wieder. Dieser Prüfschritt stellt sicher, dass der Server sowohl Lese- als auch Schreibvorgänge akzeptiert, bevor Sie fortfahren.
from actian_vectorai import VectorAIClient, VectorParams, Distance
# Connect to VectorAI DB over gRPC.
client = VectorAIClient("localhost:6574")
client.connect()
# Create a test collection to confirm the server accepts writes.
client.collections.create(
"connection_test",
vectors_config=VectorParams(size=128, distance=Distance.Cosine),
)
# Confirm the collection was created.
collections = client.collections.list()
print(f"Collections: {collections}")
# Expected: ['connection_test']
# Remove the test collection before proceeding.
client.collections.delete("connection_test")
print("Connection verified. Ready to proceed.")
client.close()
Falls client.connect() löst ein ConnectionError, überprüfen Sie, ob der Docker-Container läuft, indem Sie docker ps und dass Port 6574 nicht von einem anderen Prozess blockiert wird.
Schritt 4: Dokumente laden und in Blöcke aufteilen
Verwenden Sie eine kleine Auswahl an Inline-Dokumenten, damit Sie für diesen Schritt keine externen Abhängigkeiten haben. Der Inhalt umfasst Konzepte der Vektordatenbank und von RAG, die in den Schritten 6 und 7 aussagekräftige Suchergebnisse liefern.
from langchain_core.documents import Document
from langchain_text_splitters import RecursiveCharacterTextSplitter
# Inline documents keep this tutorial self-contained.
# In a production pipeline, replace this with a document loader
# such as PyPDFLoader, DirectoryLoader, or a custom ingestion process.
raw_documents = [
Document(page_content="""A vector database stores high-dimensional numerical
representations of data called embeddings. Each embedding captures the semantic
meaning of the original content, allowing the database to find similar items by
comparing their positions in vector space rather than matching exact keywords.""",
metadata={"source": "intro", "topic": "vector-databases"}),
Document(page_content="""Retrieval-Augmented Generation combines a retrieval
system with a language model. The retrieval component finds relevant documents from
a vector store based on the user question, and the language model generates an answer
grounded in those retrieved documents rather than relying on its training data alone.""",
metadata={"source": "intro", "topic": "rag"}),
Document(page_content="""Embedding models convert text into fixed-length numerical
vectors. The choice of embedding model determines the vector dimension and the quality
of semantic similarity. OpenAI text-embedding-ada-002 produces 1536-dimensional vectors.
Sentence transformers such as all-MiniLM-L6-v2 produce 384-dimensional vectors and
run locally without an external API key.""",
metadata={"source": "intro", "topic": "embeddings"}),
Document(page_content="""Metadata filtering narrows the candidate set before
running similarity search. Attaching fields such as document type, date, or source
to each stored vector enables queries scoped to a specific subset of your collection
without changing the embedding or search logic.""",
metadata={"source": "intro", "topic": "filtering"}),
]
# RecursiveCharacterTextSplitter preserves sentence boundaries before splitting.
splitter = RecursiveCharacterTextSplitter(chunk_size=300, chunk_overlap=50)
docs = splitter.split_documents(raw_documents)
print(f"Produced {len(docs)} chunks from {len(raw_documents)} documents.")
Das metadata Feld auf jedem Document wird als Nutzdaten in der VectorAI-Datenbank gespeichert und steht zum Zeitpunkt der Suche für Filterungen zur Verfügung.

Terminalausgabe mit der Anzahl der aus den vier Inline-Dokumenten erzeugten Chunks.
Schritt 5: Dokumente unter „ einbetten “ speichern
Dies ist der Kern des Tutorials. Je nachdem, ob Sie über einen OpenAI-API-Schlüssel verfügen oder vollständig offline arbeiten müssen, stehen Ihnen zwei Vorgehensweisen zur Auswahl. Wählen Sie eine davon aus und wenden Sie diese in den Schritten 6 und 7 durchgehend an.
Für beide Vorgehensweisen gilt eine Einschränkung: Eine mit einem Embedding-Modell erstellte Sammlung kann keine Vektoren aus einem anderen Modell aufnehmen, da sich die Dimensionen unterscheiden. OpenAI-Embeddings sind 1536-dimensional. Das unten verwendete HuggingFace-Modell erzeugt 384-dimensionale Vektoren. Wenn Sie zwischen den Durchläufen das Embedding-Modell wechseln, übergeben Sie force_recreate=True um die Sammlung automatisch zu löschen und neu zu erstellen.
Pfad 1: OpenAI-Embeddings
from langchain_actian_vectorai import ActianVectorAIVectorStore
from langchain_openai import OpenAIEmbeddings
from actian_vectorai import VectorAIClient
store = ActianVectorAIVectorStore.from_documents(
documents=docs,
embedding=OpenAIEmbeddings(), # produces 1536-dim vectors
collection_name="rag_documents",
url="localhost:6574",
force_recreate=True,
)
print("Done.")
# Confirm vectors are stored and queryable.
client = VectorAIClient("localhost:6574")
client.connect()
print(f"Active collections: {client.collections.list()}")
test = store.similarity_search("vector database", k=1)
print(f"Test search returned {len(test)} result. Vectors are queryable.")
client.close()
from_documents() verwaltet die Verbindung zur VectorAI-Datenbank, erstellt die Sammlung und fügt die Vektoren in einem einzigen Aufruf ein. Dies ist der einzige Teil der Pipeline, der sich ändert, wenn Sie das Backend austauschen.
Pfad 2: Lokale HuggingFace-Embeddings. Verwenden Sie diesen Pfad, wenn die Pipeline ohne externe API-Aufrufe ausgeführt werden muss.
from langchain_actian_vectorai import ActianVectorAIVectorStore
from langchain_huggingface import HuggingFaceEmbeddings
from actian_vectorai import VectorAIClient
# all-MiniLM-L6-v2 produces 384-dim vectors and runs on CPU.
# Downloads ~90 MB on first use. Subsequent runs load from cache.
embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
store = ActianVectorAIVectorStore.from_documents(
documents=docs,
embedding=embeddings, # produces 384-dim vectors
collection_name="rag_documents",
url="localhost:6574",
force_recreate=True,
)
print("Done.")
# Confirm vectors are stored and queryable.
client = VectorAIClient("localhost:6574")
client.connect()
print(f"Active collections: {client.collections.list()}")
test = store.similarity_search("vector database", k=1)
print(f"Test search returned {len(test)} result. Vectors are queryable.")
client.close()
Für den erstmaligen Download des Modells ist eine Internetverbindung erforderlich. Sobald das Modell zwischengespeichert ist, läuft dieser Pfad vollständig offline.

Terminalausgabe von Pfad 2 (lokale HuggingFace-Embeddings), die bestätigt, dass die Sammlung erstellt wurde und die Vektoren abgefragt werden können.
Wenn Sie eine explizite Konfiguration der Sammlung benötigen. Das from_documents() Der Konstruktor leitet die Vektordimension aus dem Einbettungsmodell ab und erstellt die Sammlung automatisch. Wenn Sie direkte Kontrolle über Parameter wie die Abstandsmetrik benötigen, verwenden Sie VectorAIClient direkt und übergeben den Client an den Vektorspeicher:
from actian_vectorai import VectorAIClient, VectorParams, Distance
from langchain_actian_vectorai import ActianVectorAIVectorStore
from langchain_openai import OpenAIEmbeddings
client = VectorAIClient("localhost:6574")
client.connect()
client.collections.create(
"rag_documents",
vectors_config=VectorParams(size=1536, distance=Distance.Cosine),
)
store = ActianVectorAIVectorStore(
client=client,
collection_name="rag_documents",
embedding=OpenAIEmbeddings(),
)
Schritt 6: Abfrage im Vektorspeicher
Führen Sie eine Ähnlichkeitssuche in den gespeicherten Dokumenten durch. Der folgende Code stellt erneut eine Verbindung zur bestehenden Sammlung her, sodass er in einer neuen Sitzung unter Python reibungslos ausgeführt werden kann.
/,code>from langchain_actian_vectorai import ActianVectorAIVectorStore
from langchain_huggingface import HuggingFaceEmbeddings
from actian_vectorai import VectorAIClient
# Verwende dasselbe Einbettungsmodell, das bei der Datenaufnahme verwendet wurde.
embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
client = VectorAIClient("localhost:6574")
client.connect()
store = ActianVectorAIVectorStore(
client=client,
collection_name="rag_documents",
embedding=embeddings,
)
# Einfache Ähnlichkeitssuche: Gibt die k ähnlichsten Dokumente zurück.
results = store.similarity_search("Wie funktioniert RAG?", k=3)
for doc in results:
print(doc.page_content[:120])
print()
Um Dokumente mit ihren Rohwerten abzurufen, verwenden Sie similarity_search_with_score():
scored = store.similarity_search_with_score("How does RAG work?", k=3)
for doc, score in scored:
print(f"score={score:.4f} {doc.page_content[:100]}")
Wenn die Integration den Kosinus-Abstand zurückgibt, weisen niedrigere Werte auf eine größere Übereinstimmung hin. Verwenden Sie die Wertverteilung Ihrer eigenen Daten, um einen Schwellenwert festzulegen, anstatt von einem allgemeingültigen Grenzwert auszugehen:
# Example threshold. Tune this against your own evaluation data.
THRESHOLD = 0.3
confident_results = [
(doc, score) for doc, score in scored if score < THRESHOLD
]
Um die Werte auf einen Bereich von 0 bis 1 zu normieren, wobei höhere Werte eine größere Relevanz bedeuten, verwenden Sie similarity_search_with_relevance_scores():
relevance = store.similarity_search_with_relevance_scores("How does RAG work?", k=3)
for doc, score in relevance:
print(f"relevance={score:.3f} {doc.page_content[:100]}")

Terminalausgabe mit den Ergebnissen der Ähnlichkeitssuche, einschließlich der rohen Kosinuswerte und der normierten Relevanzwerte für drei Suchmethoden.
Schritt 7: Aufbau der RAG-Kette
Verbinden Sie den Retriever mit einem LLM und erstellen Sie mithilfe von LCEL eine vollständige Frage-Antwort-Kette. Beide Codeblöcke stellen zu Beginn erneut eine Verbindung zur VectorAI-Datenbank her, sodass sie in einer neuen Sitzung reibungslos ausgeführt werden.
Mit OpenAI
from langchain_actian_vectorai import ActianVectorAIVectorStore
from langchain_openai import OpenAIEmbeddings, ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
from actian_vectorai import VectorAIClient
embeddings = OpenAIEmbeddings()
client = VectorAIClient("localhost:6574")
client.connect()
store = ActianVectorAIVectorStore(
client=client,
collection_name="rag_documents",
embedding=embeddings,
)
retriever = store.as_retriever(search_type="similarity", search_kwargs={"k": 3})
# For diverse results that cover different aspects of the query,
# use Max Marginal Relevance search instead:
# retriever = store.as_retriever(
# search_type="mmr",
# search_kwargs={"k": 4, "fetch_k": 20, "lambda_mult": 0.5},
# )
prompt = ChatPromptTemplate.from_template("""Answer the question using only the
context below. If the context does not contain enough information to answer,
say so.
Context:
{context}
Question: {question}
Answer:""")
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
chain = (
{"context": retriever, "question": RunnablePassthrough()}
| prompt
| llm
| StrOutputParser()
)
query = "What is Retrieval-Augmented Generation and how does it work?"
print(f"Query: {query}")
print()
answer = chain.invoke(query)
print(f"Answer: {answer}")
Ersetzen Sie das LLM durch Ollama, um eine vollständig lokale Pipeline zu erhalten:
from langchain_actian_vectorai import ActianVectorAIVectorStore
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_ollama import OllamaLLM
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
from actian_vectorai import VectorAIClient
embeddings = HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
client = VectorAIClient("localhost:6574")
client.connect()
store = ActianVectorAIVectorStore(
client=client,
collection_name="rag_documents",
embedding=embeddings,
)
retriever = store.as_retriever(search_type="similarity", search_kwargs={"k": 3})
prompt = ChatPromptTemplate.from_template("""Answer the question using only the
context below. If the context does not contain enough information to answer,
say so.
Context:
{context}
Question: {question}
Answer:""")
# Run `ollama pull llama3.2` before using this path.
# llama3.2 requires approximately 2 GB of available RAM.
# If you see an out-of-memory error, use llama3.2:1b (~700 MB) instead.
llm = OllamaLLM(model="llama3.2")
chain = (
{"context": retriever, "question": RunnablePassthrough()}
| prompt
| llm
| StrOutputParser()
)
query = "What is Retrieval-Augmented Generation and how does it work?"
print(f"Query: {query}")
print()
answer = chain.invoke(query)
print(f"Answer: {answer}")
Die Antwort stammt direkt aus den gespeicherten Dokumenten und nicht aus den „ Training “-Daten des Modells. Der Retriever hat den relevanten Ausschnitt abgerufen, die Eingabeaufforderung hat ihn als Kontext weitergegeben, und das LLM hat eine Antwort generiert, die auf diesem Material basiert. Der OpenAI-Ansatz erzeugt dieselbe Struktur mit denselben „ abfragen “-Daten.
Die LCEL-Kettenstruktur ist auf beiden Pfaden identisch. Nur die LLM-Instanziierung ändert sich. Dies entspricht dem gleichen Prinzip wie der Vektorspeicher-Swap in Schritt 5. Durch diese Abstraktion wird die Kettenlogik von der Komponente getrennt, die die eigentliche Arbeit erledigt.

Terminalausgabe des Ollama-Pfads, die den Befehl „ abfragen “ und die aus den gespeicherten Dokumenten abgerufene Antwort „grounded“ zeigt. Der OpenAI-Pfad erzeugt eine entsprechende Ausgabe, wobei anstelle von OllamaLLM „ChatOpenAI“ verwendet wird.
Wann sollte man dieses Muster verwenden und wann sollte man sich anderweitig umsehen?
Dieses Modell eignet sich für „ On-Premises “-Server und private „ Cloud “-Bereitstellungen, Air-Gapped-Netzwerke, in denen Dokumente das Netzwerk nicht verlassen dürfen, Compliance-Umgebungen mit Anforderungen an den Datenaufbewahrungsort, Edge-Geräte, bei denen ein schlanker lokaler Vektorspeicher einer Abhängigkeit von „ Cloud “ vorzuziehen ist, sowie kostensensible Bereitstellungen, bei denen Gebühren für den Datenausgang bei „ Cloud “-Vektordatenbanken ein Thema sind.
Ziehen Sie in solchen Situationen einen anderen Ansatz in Betracht. Bei Vektor-Workloads mit weniger als 1 Million Einträgen in einem Team, das bereits Postgres einsetzt, ist die Nutzung von pgvector auf der bestehenden Datenbank einfacher zu handhaben als ein zusätzlicher Container. Bei serverlosen Funktionen mit strengen Anforderungen an den Kaltstart verursacht die Startzeit des Containers eine Latenz, die möglicherweise nicht akzeptabel ist. Für Teams, die keine Kontrolle über ihre eigene Infrastruktur haben, entlastet ein verwalteter Vektorspeicher sie von dem Betriebsaufwand, den dieses Muster mit sich bringt.
Zum Abschluss
Sie haben eine RAG-Pipeline auf Basis eines lokalen Vektorspeichers aufgebaut. Das LLM, die Prompt-Vorlage, der Retriever und der Output-Parser sind dieselben, die auch ein gehostetes Backend verwenden würde. Darin liegt der praktische Nutzen von LangChain: VectorStore Zusammenfassung: Das Austauschen von Backends wirkt sich auf den Instanziierungsaufruf aus, nicht auf die Kette.
Die Entscheidungsregel für die Zukunft ist einfach: Wenn Ihr „ Workload “ innerhalb der Obergrenze von 5.000 Vektoren der Community Edition liegt, reicht der hier beschriebene lokale Ansatz aus. Wenn er darüber hinauswächst oder Funktionen wie Hybrid-Suche oder Multi-Tenancy benötigt, lassen sich sowohl die kostenpflichtige Stufe von VectorAI DB als auch das umfassendere Integrations-Ökosystem von LangChain unabhängig voneinander skalieren.
Informationen zu einem Backend mit persistenter Agentenspeicherung finden Sie unter „Verwendung von VectorAI DB als Backend mit persistenter Speicherung für CrewAI-Agenten“. Informationen zu einer RAG-Pipeline, die auf Hardware mit begrenzten Ressourcen ausgeführt wird, finden Sie unter „Ausführung von Gemma 4 auf Edge-Hardware mit VectorAI DB“.