MongoDB ベクトル検索 をLgChuin と統合すると、 の自己クエリ検索を実行できます。このチュートリアルでは、自己クエリリトリバーを使用して、メタデータをフィルタリングして自然言語MongoDB ベクトル検索クエリを実行する方法を説明します。
セルフクエリ検索では、LVM を使用して検索クエリーを処理し、可能なメタデータフィルターを識別し、フィルターを使用して構造化ベクトル検索クエリーを作成し、そのクエリを実行して最も関連性の高いドキュメントを検索します。
例
「評価が を超える、 以降のアクション映画は?クエリに一致するドキュメントを検索するためにフィルタリングします。20108genre
year
rating
このチュートリアルの実行可能なバージョンを Python エディタとして操作します。
前提条件
Atlas の サンプル データ セット からの映画データを含むコレクションを使用します。
次のいずれかのMongoDBクラスター タイプ
MongoDBバージョン 6.0.11を実行中Atlas クラスター7.0.2、またはそれ以降IPアドレスが Atlas プロジェクトのアクセス リストに含まれていることを確認します。
Atlas CLI を使用して作成されたローカル Atlas 配置。詳細については、「Atlas 配置のローカル配置の作成」を参照してください。
Search とベクトル検索がインストールされたMongoDB Community または Enterprise クラスター。
投票AI APIキー。詳細については、投票AIドキュメント を参照してください
OpenAI APIキー。APIリクエストに使用できるクレジットを持つ OpenAI アカウントが必要です。OpenAI アカウントの登録の詳細については、OpenAI APIウェブサイト を参照してください。
MongoDB をベクトル ストアとして使用
このセクションでは、 MongoDBクラスターをベクトルデータベースとして使用してベクトルストアのインスタンスを作成します。
環境を設定します。
このチュートリアルの環境を設定します。 .ipynb
拡張機能のファイルを保存して、インタラクティブPythonノートを作成します。 このノートはPythonコード スニペットを個別に実行でき、このチュートリアルのコードを実行するために使用します。
ノートク環境を設定するには、次の手順に従います。
ノートブックで次のコマンドを実行します。
pip install --quiet --upgrade langchain-mongodb langchain-voyageai langchain-openai langchain langchain-core lark 環境変数を設定してください。
このチュートリアルの環境変数を設定するには、次のコードを実行します。Vorage APIキー、OpenAI APIキー、およびMongoDBクラスターの SRV 接続文字列を指定します。
import os os.environ["OPENAI_API_KEY"] = "<openai-key>" os.environ["VOYAGE_API_KEY"] = "<voyage-key>" MONGODB_URI = "<connection-string>" 注意
<connection-string>
を Atlas クラスターまたはローカル Atlas 配置の接続文字列に置き換えます。接続stringには、次の形式を使用する必要があります。
mongodb+srv://<db_username>:<db_password>@<clusterName>.<hostname>.mongodb.net 詳しくは、ドライバーを使用してクラスターに接続する を参照してください。
接続stringには、次の形式を使用する必要があります。
mongodb://localhost:<port-number>/?directConnection=true 詳細については、「接続文字列 」を参照してください。
ベクトル ストアをインスタンス化します。
ノート次のコードを実行して、 MongoDBの langchain_db.self_query
名前空間を使用して vector_store
という名前のベクトルストアインスタンスを作成します。
from langchain_mongodb import MongoDBAtlasVectorSearch from langchain_voyageai import VoyageAIEmbeddings # Use the voyage-3-large embedding model embedding_model = VoyageAIEmbeddings(model="voyage-3-large") # Create the vector store vector_store = MongoDBAtlasVectorSearch.from_connection_string( connection_string = MONGODB_URI, embedding = embedding_model, namespace = "langchain_db.self_query", text_key = "page_content" )
ベクトルストアにデータを追加します。
ノートクに次のコードを貼り付けて実行し、メタデータを含むサンプルドキュメントをMongoDBのコレクションに取り込みます。
from langchain_core.documents import Document docs = [ Document( page_content="A bunch of scientists bring back dinosaurs and mayhem breaks loose", metadata={"year": 1993, "rating": 7.7, "genre": "action"}, ), Document( page_content="A fight club that is not a fight club, but is a fight club", metadata={"year": 1994, "rating": 8.7, "genre": "action"}, ), Document( page_content="Leo DiCaprio gets lost in a dream within a dream within a dream within a ...", metadata={"year": 2010, "genre": "thriller", "rating": 8.2}, ), Document( page_content="A bunch of normal-sized women are supremely wholesome and some men pine after them", metadata={"year": 2019, "rating": 8.3, "genre": "drama"}, ), Document( page_content="Three men walk into the Zone, three men walk out of the Zone", metadata={"year": 1979, "rating": 9.9, "genre": "science fiction"}, ), Document( page_content="A psychologist / detective gets lost in a series of dreams within dreams within dreams and Inception reused the idea", metadata={"year": 2006, "genre": "thriller", "rating": 9.0}, ), Document( page_content="Toys come alive and have a blast doing so", metadata={"year": 1995, "genre": "animated", "rating": 9.3}, ), Document( page_content="The toys come together to save their friend from a kid who doesn't know how to play with them", metadata={"year": 1997, "genre": "animated", "rating": 9.1}, ), ] # Add data to the vector store, which automaticaly embeds the documents vector_store.add_documents(docs)
Atlaslangchain_db.self_query
を使用している場合は、Atlas UI で名前空間に移動することでベクトル埋め込みを確認できます。
フィルターを使用してMongoDB ベクトル検索インデックスを作成します。
次のコードを実行して、ベクトル検索とデータのメタデータフィルタリングを有効にするためにベクトルストアのフィルターを含むMongoDB ベクトル検索インデックスを作成します。
# Use LangChain helper method to create the vector search index vector_store.create_vector_search_index( dimensions = 1024, # The dimensions of the vector embeddings to be indexed filters = [ "genre", "rating", "year" ], # The metadata fields to be indexed for filtering wait_until_complete = 60 # Number of seconds to wait for the index to build (can take around a minute) )
インデックスの構築には約 1 分かかります。 構築中、インデックスは最初の同期状態になります。 構築が完了したら、コレクション内のデータのクエリを開始できます。
自己クエリ型レプリカの作成
このセクションでは、ベクトルストアのデータをクエリするために自己クエリ レプリカを初期化します。
ドキュメントとメタデータフィールドを説明します。
自己クエリ検索バーを使用するには、コレクション内のドキュメントと、フィルタリングするメタデータフィールドを記述する必要があります。この情報は、LM がデータの構造と、ユーザー クエリに基づいて結果をフィルタリングする方法を理解するのに役立ちます。
from langchain.chains.query_constructor.schema import AttributeInfo # Define the document content description document_content_description = "Brief summary of a movie" # Define the metadata fields to filter on metadata_field_info = [ AttributeInfo( name="genre", description="The genre of the movie", type="string", ), AttributeInfo( name="year", description="The year the movie was released", type="integer", ), AttributeInfo( name="rating", description="A 1-10 rating for the movie", type="float" ), ]
自己クエリ検索バーを初期化します。
MongoDBAtlasSelfQueryRetriever.from_llm
メソッドを使用して自己クエリ型リゾルバを作成するには、次のコードを実行します。
from langchain_mongodb.retrievers import MongoDBAtlasSelfQueryRetriever from langchain_openai import ChatOpenAI llm = ChatOpenAI(model="gpt-4o") retriever = MongoDBAtlasSelfQueryRetriever.from_llm( llm=llm, vectorstore=vector_store, metadata_field_info=metadata_field_info, document_contents=document_content_description )
自己クエリ型リトリガーによるクエリの実行
次のクエリを実行して、自己クエリ検索取得者がさまざまなタイプのクエリをどのように実行するかを確認します。
# This example specifies a filter (rating > 9) retriever.invoke("What are some highly rated movies (above 9)?")
[Document(id='686e84de13668e4048bf9ff3', metadata={'_id': '686e84de13668e4048bf9ff3', 'year': 1979, 'rating': 9.9, 'genre': 'science fiction'}, page_content='Three men walk into the Zone, three men walk out of the Zone'), Document(id='686e84de13668e4048bf9ff5', metadata={'_id': '686e84de13668e4048bf9ff5', 'year': 1995, 'genre': 'animated', 'rating': 9.3}, page_content='Toys come alive and have a blast doing so'), Document(id='686e84de13668e4048bf9ff6', metadata={'_id': '686e84de13668e4048bf9ff6', 'year': 1997, 'genre': 'animated', 'rating': 9.1}, page_content="The toys come together to save their friend from a kid who doesn't know how to play with them")]
# This example specifies a semantic search and a filter (rating > 9) retriever.invoke("I want to watch a movie about toys rated higher than 9")
[Document(id='686e84de13668e4048bf9ff5', metadata={'_id': '686e84de13668e4048bf9ff5', 'year': 1995, 'genre': 'animated', 'rating': 9.3}, page_content='Toys come alive and have a blast doing so'), Document(id='686e84de13668e4048bf9ff6', metadata={'_id': '686e84de13668e4048bf9ff6', 'year': 1997, 'genre': 'animated', 'rating': 9.1}, page_content="The toys come together to save their friend from a kid who doesn't know how to play with them"), Document(id='686e84de13668e4048bf9ff3', metadata={'_id': '686e84de13668e4048bf9ff3', 'year': 1979, 'rating': 9.9, 'genre': 'science fiction'}, page_content='Three men walk into the Zone, three men walk out of the Zone')]
# This example specifies a composite filter (rating >= 9 and genre = thriller) retriever.invoke("What's a highly rated (above or equal 9) thriller film?")
[Document(id='686e84de13668e4048bf9ff4', metadata={'_id': '686e84de13668e4048bf9ff4', 'year': 2006, 'genre': 'thriller', 'rating': 9.0}, page_content='A psychologist / detective gets lost in a series of dreams within dreams within dreams and Inception reused the idea')]
# This example specifies a query and composite filter (year > 1990 and year < 2005 and genre = action) retriever.invoke( "What's a movie after 1990 but before 2005 that's all about dinosaurs, " + "and preferably has the action genre" )
[Document(id='686e84de13668e4048bf9fef', metadata={'_id': '686e84de13668e4048bf9fef', 'year': 1993, 'rating': 7.7, 'genre': 'action'}, page_content='A bunch of scientists bring back dinosaurs and mayhem breaks loose'), Document(id='686e84de13668e4048bf9ff0', metadata={'_id': '686e84de13668e4048bf9ff0', 'year': 1994, 'rating': 8.7, 'genre': 'action'}, page_content='A fight club that is not a fight club, but is a fight club')]
# This example only specifies a semantic search query retriever.invoke("What are some movies about dinosaurs")
[Document(id='686e84de13668e4048bf9fef', metadata={'_id': '686e84de13668e4048bf9fef', 'year': 1993, 'rating': 7.7, 'genre': 'action'}, page_content='A bunch of scientists bring back dinosaurs and mayhem breaks loose'), Document(id='686e84de13668e4048bf9ff5', metadata={'_id': '686e84de13668e4048bf9ff5', 'year': 1995, 'genre': 'animated', 'rating': 9.3}, page_content='Toys come alive and have a blast doing so'), Document(id='686e84de13668e4048bf9ff1', metadata={'_id': '686e84de13668e4048bf9ff1', 'year': 2010, 'genre': 'thriller', 'rating': 8.2}, page_content='Leo DiCaprio gets lost in a dream within a dream within a dream within a ...'), Document(id='686e84de13668e4048bf9ff6', metadata={'_id': '686e84de13668e4048bf9ff6', 'year': 1997, 'genre': 'animated', 'rating': 9.1}, page_content="The toys come together to save their friend from a kid who doesn't know how to play with them")]
RAG パイプラインでのレトリーバーの使用
自己クエリ型リゾルバは、 RAGパイプラインで使用できます。次のコードをノート PC に貼り付けて実行し、自己クエリ検索を実行するサンプルRAGパイプラインを実装します。
このコードでは、必要に応じて LM が取得で返されるドキュメント数を制限できるようにする enable_limit
パラメータを使用するように取得を構成します。 生成される応答は異なる場合があります。
import pprint from langchain_core.output_parsers import StrOutputParser from langchain_core.prompts import PromptTemplate from langchain_core.runnables import RunnablePassthrough from langchain_openai import ChatOpenAI llm = ChatOpenAI(model="gpt-4o") # Configure self-query retriever with a document limit retriever = MongoDBAtlasSelfQueryRetriever.from_llm( llm, vector_store, document_content_description, metadata_field_info, enable_limit=True ) # Define a prompt template template = """ Use the following pieces of context to answer the question at the end. {context} Question: {question} """ prompt = PromptTemplate.from_template(template) # Construct a chain to answer questions on your data chain = ( { "context": retriever, "question": RunnablePassthrough()} | prompt | llm | StrOutputParser() ) # Prompt the chain question = "What are two movies about toys after 1990?" # year > 1990 and document limit of 2 answer = chain.invoke(question) print("Question: " + question) print("Answer: " + answer) # Return source documents documents = retriever.invoke(question) print("\nSource documents:") pprint.pprint(documents)
Question: What are two movies about toys after 1990? Answer: The two movies about toys after 1990 are: 1. The 1995 animated movie (rated 9.3) where toys come alive and have fun. 2. The 1997 animated movie (rated 9.1) where toys work together to save their friend from a kid who doesn’t know how to play with them. Source documents: [Document(id='686e84de13668e4048bf9ff5', metadata={'_id': '686e84de13668e4048bf9ff5', 'year': 1995, 'genre': 'animated', 'rating': 9.3}, page_content='Toys come alive and have a blast doing so'), Document(id='686e84de13668e4048bf9ff6', metadata={'_id': '686e84de13668e4048bf9ff6', 'year': 1997, 'genre': 'animated', 'rating': 9.1}, page_content="The toys come together to save their friend from a kid who doesn't know how to play with them")]