Milvus als LangChain-Vektorspeicher verwenden

Dieses Notizbuch zeigt, wie man die Funktionalität des Milvus als LangChain-Vektorspeicher nutzen kann.

Einrichtung von

Sie müssen langchain-milvus und andere notwendige Abhängigkeiten installieren.

$ pip install -qU langchain-milvus milvus-lite langchain-openai

Die neueste Version von pymilvus kommt mit einer lokalen Vektordatenbank Milvus Lite, die sich gut für Prototypen eignet. Wenn Sie große Datenmengen haben, z. B. mehr als eine Million Dokumente, empfehlen wir, einen leistungsfähigeren Milvus-Server auf Docker oder Kubernetes einzurichten.

Initialisierung

from langchain_openai import OpenAIEmbeddings

embeddings = OpenAIEmbeddings(model="text-embedding-3-large")
from langchain_milvus import Milvus

# The easiest way is to use Milvus Lite where everything is stored in a local file.
# If you have a Milvus server you can use the server URI such as "http://localhost:19530".
URI = "./milvus_example.db"

vector_store = Milvus(
    embedding_function=embeddings,
    connection_args={"uri": URI},
)

Kompartimentierung der Daten mit Milvus Collections

Sie können verschiedene, nicht zusammenhängende Dokumente in verschiedenen Sammlungen innerhalb derselben Milvus-Instanz speichern, um den Kontext zu erhalten

Hier sehen Sie, wie Sie eine neue Vektorspeichersammlung aus Dokumenten erstellen können:

from langchain_core.documents import Document

vector_store_saved = Milvus.from_documents(
    [Document(page_content="foo!")],
    embeddings,
    collection_name="langchain_example",
    connection_args={"uri": URI},
)

Und hier sehen Sie, wie Sie diese gespeicherte Sammlung abrufen

vector_store_loaded = Milvus(
    embeddings,
    connection_args={"uri": URI},
    collection_name="langchain_example",
)

Verwalten des Vektorspeichers

Sobald Sie Ihren Vektorspeicher erstellt haben, können wir mit ihm interagieren, indem wir verschiedene Elemente hinzufügen und löschen.

Elemente zum Vektorspeicher hinzufügen

Mit der Funktion add_documents können wir Elemente zu unserem Vektorspeicher hinzufügen.

from uuid import uuid4

from langchain_core.documents import Document

document_1 = Document(
    page_content="I had chocalate chip pancakes and scrambled eggs for breakfast this morning.",
    metadata={"source": "tweet"},
)

document_2 = Document(
    page_content="The weather forecast for tomorrow is cloudy and overcast, with a high of 62 degrees.",
    metadata={"source": "news"},
)

document_3 = Document(
    page_content="Building an exciting new project with LangChain - come check it out!",
    metadata={"source": "tweet"},
)

document_4 = Document(
    page_content="Robbers broke into the city bank and stole $1 million in cash.",
    metadata={"source": "news"},
)

document_5 = Document(
    page_content="Wow! That was an amazing movie. I can't wait to see it again.",
    metadata={"source": "tweet"},
)

document_6 = Document(
    page_content="Is the new iPhone worth the price? Read this review to find out.",
    metadata={"source": "website"},
)

document_7 = Document(
    page_content="The top 10 soccer players in the world right now.",
    metadata={"source": "website"},
)

document_8 = Document(
    page_content="LangGraph is the best framework for building stateful, agentic applications!",
    metadata={"source": "tweet"},
)

document_9 = Document(
    page_content="The stock market is down 500 points today due to fears of a recession.",
    metadata={"source": "news"},
)

document_10 = Document(
    page_content="I have a bad feeling I am going to get deleted :(",
    metadata={"source": "tweet"},
)

documents = [
    document_1,
    document_2,
    document_3,
    document_4,
    document_5,
    document_6,
    document_7,
    document_8,
    document_9,
    document_10,
]
uuids = [str(uuid4()) for _ in range(len(documents))]

vector_store.add_documents(documents=documents, ids=uuids)
['31915e2d-55fd-4bfb-ae08-d441252b8e08',
 'dbf6560a-1487-4a6e-8797-245d57874f5b',
 'e991a253-5f37-46ae-850a-82a660e33013',
 '2818c051-5a1a-44cb-9deb-aaaac709f616',
 '91c7ef07-26d1-4319-b48c-9261df9ce8d7',
 'fb258085-6400-4cd7-aa92-fc5e32ca243e',
 'ffea9a9f-460d-4d8d-ba07-c45e9cfa1e33',
 'eb149e29-239a-4e2c-9f99-751cb7207abf',
 '119d4a42-fd6b-433d-842b-1e0be5df81e5',
 '5b099eb0-98fe-40a3-b13a-300c10250960']

Elemente aus dem Vektorspeicher löschen

vector_store.delete(ids=[uuids[-1]])
True

Abfrage des Vektorspeichers

Sobald Ihr Vektorspeicher erstellt wurde und die relevanten Dokumente hinzugefügt wurden, werden Sie ihn wahrscheinlich während der Ausführung Ihrer Kette oder Ihres Agenten abfragen wollen.

Direkt abfragen

