はじめに
昨日作成したテキストデータからRAGで使えるデータベースを作成し、数個の特定文字列を用意し、それを検索して評価する。
情報源
- LLMのファインチューニングとRAG 自分がRAGのことを体系的に学んだ書籍。ベクトルデータベース、キーワードベース(BM25を使った)を作成する部分は、この書籍で学んだ内容である。
使用環境
ベクトルストアを構築するために、GPU版FAISSパッケージを使用した。また日本語キーワードベースを作成する際に、キーワードを取り出すために日本語の形態素解析のために、janomeという名前のパッケージを使用した。そこで、今回使用したコンテナ環境を明確にするため、Dockerfileを以下に示す。
# JupyterLabが使えるDockerイメージ
# 自分がこれまで作成したNoteBookに必要なパッケージをインストールしたもの。
FROM nvidia/cuda:12.1.1-cudnn8-devel-ubuntu22.04
# Set bash as the default shell
ENV SHELL=/bin/bash
# Build with some basic utilities
RUN apt update \
&& apt install -y \
wget \
bzip2 \
git \
git-lfs \
curl \
unzip \
file \
xz-utils \
sudo \
python3 \
python3-pip && \
apt-get autoremove -y && \
apt-get clean && \
rm -rf /usr/local/src/*
# alias python='python3'
RUN ln -s /usr/bin/python3 /usr/bin/python
RUN pip install --upgrade pip setuptools \
&& pip install torch==2.2.2 torchvision==0.17.2 torchaudio==2.2.2 \
--index-url https://download.pytorch.org/whl/cu121 \
&& pip install torch torchvision torchaudio \
&& pip install jupyterlab matplotlib pandas scikit-learn ipywidgets \
&& pip install transformers accelerate sentencepiece einops \
&& pip install langchain bitsandbytes protobuf \
&& pip install auto-gptq optimum \
&& pip install pypdf tiktoken sentence_transformers faiss-gpu trafilatura \
&& pip install langchain-community langchain_openai wikipedia \
&& pip install langchain-huggingface unstructured html2text rank-bm25 janome \
&& pip install langchain-chroma sudachipy sudachidict_full \
&& pip install mysql-connector-python
# Install llama-cpp-python[server] with cuBLAS on
#RUN CMAKE_ARGS="-DLLAMA_CUBLAS=on" FORCE_CMAKE=1 \
# pip install llama-cpp-python[server]==0.2.75 --force-reinstall --no-cache-dir
RUN CMAKE_ARGS="-DGGML_CUDA=on" FORCE_CMAKE=1 \
pip install llama-cpp-python[server] --force-reinstall --no-cache-dir
RUN pip install -U numpy==1.26.4
# Create a working directory
WORKDIR /workdir
# Port number in container side
EXPOSE 8888
ENTRYPOINT ["jupyter-lab", "--ip=0.0.0.0", "--port=8888", "--no-browser", "--allow-root", "--NotebookApp.token=''"]
CMD ["--notebook-dir=/workdir"]
日本語形態素解析としては、sudachiも試してみたので、その関連パッケージも入っている。また、mysql関連のパッケージが入っているのは、先日の投稿でも触れたとおり、MySQL(MariaDB)サーバを構築してそこに接続するために入れたもの。両者とも今は使っていない。
データベースを作成
ベクトルデータベース(wiki_vs.db)、キーワードベース(wiki_kw.pkl)それぞれ以下のコードで作成している。
また、昨日作成した「textdb」という名前のテキストファイルは、「wiki_text」として同じフォルダに格納されている。
ベクトルデータベース
# Vector databaseを作成する。
import time
start_time = time.time()
# Wikipediaから天文関係の記事のみを抽出したテキストデータは、WIKI_TEXTとして事前に準備。
# VectorStoreするため、テキストコーパスをチャンクに分割。
WIKI_TEXT = "wiki_text"
# チャンク文字数、オーバラップ文字数を定義
CHUNK_SIZE = 300
CHUNK_OVERLAP = 30
from langchain.text_splitter import RecursiveCharacterTextSplitter
with open(WIKI_TEXT,'r',encoding='utf-8') as f:
text = f.read()
text_splitter = RecursiveCharacterTextSplitter(
chunk_size = CHUNK_SIZE, # チャンクの文字数
chunk_overlap = CHUNK_OVERLAP, # チャンクオーバーラップの文字数
)
texts = text_splitter.split_text(text)
WIKI_TEXT = "wiki_text"
WIKI_DB = "wiki_vs.db"
## データベースを構築
from langchain_huggingface import HuggingFaceEmbeddings
model_name = "intfloat/multilingual-e5-large"
model_path = f"/workdir/models/{model_name}"
embeddings = HuggingFaceEmbeddings(
model_name = model_path,
model_kwargs = {'device':'cuda:0'},
)
from langchain_community.vectorstores import FAISS
# ベクトルデータベースを構築し、WIKI_DBとして保存する
db = FAISS.from_texts(texts, embeddings)
end_time = time.time()
db.save_local(WIKI_DB)
embedding modelは、事前にHuggingFaceからダウンロードし、model_pathに格納されている。
processing_time = end_time - start_time
print("processing_time(sec): ", processing_time)
実行結果(処理時間)は次のとおり。自分の実行環境では約12分掛かった。
processing_time(sec): 704.8360137939453
キーワードベース
# キーワード検索用のデータベースを作成
#
import time
start_time = time.time()
# my_preprocess_funcを定義
from janome.tokenizer import Tokenizer
t = Tokenizer()
def my_preprocess_func(text):
keywords = []
for token in t.tokenize(text):
pos = token.part_of_speech.split(',')[0]
if (pos in ["名詞", "動詞", "形容詞"]):
keywords.append(token.surface)
return keywords
# Wikipediaから天文関係の記事のみを抽出したテキストデータは、WIKI_TEXTとして事前に準備。
# キーワードベースのデータベースを作成するため、テキストコーパスをチャンクに分割。
WIKI_TEXT = "wiki_text"
# チャンク文字数、オーバラップ文字数を定義
CHUNK_SIZE = 300
CHUNK_OVERLAP = 30
from langchain.text_splitter import RecursiveCharacterTextSplitter
with open(WIKI_TEXT, encoding='utf-8') as f:
text = f.read()
text_splitter = RecursiveCharacterTextSplitter(
chunk_size = CHUNK_SIZE, # チャンクの文字数
chunk_overlap = CHUNK_OVERLAP, # チャンクオーバーラップの文字数
)
texts = text_splitter.split_text(text)
from langchain_community.retrievers import BM25Retriever
WIKI_DB = "wiki_kw.pkl"
db = BM25Retriever.from_texts(
texts,
preprocess_func=my_preprocess_func,
)
end_time = time.time()
import pickle
with open(WIKI_DB, 'wb') as f:
pickle.dump(db, f)
processing_time = end_time - start_time
print("processing_time(sec): ", processing_time)
実行結果(処理時間)は次のとおり。 自分の環境では約13分掛かった。
processing_time(sec): 753.1111702919006
作成したデータベースを評価(試しに検索する)
ベクトルデータベース
# ベクトルデータベース検索結果を評価する
#
WIKI_DB = "wiki_vs.db"
import os
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_community.vectorstores import FAISS
model_name = "intfloat/multilingual-e5-large"
model_path = f"/workdir/models/{model_name}"
embeddings = HuggingFaceEmbeddings(
model_name = model_path,
model_kwargs = {'device':'cuda:0'},
)
# 事前に構築したベクトルデータベースを読み込む
if os.path.exists(WIKI_DB):
db = FAISS.load_local(WIKI_DB, embeddings, allow_dangerous_deserialization=True)
else:
print("="*80)
print("You need to make vector database")
print("="*80)
# ベクトル検索で4文書を得る
query = "r過程について教えてください"
docs = db.similarity_search(query, k=4)
print(f"1st: {docs[0].page_content}")
print(f"2nd: {docs[1].page_content}")
print(f"3rd: {docs[2].page_content}")
print(f"4th: {docs[3].page_content}")
# ベクトル検索で4文書を得る
query = "ナンシー・グレース・ローマン宇宙望遠鏡について教えてください"
docs = db.similarity_search(query, k=4)
print(f"1st: {docs[0].page_content}")
print(f"2nd: {docs[1].page_content}")
print(f"3rd: {docs[2].page_content}")
print(f"4th: {docs[3].page_content}")
# ベクトル検索で4文書を得る
query = "B2FH論文について教えてください"
docs = db.similarity_search(query, k=4)
print(f"1st: {docs[0].page_content}")
print(f"2nd: {docs[1].page_content}")
print(f"3rd: {docs[2].page_content}")
print(f"4th: {docs[3].page_content}")
キーワードベース
# キーワード検索結果を評価する
#
from janome.tokenizer import Tokenizer
t = Tokenizer()
def my_preprocess_func(text):
keywords = []
for token in t.tokenize(text):
pos = token.part_of_speech.split(',')[0]
if (pos in ["名詞", "動詞", "形容詞"]):
keywords.append(token.surface)
return keywords
WIKI_DB = "wiki_kw.pkl"
import os
import pickle
from langchain_community.retrievers import BM25Retriever
# 事前に構築したキーワードのデータベースを読み込む
if os.path.exists(WIKI_DB):
with open(WIKI_DB, 'rb') as f:
retriever = pickle.load(f)
else:
print("="*80)
print("You need to make keyword database")
print("="*80)
# キーワード検索で4文書を得る
query = "r過程について教えてください"
docs = retriever.get_relevant_documents(query, k=4)
print(f"1st: {docs[0].page_content}")
print(f"2nd: {docs[1].page_content}")
print(f"3rd: {docs[2].page_content}")
print(f"4th: {docs[3].page_content}")
# キーワード検索で4文書を得る
query = "ナンシー・グレース・ローマン宇宙望遠鏡について教えてください"
docs = retriever.get_relevant_documents(query, k=4)
print(f"1st: {docs[0].page_content}")
print(f"2nd: {docs[1].page_content}")
print(f"3rd: {docs[2].page_content}")
print(f"4th: {docs[3].page_content}")
# キーワード検索で4文書を得る
query = "B2FH論文について教えてください"
docs = retriever.get_relevant_documents(query, k=4)
print(f"1st: {docs[0].page_content}")
print(f"2nd: {docs[1].page_content}")
print(f"3rd: {docs[2].page_content}")
print(f"4th: {docs[3].page_content}")
結果比較
出力された結果をそのまま下表にコピペしたもの。
ベクトルデータベース | キーワードベース |
---|---|
1st: b(.02)とTOI-1670 2nd: Rp過程rp過程(rp かてい,高速陽子捕獲過程 ) は、種核種に連続的に陽子が捕獲され重元素を作り出す過程である.これは元素合成過程であり、 s過程やr過程とともに宇宙に存在する重元素の生成にかかわっている。しかしながら、他の元素合成過程とは、他の過程が中性子に富む側の安定性が問題になるのに対し、陽子に富む側の安定性が問題になる点がかなり違っている。rp過程の終了点(生成することの出来る最重元素)は良くわかっていないが最近の中性子星に関する研究により、テルルより先へ反応が進まないことがわかっている。 3rd: 植物の構成を大きく置き換えるなどの動植物の変化を引き起こした<ref 4th: ()ではエネルギー曲線が不連続になる | 1st: II型)でr過程が起こると広く信じられてきた。しかしながら、r過程核種の存在比からすると、超新星爆発のうち、ほんの少しの事例でr過程核種を星間物質に放出するか、それぞれの超新星爆発で生成されたr過程核種のうち、ほんの少しの部分を放出するということを要請する。またコンピューターシミュレーションでも超新星爆発によってr過程が生じなかったため、超新星爆発がr過程の発生する現場であることに疑問が持たれていた。別の候補として中性子星同士の衝突によってr過程が起こりうる可能性があることが知られていたが、2014年、国立天文台・東京大学の研究チームによって中性子星の合体によるr過程が矛盾なく説明できるとの 2nd: 合成できる環境が考えられる。恒星内元素合成の間に起こるs過程は最大で原子量209のビスマスまでの元素を合成することが可能である。s過程は主に低質量の反応段階の進展の遅い恒星に起こる。r過程.2017年8月、中性子星同士の衝突現象が観測され、その現象を分析した結果、中性子星の衝突によるr過程元素の合成が確認された。この分析結果により、r過程が中性子星同士の融合によって発生することが証明されている。上記の現象が分析されるまでは、恒星核が重力崩壊する超新星爆発(スペクトル型 3rd: (Slow)“の中性子捕獲過程によって、鉄以降の重元素のおよそ半分が合成される。残りの半分はr過程と呼ばれるより"速く 4th: あると誤解されることがある。ノーベル物理学賞の選考委員会は受賞理由を「宇宙における化学元素の生成にとって重要な原子核反応に関する理論的および実験的研究」としている。ファウラーがノーベル賞を受賞した一方で、ホイルは生涯受賞できなかった。ホイルがノーベル物理学賞を受賞できなかった理由について、「ファウラーのBFHへの貢献には、s過程とr過程の原子核物理学も含まれるが、ホイルもまたs過程とr過程に関する理論的研究でファウラー同様の評価を受けるに値する。ビッグバンに関するホイルの否定的な見解がノーベル賞受賞の妨げになった。」と主張するものもいる。ホイルが受賞できなかった理由について、ジェフリー・バービ |
1st: ナンシー・グレース・ローマン宇宙望遠鏡、略称 ローマン宇宙望遠鏡 (, Roman Space Telescope) は、2020年代半ばの打ち上げを目指し、日本を含む国際協力で進められているアメリカ航空宇宙局 (NASA) の広視野赤外線宇宙望遠鏡計画。“Wide Field Infrared Survey Telescope” (広視野近赤外線サーベイ宇宙望遠鏡)の頭文字を取って WFIRST という名称で計画が進められていたが、2020年5月20日、NASAは正式名称を Nancy Grace Roman Space Telescope 2nd: (JWST) が2021年12月25日に打ち上げられた。六角形の鏡を18枚組み合わせた主鏡の口径は約6.5mであり、ハッブル宇宙望遠鏡よりも大幅な高性能化が図られている。ただし観測波長域は近赤外線・赤外線のみであり、近紫外線・可視光の観測能力は持たない。地球と太陽のラグランジュ点 (L2) に位置することで、地球近傍の塵の影響を避け、より高精度の観測を可能としている。元は2011年の打ち上げ予定であったが、度々延期されたものである。ナンシー・グレース・ローマン宇宙望遠鏡.2012年6月4日、アメリカ国家偵察局 (NRO) 3rd: Grace Roman Space Telescope と定めたと発表した。ナンシー・グレース・ローマンは、1960年代以降NASAの宇宙望遠鏡計画実現に重要な役割を果たし、特にハッブル宇宙望遠鏡の計画実現のためNASA内部や議会へ積極的な働きかけをしたことから「ハッブルの母 (Mother of Hubble) 4th: Hubble”)」とも呼ばれた。また、ローマンはそのキャリアを通じて、積極的な講演者や教育者、科学分野における女性の擁護者でもあった。2020年5月20日、NASAのジム・ブライデンスタイン長官は、彼女の天文学への絶えることのない貢献を称え、計画中の赤外線宇宙望遠鏡WFIRSTをナンシー・グレース・ローマン宇宙望遠鏡と命名することを発表した。若年期.ナンシー・グレース・ローマンは、テネシー州ナッシュビルで、音楽教師のジョージア・フランシス・スミス・ローマンと物理学者・数学者のアーウィン・ローマンの間に生まれた。生後間もなく、父親が石油会社の地球物理学者として就職したため、生後3ヶ月で一家はオ | 1st: Hubble”)」とも呼ばれた。また、ローマンはそのキャリアを通じて、積極的な講演者や教育者、科学分野における女性の擁護者でもあった。2020年5月20日、NASAのジム・ブライデンスタイン長官は、彼女の天文学への絶えることのない貢献を称え、計画中の赤外線宇宙望遠鏡WFIRSTをナンシー・グレース・ローマン宇宙望遠鏡と命名することを発表した。若年期.ナンシー・グレース・ローマンは、テネシー州ナッシュビルで、音楽教師のジョージア・フランシス・スミス・ローマンと物理学者・数学者のアーウィン・ローマンの間に生まれた。生後間もなく、父親が石油会社の地球物理学者として就職したため、生後3ヶ月で一家はオ 2nd: Grace Roman Space Telescope と定めたと発表した。ナンシー・グレース・ローマンは、1960年代以降NASAの宇宙望遠鏡計画実現に重要な役割を果たし、特にハッブル宇宙望遠鏡の計画実現のためNASA内部や議会へ積極的な働きかけをしたことから「ハッブルの母 (Mother of Hubble) 3rd: ナンシー・グレース・ローマン宇宙望遠鏡、略称 ローマン宇宙望遠鏡 (, Roman Space Telescope) は、2020年代半ばの打ち上げを目指し、日本を含む国際協力で進められているアメリカ航空宇宙局 (NASA) の広視野赤外線宇宙望遠鏡計画。“Wide Field Infrared Survey Telescope” (広視野近赤外線サーベイ宇宙望遠鏡)の頭文字を取って WFIRST という名称で計画が進められていたが、2020年5月20日、NASAは正式名称を Nancy Grace Roman Space Telescope 4th: ナンシー・ローマンナンシー・グレース・ローマン(Nancy Grace Roman、1925年5月16日 - 2018年12月25日)は、1950年代に恒星の分類と運動の研究に多大な貢献を果たしたアメリカの天文学者。アメリカ航空宇宙局 (NASA) において女性として初めて幹部職に就き、1960年代から1970年代にかけてNASAの初代主任天文学者として宇宙天文学プログラムをスタートさせた。ハッブル宇宙望遠鏡計画では、天文学コミュニティや議会を動かすなど基礎を築く役割を果たしたことから「ハッブルの母 (“Mother of |
1st: B2FH論文BFH論文 (BFH paper) は、元素の起源に関する記念碑的な論文である。論文の題名は “Synthesis of the Elements in Stars” だが、著者であるマーガレット・バービッジ、ジェフリー・バービッジ、ウィリアム・ファウラー、フレッド・ホイルの4名の頭文字を取って「B2FH」として知られている。1955年から1956年にかけてケンブリッジ大学とカリフォルニア工科大学で執筆され、1957年にアメリカ物理学会の査読付き学術誌"Reviews of Modern 2nd: b(.02)とTOI-1670 3rd: formula_16 である。この論文で、トフーフトは formula_16 4th: using the background-field method」や、と共同執筆した「The finiteness requirement for six-dimensional Euclidean-Einstein | 1st: B2FH論文BFH論文 (BFH paper) は、元素の起源に関する記念碑的な論文である。論文の題名は “Synthesis of the Elements in Stars” だが、著者であるマーガレット・バービッジ、ジェフリー・バービッジ、ウィリアム・ファウラー、フレッド・ホイルの4名の頭文字を取って「B2FH」として知られている。1955年から1956年にかけてケンブリッジ大学とカリフォルニア工科大学で執筆され、1957年にアメリカ物理学会の査読付き学術誌"Reviews of Modern 2nd: 年にはワシントン大学の客員教授を務めた。業績.1957年にマーガレット・バービッジ、ジェフリー・バービッジ、フレッド・ホイルと共著の論文(4人の名前からB2FH論文と呼ばれる)は、恒星のなかでの元素の起源に関するその分野での重要な論文である。ファウラーは、炭素を合成するトリプルアルファ反応が働くために必要なエネルギー準位を、炭素原子核が持つことを実験で証明した。 3rd: ということを1952年に提唱し、ホイルにその節を示唆されたウィリアム・ファウラーは、実際にそのような準位が存在することを示し、B2FH論文と呼ばれる世界的な論文を1957年に発表した。今日ではこのような考え方を人間原理と呼び、その例として挙げられることもあるが、2010年に出された論文では、少なくともホイルは炭素を基盤とした生命体である人間の存在を仮定してこの説を唱えたわけではないとするものが出された。 4th: ッグ放射線研究所に赴いて、所長のウィリアム・ファウラーの協力で、泡箱を用いて原子核の衝突実験(3個のヘリウムでできる炭素の原子核の性質を調べる実験)を成功させた。これにより炭素は星のなかで無尽蔵に作られる性質があることが判った。その後も彼ら2人を含めて数名が元素の歴史に迫り、B2FH論文に結実させた。だが、こうした論文は定常モデルに有利に働いたというよりむしろ、ハッブルの観測によって導かれた星の進化に関するアイディア群がより完成度を高めた、と一般には見なされた。《ビッグバン |
まとめ
上記の検索例(何も元のテキストデータにはその説明は必ずあるキーワード ー r過程、ナンシー・グレース・ローマン宇宙望遠鏡、B2FH論文 ー を使った)では、キーワード検索の方が良くヒットしているようである。 ベクトルデータベースのr過程の例では、2nd以外は外しているように見える。B2FH論文の例でも、1st以外は外しているようだ。
この辺りにベクトルデータベースでの難しさがあるように感じる。