LangChainでPDFをベクトル化してローカルに保存してみた

はじめに

LangChainを使用して、PDF文書をベクトル化し、ローカルのベクトルストアに保存してみました。この方法により、一度ローカルに保存した後はベクトル化を再度行う必要がなくなり、回答時間を短縮することができます。LangChainを使った文書検索を開発している方におすすめです。

開発環境

  • Windows 11
  • Python 3.9.15
  • dotenv
  • LangChain
  • Azure OpenAI Embeddings
  • CharacterTextSplitter
  • PyPDFLoader

実装

必要なパッケージのインストール

以下のコマンドで必要なパッケージをインストールします。

pip install langchain openai python-dotenv faiss-cpu pypdf PyPDF2 tiktoken

環境変数の設定と依存関係の読み込み

.envファイルを作成し、Azure Open AIの環境変数の設定をします。

ご自身の環境に合わせて設定してください。

# APIキー
OPENAI_API_KEY = "XXXXX"

# エンドポイント

AZURE_OPENAI_ENDPOINT = "XXXXX"

# 使用するOpenAI APIのバージョン

OPENAI_API_VERSION = "XXXXX"

必要なライブラリをインポートします。

import os 

from dotenv import load_dotenv 
load_dotenv() 

from langchain.embeddings import AzureOpenAIEmbeddings
from langchain.text_splitter import CharacterTextSplitter 
from langchain.vectorstores import FAISS 
from langchain.document_loaders import PyPDFLoader

ベクトル化の準備

ベクトル化に使用するAzure OpenAI Embeddingsを定義します。

embeddings = AzureOpenAIEmbeddings(
    azure_deployment="text-embedding-ada-002",
    openai_api_version="2023-05-15"
)

FAISSベクトルストアの初期化

FAISSを使用して、文書を高速に検索可能な形式に変換します。

dummy_text, dummy_id = "1", 1
vectorstore = FAISS.from_texts([dummy_text], embeddings, ids=[dummy_id])
vectorstore.delete([dummy_id])

ファイルの読み込みと処理

指定されたディレクトリ内のPDFファイルを読み込み、処理します。

dirnameはご自身のディレクトリ名に合わせてください。

dirname = "datasets"
files = []

for filename in os.listdir(dirname):
    full_path = os.path.join(dirname, filename)
    if os.path.isfile(full_path):
        files.append({"name": filename, "path": full_path})

テキストのベクトル化とストアへの保存

読み込んだPDF文書からテキストを抽出し、ベクトル化してストアに保存します。

for file in files:
    if file["path"].endswith(".pdf"):
        loader = PyPDFLoader(file["path"])
    else:

        raise ValueError(f"Unsupported file format: {file['path']}")
    pages = loader.load_and_split()
    for page in pages:
        page.metadata["source"] = file["path"]
        page.metadata["name"] = file["name"]

    text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
    docs = text_splitter.split_documents(pages)
    vectorstore.merge_from(FAISS.from_documents(docs, embeddings))

vectorstore.save_local("./vectorstore")

これまでのPythonコードを上から順に記述し終わったら、Pythonファイルを実行します。

実行が完了すると、以下のようにvectorstoreディレクトリが作成されます。

image.png

おわりに

LangChainを使用して、PDF文書をベクトル化し、ローカルのベクトルストアに保存してみました。文書検索システム開発の際に便利です。ぜひ、試してみてください。

最後までお読みいただき、ありがとうございました! 記事に関する質問等ございましたら、コメントもしくは以下のDMにてよろしくお願いします。

参考文献

この記事を書いた人

azure-recipe-user