この内容は2024年11月27日(水)にホテル雅叙園東京で開催された「IBM TechXchange Japan 2024」で実施したwatsonxハンズオン「さわってみよう ベクトル・データベース watsonx.dataでRAG体験」の内容です。QiitaではPart1, Part2, Part3, Part4の四部構成で、 この投稿はPart1となります。
- Part1: Excelをベクトル化してベクトルDB Milvusに入れよう (当投稿)
- Part2: ベクトルDB Milvusに入ったデータで類似検索してみよう!
- Parr3: ベクトルDB Milvusとwatsonx.ai LLMでRAGを構成して、質問をしてみよう!
- Part4: ベクトルDB Milvusとwatsonx.ai LLMでRAGを構成して、チャットアプリを作成してみよう!
座学部分の資料はこちらです:
使用したハンズオン資料はこちらです:
0. ハンズオン内容 および 前提
0.1: ハンズオン内容
TechXchange JapanのWebサイトの内容のソースであるExcelファイルを使って、RAGを構成し、 TechXchange JapanについてQ&Aができるchatbotを作ります。
- このハンズオンでは watsonx.dataのベクトル・データベース Milvusへのアクセス、データの追加をし、watsonx.aiの生成AIを組み合わせてRAGを体験していただくのが目的です。
- RAGのフレームワークとしてLangChainを使います。
- chatbotのGUI構築にはpythonの機械学習モデルのデモを行うWebアプリケーションを簡単に作ることができるPythonのライブラリーgradioを使います。
- RAGを体験していただくのが目的のため、Milvusのindex typeやmetricsなどの詳細、LangChainの使い方詳細、gradioの使い方詳細など Coding詳細はこのハンズオンでは扱いません。
0.2: ハンズオン前提
当ハンズオンを実施するには以下の環境が必要です:
- watsonx.dataのMilvus または なんらかのMilvusが使える状況にあり、接続に必要なhostname, port, APIKEY情報が入手可能
- watsonx.ai Studioでプロジェクト作成済み かつ Watson Machine Learning と関連付けされていて、APIKEY, Project Id情報が入手可能
- pythonが実行できるjupyter notebook環境があること(Local環境でもOK)
1. Excelをベクトル化してベクトルDB Milvusに入れよう!
この内容はjupyter notebook https://github.com/IBM/japan-technology/blob/main/techxchange/2024-watsonx-handson-1/notebooks/techxchange_handson_01_vectordb.ipynb とほぼ同じです。Link先notebookはwatsonx.ai Studioでの実行を前提としていますが、当内容はLocalも含め一般的なpython実行環境が前提です。
1. 必要なライブラリーのインストール
pipにて以下のライブラリーを導入します:
pip install 'ibm-watsonx-ai>=1.1.15'
pip install 'langchain>=0.3.3'
pip install 'langchain-ibm>=0.3.1'
pip install 'langchain-milvus>=0.1.6'
pip install 'langchain-community>=0.3.2'
pip install 'pymilvus>=2.4.8'
2. apikeyの設定
apikey をセットしてください。
IBM Cloud環境でのAPIKEYの取得方法はこちらを参考にしてください。
またwatsonx.dataとwatsonx.ai Studioは同じAPIKEYである前提で同じ変数を使用していますので、もし違う場合は2つ変数を準備するようにしてください。
apikey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
3. Milvus接続情報の設定
Milvus接続情報の値をセットしてください。
- Milvus Host名
- Milvus Port番号
Milvus接続情報の詳細取得手順はこちら を参照してください。
またmy_connection_argsに設定するkeyの詳細はpymilvusのMilvusClientのパラメータを参照してください。
milvus_host="xxx.xxx.xxx.com"
milvus_port="YYYY"
# Milvus接続情報パラメータののセット
my_connection_args ={
'uri': f'https://{milvus_host}:{milvus_port}',
'token': f'ibmlhapikey:{apikey}'
}
4. watsonx.ai Studio Project idの設定
watsonx.ai Studioで実行する場合は、このノートブックが実行されるプロジェクトからProject idを取得します。 watsonx.ai Studio以外で実行する場合は、Project idを入力してください。
Hint: project_id はプロジェクトを表示し、管理タブから project_id を取得可能です.
import os
try:
project_id = os.environ["PROJECT_ID"]
except KeyError:
project_id = "<ProjrctID>"
5.watsonx.aiのAuthentication用のエンドポイントのURLの設定
Waston Machine Learningのインスタンスを作成したリージョンで決まります。 https://ibm.github.io/watson-machine-learning-sdk/setup_cloud.html#authentication より
Dallas: https://us-south.ml.cloud.ibm.com
London: https://eu-gb.ml.cloud.ibm.com
Frankfurt: https://eu-de.ml.cloud.ibm.com
Tokyo: https://jp-tok.ml.cloud.ibm.com
watsonx_url = "https://us-south.ml.cloud.ibm.com" #ダラスの場合
6. Excelデータの取得
TechXchange Confrence Japan 2024の情報の入ったExcelを取得します。
尚ファイルはこちらにありますので、お手持ちのPCで見たい場合はダウンロードしてExcelで開いて見てみてください。
wget https://github.com/IBM/japan-technology/raw/refs/heads/main/techxchange/2024-watsonx-handson-1/data/TechXchangeJapan2024.xlsx -O TechXchangeJapan2024.xlsx
7. 必要ライブラリーのImport
import pandas as pd
from langchain.schema.document import Document
import json
from langchain_milvus import Milvus
import os
from ibm_watsonx_ai.metanames import EmbedTextParamsMetaNames
from langchain_ibm import WatsonxEmbeddings
from ibm_watsonx_ai.foundation_models.utils.enums import EmbeddingTypes
8, 9, 10で以下を行います
8. Excelファイルの内容を pandas Daraframeに読み込む
path="./"
filename='TechXchangeJapan2024.xlsx'
excel_file = path+filename
df_list = []
# 全てのシートを読み込み、リストdf_listに格納
for sheet_name in pd.ExcelFile(excel_file).sheet_names:
df = pd.read_excel(excel_file, sheet_name=sheet_name)
df_list.append(df)
print(f"\nExcelシート名: {sheet_name}")
display(df.head()) #各シート最初の5 行 表示
9. 行をJSON化し、metadataとしてCategory
,ID
を抜き出す
ベクトルDBにデータを入れる際、どの単位でどのようにベクトル化するかというのは、のちのちの類似検索の結果に関わってきますので重要です。
今回はやりませんが、PDFならページ単位に文字を抜き出して、1ページ分を1ベクトルににするとか、さらに細かく切っておおよそ1000文字単位でうまく文章の切れ目で切って1ベクトルにするとか、いろいろ考えられます。
今回はExcelファイルなので、シート単位で1シート1ベクトルとか、一行1ベクトルとかが考えられます。
今回は一行1ベクトルにしてみます。
さらに一行のベクトル化する元の文字列ですが、列名をいれたJSON形式の文字列にしてみます。
Milvusにはベクトルデータの他に、Keyとなる値を列として持つことができます。RDBのように列で検索も可能です。
LangChainを使って、ベクトルDBにインサートする際、列データはDocumentオブジェクトのmetadataとしてJSONで指定します。 こちらのmetadataのJSON文字列もここで作成します。
import numpy as np
json_doc_list=[]
json_meta_list=[]
for df in df_list:
# 各シートのデータフレームに対する処理
# 行をJSONフォーマットに変換
json_doc_string = json.loads(df.to_json(orient='records', force_ascii=False))
# metaデータとして'Category','ID'を抜き出し, JSONに変換
json_meta_string = json.loads(df[['Category','ID']].to_json(orient='records', force_ascii=False), parse_int=str)
# 各シートのJSON Listを1つのListに結合
json_doc_list.extend(json_doc_string)
json_meta_list.extend( json_meta_string)
#中身確認 最初の5行
print("ベクトル化するデータ 最初の5行")
for index, item in enumerate(json_doc_list[0:5]):
print(index + 1, item)
print("\nmetaデータ 最初の5行")
for index, item in enumerate(json_meta_list[0:5]):
print(index + 1, item)
10. 1行の情報をlangchainのDocumentにし、Listを作成
- page_contentはjson_doc_listの一行分のjson
- ベクトル化されるデータ
- metadataはjson_meta_listのの一行分のjson
- ベクトルDBに列の項目として入るデータ
# DocumentのListをjson_doc_listとjson_meta_listから作成
# page_contentはjson_doc_listの一行分のjson
# metadataはjson_meta_listのの一行分のjson
# 以下と同じコード
# docs = []
# for doc_str, meta_str in zip(json_doc_list, json_meta_list):
# docs.append(Document(page_content=json.dumps(doc_str, ensure_ascii=False), metadata=meta_str))
docs = [Document(page_content=json.dumps(doc_str, ensure_ascii=False), metadata=meta_str)
for doc_str, meta_str in zip(json_doc_list, json_meta_list)]
#中身確認 最初の二行
print(docs[0], "\n\n")
print(docs[1], "\n\n")
11, 12で以下を行います
11. Embeddingモデルを作成
ここではintfloat/multilingual-e5-large
を使います
- https://huggingface.co/intfloat/multilingual-e5-large
- https://dataplatform.cloud.ibm.com/docs/content/wsj/analyze-data/fm-models-embed.html?context=wx&locale=ja#multilingual-e5-large
LangChainで使用できるwatsonx.aiのEmbeddingモデルintfloat/multilingual-e5-largeがあるので、今回はこちらを使用します:
尚、
intfloat/multilingual-e5-large
はオープンソースで公開されているので、watsonx.aiのEmbeddingモデルを使用しなくとも、ローカルにダウンロードすることで使用可能です。 その場合のコードはこちらです(今回は使用しません)from langchain_huggingface import HuggingFaceEmbeddings from tqdm.autonotebook import tqdm embeddings = HuggingFaceEmbeddings(model_name="intfloat/multilingual-e5-large")
下記は`apikey`はMilvusと同じものを使用しています。異なる場合は変数apikeyを変更してください。
# watsonx.aiのEmbeddingモデル取得
embed_params = {
EmbedTextParamsMetaNames.TRUNCATE_INPUT_TOKENS: 512,
EmbedTextParamsMetaNames.RETURN_OPTIONS: {"input_text": True},
}
embeddings = WatsonxEmbeddings(
model_id="intfloat/multilingual-e5-large",
url=watsonx_url,
apikey=apikey,
project_id=project_id
)
12. ベクトルDB Milvusにデータの挿入
参考: LangChain ドキュメント: Vector stores
Milvus参考:
- metric_type https://milvus.io/docs/ja/metric.md?tab=floating 参照
- index_type https://milvus.io/docs/index.md?tab=floating 参照
- paramsは index_type HNSWのパラメーター https://milvus.io/docs/index.md?tab=floatingのHNSWの記載参照
コレクション(Milvusのテーブル名のようなもの)の名前はtechxchange_line_data
とします。
# パラメータの設定
index_params = {
"metric_type": "COSINE", #コサイン類似度
"index_type": "HNSW",
"params": { "M": 16,"efConstruction": 200,"efSearch": 16 }
}
# techxchange_line_data に データの挿入
vector_store = Milvus.from_documents(
docs,
embeddings,
connection_args=my_connection_args,
index_params = index_params,
drop_old=True, #追加の場合はここをFalseに
collection_name = 'techxchange_line_data' # コレクション名
)
上記はベクトル化+データの挿入を実施していますが、もし既にデータの入っているMilvusのCollectionに接続するのみの場合は以下のように接続してください:
# 既存データを使う場合はこちらを実行
from langchain_milvus import Milvus
vector_store = Milvus(
embeddings,
connection_args=my_connection_args,
collection_name = 'techxchange_line_data'
)
13. 挿入データの確認
Milvus DBにロードした内容をDataFrameにダンプして表示させます。
AttuなどのGUIツールがあればそれを使用すれば見えますが、今回のハンズオンでは環境がないため、ダンプして表示してみます。
from pymilvus import MilvusClient
import pandas as pd
pk_list=vector_store.get_pks(expr="pk > 0")
client = MilvusClient(uri=my_connection_args['uri'], token=my_connection_args['token'])
res = client.get(
collection_name="techxchange_line_data",
ids=pk_list
)
for i, milvus_rec in enumerate(res):
vecter_data = milvus_rec['vector']
res[i]['vector']= "["+", ".join(map(str, vecter_data))+"]"
res[i]['pk']= str(milvus_rec['pk'])
# DataFrame df_s にダンプしたデータが入ります
df_s = pd.DataFrame.from_dict(res).reindex(columns=['ID', 'Category', 'text', 'pk', 'vector'])
# notebookの場合は以下で表示してきます
df_s
以上で「Part1: Excelをベクトル化してベクトルDB Milvusに入れよう」は完了です。
次のPart2: ベクトルDB Milvusに入ったデータで類似検索してみよう!に進んでください。