ベクトルストア

  • インテグレーションにアクセスして、LangChainが公式にサポートしているすべてのサードパーティー ベクトルストレージエンジンについて詳細を把握してください。

非構造化データの格納と検索における最も一般的な解決策は、データの特徴ベクトルを計算し、クエリ時にベクトルの類似性に基づいて類似ベクトルを検索することです。ベクトルデータベースは、ベクトルの格納とクエリのためのデータストレージエンジンを提供する責務があります。

LangChain ベクトルストアのはじめ方

このガイドでは、ベクトルストアに関連する基本機能について紹介します。ベクトルストレージと連動する主要なコンポーネントは埋め込みモデル(特徴ベクトルの計算を担当)です。そのため、この章を学習する前に、テキスト埋め込みモデルを使用してテキストベクトルを計算する方法を学ぶことをお勧めします。

LangChainフレームワークでは、多くの優れたベクトルストレージエンジンが利用可能です。以下では、LangChainフレームワークで提供されている3つの無料かつオープンソースのベクトルストレージエンジンの使用法を紹介します。

Chroma

この章では、chroma ベクトルデータベースを使用します。これはPythonライブラリとしてローカルで実行されます。

pip install chromadb

ここではOpenAIの埋め込みモデルを使用してベクトルを計算するため、OpenAI APIキーを取得する必要があります。

import os
import getpass
os.environ['OPENAI_API_KEY'] = getpass.getpass('OpenAI APIキー:')
from langchain_community.document_loaders import TextLoader
from langchain_openai import OpenAI埋め込み
from langchain_text_splitters import CharacterTextSplitter
from langchain_community.vectorstores import Chroma

raw_documents = TextLoader('../../../state_of_the_union.txt').load()
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
documents = text_splitter.split_documents(raw_documents)
db = Chroma.from_documents(documents, OpenAI埋め込み())

FAISS

この章では、Facebook AI Similarity Search(FAISS)ライブラリを利用するFAISS ベクトルデータベースを使用します。

pip install faiss-cpu

ここではOpenAIの埋め込みモデルを使用してベクトルを計算するため、OpenAI APIキーを取得する必要があります。

import os
import getpass

os.environ['OPENAI_API_KEY'] = getpass.getpass('OpenAI APIキー:')
from langchain_community.document_loaders import TextLoader
from langchain_openai import OpenAI埋め込み
from langchain_text_splitters import CharacterTextSplitter
from langchain_community.vectorstores import FAISS

raw_documents = TextLoader('../../../state_of_the_union.txt').load()
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
documents = text_splitter.split_documents(raw_documents)
db = FAISS.from_documents(documents, OpenAI埋め込み())

Lance

この章では、LangChainフレームワークがLanceDBベクトルデータベースを使用する方法を紹介します。

pip install lancedb

ここではOpenAIの埋め込みモデルを使用してベクトルを計算するため、OpenAI APIキーを取得する必要があります。

import os
import getpass

os.environ['OPENAI_API_KEY'] = getpass.getpass('OpenAI APIキー:')
from langchain_community.document_loaders import TextLoader
from langchain_openai import OpenAI埋め込み
from langchain_text_splitters import CharacterTextSplitter
from langchain_community.vectorstores import LanceDB

import lancedb

db = lancedb.connect("/tmp/lancedb")
table = db.create_table(
    "my_table",
    data=[
        {
            "vector": embeddings.embed_query("ハローワールド"),
            "text": "ハローワールド",
            "id": "1",
        }
    ],
    mode="上書き",
)

raw_documents = TextLoader('../../../state_of_the_union.txt').load()
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
documents = text_splitter.split_documents(raw_documents)
db = LanceDB.from_documents(documents, OpenAI埋め込み(), connection=table)

類似性検索

query = "大統領はケタンジ・ブラウン・ジャクソンに何と言いましたか?"
docs = db.similarity_search(query)
print(docs[0].page_content)

ベクトル類似検索

与えられたベクトルに基づいて類似検索を実行するには、similarity_search_by_vector を使用します。この関数は、文字列ではなく埋め込みベクトルをパラメータとして取ります。

embedding_vector = OpenAIEmbeddings().embed_query(query)
docs = db.similarity_search_by_vector(embedding_vector)
print(docs[0].page_content)

非同期操作

ベクトルストレージは通常、独立したサービスとして実行され、いくつかのIO操作が必要です。そのため、ベクトルデータベースインターフェースを非同期呼び出しすることで、外部サービスからの応答を待つ時間を無駄にせずにパフォーマンスを向上させることができます。

Langchain はベクトルストレージの非同期操作をサポートしています。すべてのメソッドは、a 接頭辞を持つ非同期関数を使用して呼び出すことができます。

Qdrant はすべての非同期操作をサポートするベクトルストレージです。以下は Qdrant を使用した例です。

pip install qdrant-client
from langchain_community.vectorstores import Qdrant

非同期ベクトルストレージの作成

db = await Qdrant.afrom_documents(documents, embeddings, "http://localhost:6333")

類似検索

query = "大統領はケタンジ・ブラウン・ジャクソンに何と言ったのですか?"
docs = await db.asimilarity_search(query)
print(docs[0].page_content)

ベクトルベースの検索

embedding_vector = embeddings.embed_query(query)
docs = await db.asimilarity_search_by_vector(embedding_vector)

最大周辺余剰(MMR)検索

最大周辺余剰はクエリと選択されたドキュメント間の類似性と多様性を最適化します。また、非同期APIをサポートしています。

query = "大統領はケタンジ・ブラウン・ジャクソンに何と言ったのですか?"
found_docs = await qdrant.amax_marginal_relevance_search(query, k=2, fetch_k=10)
for i, doc in enumerate(found_docs):
    print(f"{i + 1}.", doc.page_content, "\n")