LoginSignup
9
12

【15分】ベクトルデータベース&RAG爆速入門

Last updated at Posted at 2024-05-21

はじめに

本記事では、ベクトルデータベースの構築とRAGでの検索を初心者向けにまとめています。
GoogleColaboratory環境で実装するため、ややこしい環境設定はほとんどありません。全部無料です。

生成AIやRAG、ベクトルデータベースは難しいイメージを持つ人が多いですが、実はとてもシンプルで実装も簡単です。15分程度で実装できるようになり、かつ語れるようになると思います。

ベクトルデータベースとは?

ここからざっくり分かりやすく説明します。イメージを掴むことを優先します。

まず普通のデータベースについて

普通のデータベースには数字のデータが入っておりSQLで必要な情報を抜き出すことができます。例えば、ある顧客の1年間での売り上げ金額を取得したりできます。

ベクトルデータベースとは?

一方で、PDFファイルなどの文字情報を検索したい場合はどうすれば良いでしょうか?例えば、100ページに渡る論文の中から特定の情報を知りたい時などです。一枚一枚目視をしていては日が暮れます。
そのような場合に使うのがベクトルデータベースです。大量の文字情報をチャンクという文節の単位で切り分けデータベースの値として保存します。

何がベクトルなのか?

チャンクにわけた文節をそのまま文字でデータベースに保管するわけではなく、文字をベクトルにしてから保存するためベクトルデータベースと言われています。文字情報のままでも使えますが、重いです。そこでベクトル化をすることで文字データを圧縮しつつ、数字として扱うことで検索の自由度を高めることができます。

ベクトルデータベースの中身

こんな感じです。行名にチャンクにした文章が入っており、以降の列はベクトルになっています。見ての通り普通のDBと同じです。文章の検索よりもベクトルの類似度の検索の方がはるかに簡単なためこのような構造になっています。
image.png

今回の目標

  1. ベクトルDBの構築
    image.png
  2. langchainでのベクトル検索実装
    image.png

1.初期準備(5分)

はじめにライブラリのインストールとOpenAI APIキーの設定を行います。

インストールするライブラリ

  1. langchain:RAGをするために使用
  2. langchain_community:langchainのライブラリを使う際に必要
  3. openai:生成AIのエンジンとしてOpenAIを使用
  4. pinecone-client:ベクトルデータベースとして使用
  5. tiktoken:文章データをチャンクにわけベクトル化する際ために使用
  6. pdfminer.six:PDFからテキストを抽出するために使用

ライブラリーのインポート

Google Colaboratory開き以下を実行します。

!pip install langchain langchain_community openai pinecone-client tiktoken pdfminer.six

OpenAI APIのキー取得

オープンAIのAPIキーを取得し、コラボの環境変数に設定します。

APIキーに慣れていない方はこちらが参考になります↓

「your OPENAI_API_KEY」の部分を取得したキーに変えて実行します。なお、Colabでは環境変数を設定する機能がありますが、この記事では便宜的にコードで環境変数を設定します。

set.py
import openai
import os

os.environ["OPENAI_API_KEY"] = "your OPENAI_API_KEY"
openai.api_key = os.getenv("OPENAI_API_KEY")

2.ベクトルDBの作成(8分)

手順

  1. 対象データの読み込みとベクトル化
    • STEP①:RAGしたいファイルの読み込み
    • STEP②:PDFのテキスト化
    • STEP③:テキストの分割(=チャンク)
    • STEP④:分割したテキストデータをベクトル化
  2. ベクトルデータベースへの格納
    • STEP①:pinconeへの接続
    • STEP②:pinconeへデータを格納する

1.対象データの読み込みとベクトル化

STEP①:RAGしたいファイルの読み込み

自分のベクトル化したいファイルをアップロードします。例としてtransformerの論文をアップロードします。

vectorize_1.py
# STEP①:RAGしたいファイルの読み込み
from google.colab import files
uploaded = files.upload()
file_name = list(uploaded.keys())[0]

STEP②:PDFのテキスト化

PDFから文字情報を抜き取る処理です。pdf2txt.pyというライブラリを使わせていただきます。

vectorize_2.py
# STEP②:PDFのテキスト化
import os
import urllib.request