Eine einfache Ähnlichkeitssuche mit Filterung nach Metadaten kann wie folgt durchgeführt werden:

results = vector_store.similarity_search(
    "LangChain provides abstractions to make working with LLMs easy",
    k=2,
    expr='source == "tweet"',
    # param=...  # Search params for the index type
)
for res in results:
    print(f"* {res.page_content} [{res.metadata}]")
WARNING: All log messages before absl::InitializeLog() is called are written to STDERR
I0000 00:00:1761298048.354308 7886403 fork_posix.cc:71] Other threads are currently calling into gRPC, skipping fork() handlers


* Building an exciting new project with LangChain - come check it out! [{'source': 'tweet', 'pk': 'e991a253-5f37-46ae-850a-82a660e33013'}]
* LangGraph is the best framework for building stateful, agentic applications! [{'source': 'tweet', 'pk': 'eb149e29-239a-4e2c-9f99-751cb7207abf'}]

Ähnlichkeitssuche mit Punktzahl

Sie können auch mit der Punktzahl suchen:

results = vector_store.similarity_search_with_score(
    "Will it be hot tomorrow?", k=1, expr='source == "news"'
)
for res, score in results:
    print(f"* [SIM={score:3f}] {res.page_content} [{res.metadata}]")
* [SIM=0.893776] The weather forecast for tomorrow is cloudy and overcast, with a high of 62 degrees. [{'source': 'news', 'pk': 'dbf6560a-1487-4a6e-8797-245d57874f5b'}]

Eine vollständige Liste aller Suchoptionen, die bei der Verwendung des Milvus Vektorspeichers zur Verfügung stehen, finden Sie in der API-Referenz.

Abfrage durch Umwandlung in Retriever

Sie können den Vektorspeicher auch in einen Retriever umwandeln, um ihn einfacher in Ihren Ketten zu verwenden.

retriever = vector_store.as_retriever(search_type="mmr", search_kwargs={"k": 1})
retriever.invoke("Stealing from the bank is a crime", expr='source == "news"')
I0000 00:00:1761298049.275354 7886403 fork_posix.cc:71] Other threads are currently calling into gRPC, skipping fork() handlers





[Document(metadata={'source': 'news', 'pk': '2818c051-5a1a-44cb-9deb-aaaac709f616'}, page_content='Robbers broke into the city bank and stole $1 million in cash.')]

Verwendung für Retrieval-Augmented Generation

Eine Anleitung zur Verwendung dieses Vektorspeichers für die abruferweiterte Generierung (RAG) finden Sie in diesem RAG-Leitfaden.

Pro-Benutzer-Abruf

Wenn Sie eine Retrieval-Applikation entwickeln, müssen Sie sie oft für mehrere Benutzer erstellen. Das bedeutet, dass Sie möglicherweise nicht nur Daten für einen Benutzer, sondern für viele verschiedene Benutzer speichern, und diese sollten nicht in der Lage sein, die Daten des jeweils anderen zu sehen.

Milvus empfiehlt die Verwendung von partition_key, um Multi-Tenancy zu implementieren, hier ist ein Beispiel.

Die Funktion des Partitionsschlüssels ist jetzt nicht in Milvus Lite verfügbar, wenn Sie sie nutzen wollen, müssen Sie den Milvus-Server von Docker oder Kubernetes aus starten.

from langchain_core.documents import Document

docs = [
    Document(page_content="i worked at kensho", metadata={"namespace": "harrison"}),
    Document(page_content="i worked at facebook", metadata={"namespace": "ankush"}),
]
vectorstore = Milvus.from_documents(
    docs,
    embeddings,
    collection_name="partitioned_collection",  # Use a different collection name
    connection_args={"uri": URI},
    # drop_old=True,
    partition_key_field="namespace",  # Use the "namespace" field as the partition key
)

Um eine Suche mit dem Partitionsschlüssel durchzuführen, sollten Sie einen der folgenden Punkte in den booleschen Ausdruck der Suchanfrage aufnehmen:

search_kwargs={"expr": '<partition_key> == "xxxx"'}

search_kwargs={"expr": '<partition_key> == in ["xxx", "xxx"]'}

Ersetzen Sie <partition_key> durch den Namen des Feldes, das als Partitionsschlüssel bezeichnet wird.

Milvus wechselt zu einer Partition, die auf dem angegebenen Partitionsschlüssel basiert, filtert Entitäten gemäß dem Partitionsschlüssel und sucht in den gefilterten Entitäten.

# This will only get documents for Ankush
vectorstore.as_retriever(search_kwargs={"expr": 'namespace == "ankush"'}).invoke(
    "where did i work?"
)
[Document(metadata={'namespace': 'ankush', 'pk': 460829372217788296}, page_content='i worked at facebook')]
# This will only get documents for Harrison
vectorstore.as_retriever(search_kwargs={"expr": 'namespace == "harrison"'}).invoke(
    "where did i work?"
)
[Document(metadata={'namespace': 'harrison', 'pk': 460829372217788295}, page_content='i worked at kensho')]

API-Referenz

Eine ausführliche Dokumentation finden Sie in der API-Referenz: https://reference.langchain.com/python/integrations/langchain_milvus/