# pdf2txt.pyのダウンロード
py_url ='https://github.com/pdfminer/pdfminer.six/blob/master/tools/pdf2txt.py'
py_fn='pdf2txt.py'
os.system("wget -O " + str(py_fn) + " " + str(py_url))

# pdf2txt.pyを用いてpdfファイルをテキスト変換
lines = !pdf2txt.py { file_name }
text = '\n'.join(lines)

STEP③:テキストの分割(=チャンク)

調整してみてください。
separator="." → 区切り位置
chunk_size=1000 → チャンクに含まれる文字数。1000文字で一塊という意味。
chunk_overlap=15 → チャンク間の重複部分のサイズ。15文字までは重複OKの意味。

vectorize_3.py
### STEP③:テキストの分割
from langchain.text_splitter import CharacterTextSplitter

text_splitter = CharacterTextSplitter(
    separator=".",
    chunk_size=1000,
    chunk_overlap=15
    )

docs = text_splitter.split_text(text)
len(docs)

43

→今回は、43個のチャンクに分けらました。各チャンクはlistに保存されています。

STEP④:分割したテキストデータをベクトル化

チャンクをベクトルに変換します。それに伴い、listではなくdataframeに変更します。

vectorize_4.py
from langchain.embeddings.openai import OpenAIEmbeddings
embeddings = OpenAIEmbeddings()

# テキストデータをベクトル化
import pandas as pd
vectorized_docs = [embeddings.embed_query(x) for x in docs]
vectorized_docs = pd.DataFrame(vectorized_docs)

docs_ = pd.DataFrame(docs)
output = pd.concat([docs_,vectorized_docs], axis=1)
output.to_excel('vector_dataset.xlsx',index=False, header=False)
            
output.head()

image.png

2.ベクトルデータベースの構築と格納(Pinecone)

STEP⓪:ベクトルDBのクリエイト

無料で使えるPineconeというベクトルデータベースを使います。下記のまとめが非常に参考になります。

Dtabaseタブからcreate a new indexを選択します。
ここでdimensionsの設定に注意する必要があります。chatgptやopenaiで使われているベクトルの次元は1,536なので、これに合わせる必要があります。
image.png

うまく構築すると以下の画面になります。
image.png

STEP①:pinconeへ接続できるようにする

pineconeとの接続を作ります。「YourAPI_KEY」はpineconeから値を取得してください。

pinecone_1.py
from pinecone import Pinecone
pc = Pinecone(api_key='YourAPI_KEY')
pinecone_index = pc.Index("vector-db")
pc.list_indexes()

STEP②:pinconeへデータを格納する

先ほど作成したベクトル化したPDFのデータ(vectorized_docs)を一行ずつ読み取りpineconeへ格納していきます。

pinecone_2.py
for i in range(len(vectorized_docs)):

    pinecone_index.upsert(
        vectors = [
            {
                'id': str(i+1),
                'values': vectorized_docs.T[i],
                'metadata': {"source": file_name,"text": docs[i], "memo": "memo_"+str(i+1)}
            }
        ]
    )

pineconeの画面を確認するとVECTOR COUNTが43になっており、先ほどのデータが全て格納されていることが確認できました。
image.png

3.ベクトル検索(2分)

セマンティック検索(質問に対して尤もらしい文を抽出する)

STEP①:langchainを使う準備をする
rag.py
os.environ["PINECONE_API_KEY"] = "your pinecone api key"

env="aws"
index_name = "vector-db"

from langchain.vectorstores import Pinecone as PineconeStore
from langchain_openai import OpenAIEmbeddings
embeddings = OpenAIEmbeddings()
docsearch = PineconeStore.from_existing_index(index_name, embeddings,"text")
STEP②:langchainでベクトルデータベースに問い合わせる(RAG)

今回は質問に対して、最も関係する文章を抽出します。43個のチャンクのベクトルから最も質問のベクトルと類似しているベクトルを抽出してます。

rag_2.py
query = "トランスフォーマーとはなんですか?"
answer = docsearch.similarity_search(query, k=1)
print(answer[0].page_content)

image.png

参考資料

終わりに

2024年4月からアウトプットのためにQiitaとnoteを始めました。「フォロー」や「いいね」頂けると励みになります!

9
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
12