「カスタマイズされたLLMパワードAIアシスタントで研究を強化する」
「研究を強化するためのカスタマイズされたLLMパワードAIアシスタント」
イントロダクション
情報が溢れる世界で、効率的に関連データにアクセスし抽出することは非常に貴重です。ResearchBotは、OpenAIのLLM(Large Language Models)とLangchainを組み合わせた情報検索のための先進的なLLMパワードアプリケーションプロジェクトです。この記事は、自分自身でResearchBotを作成し、現実の生活でどのように役立つかのステップバイステップガイドのようなものです。まるでデータの海から必要な情報を見つける知的なアシスタントを持っているようなものです。コーディングが好きであるかAIに興味があるかにかかわらず、このガイドは、カスタマイズされたLLMパワードAIアシスタントを使用して研究を強化するのに役立つものです。これは、LLMの潜在能力を引き出し、情報へのアクセス方法を革新するための旅です。
学習目標
- LLM(Large Language Models)、Langchain、ベクトルデータベース、埋め込みなど、より深い概念を理解する。
- LLMとResearchBotのリアルワールドの応用例を研究、カスタマーサポート、コンテンツ生成などの分野で探求する。
- 既存のプロジェクトやワークフローにResearchBotを統合するためのベストプラクティスを見つけ、生産性と意思決定を改善する。
- データの抽出とクエリの回答のプロセスを簡素化するためにResearchBotを構築する。
- LLMテクノロジーの動向を把握し、情報へのアクセスと使用方法を革新する潜在能力について最新の情報を得る。
この記事はデータサイエンスブロガソンの一部として公開されました。
ResearchBotとは何ですか?
ResearchBotは、LLM(Large Language Models)によって動力を得る研究アシスタントです。さまざまな業界のプロフェッショナルにとって素晴らしいパートナーとなり、コンテンツを迅速にアクセスし要約することができる革新的なツールです。
複数の記事、文書、ウェブページを読み理解し、関連性のある短い要約を提供できる個人的なアシスタントを想像してみてください。私たちのResearchBotは、研究目的に必要な時間と労力を削減することを目指しています。
実世界の使用例
- 金融分析: 最新の市場ニュースを把握し、金融に関するクエリに素早く回答します。
- ジャーナリズム: 記事のための背景情報、ソース、参考資料を効率的に収集します。
- 医療: 研究目的のための現在の医学研究論文と要約にアクセスします。
- 学術: 関連する学術論文、研究資料、研究の質問に対する回答を見つけます。
- 法律研究: 法的文書、判例、法的問題に関する洞察を迅速に取得します。
技術用語
ベクトルデータベース
テキストデータのベクトル埋め込みを効率的に類似度ベースの検索を行うためのコンテナ。
セマンティックサーチ
キーワードの完全な一致に完全に依存せずに、ユーザーのクエリの意図と文脈を理解して検索を行うこと。
埋め込み
テキストデータの効率的な比較と検索を可能にする数値表現。
プロジェクトの技術的アーキテクチャ
- 埋め込みモデルを使用して、インデックス化する必要のある情報またはコンテンツのベクトル埋め込みを作成します。
- ベクトル埋め込みは、元のコンテンツへの参照を持つベクトルデータベースに挿入されます。
- アプリケーションがクエリを発行すると、同じ埋め込みモデルを使用してクエリの埋め込みを作成し、その埋め込みを使用してデータベース内の類似したベクトル埋め込みをクエリします。
- これらの類似した埋め込みは、それらを作成した元のコンテンツに関連付けられます。
ResearchBotはどのように機能しますか?
このアーキテクチャは、コンテンツの保存、検索、およびインタラクションを容易にし、ResearchBotを情報検索と分析のための強力なツールにします。ベクトル埋め込みとベクトルデータベースを活用して、素早く正確なコンテンツの検索を実現します。
コンポーネント
- ドキュメント:これらは、将来の参照や検索のためにインデックス化したい記事またはコンテンツです。
- スプリッツ:これは、ドキュメントをより小さな、扱いやすいチャンクに分割するプロセスを処理します。大きなドキュメントや記事に対しては重要であり、言語モデルの制約に完全にフィットし、効率的なインデックス化が行われるようにします。
- ベクトルデータベース:ベクトルデータベースはアーキテクチャの重要な部分です。コンテンツから生成されたベクトル埋め込みを格納します。各ベクトルはそれが派生した元のコンテンツと関連付けられており、数値的な表現とソース素材との間にリンクを作ります。
- 検索:ユーザーがシステムをクエリすると、同じ埋め込みモデルがクエリ用の埋め込みを作成するために使用されます。これらのクエリ埋め込みは、類似のベクトル埋め込みを検索するためにベクトルデータベースを検索するために使用されます。結果は、それぞれの元のコンテンツソースと関連付けられた大きなグループの類似ベクトルです。
- プロンプト:ユーザーがシステムと対話する場所が定義されています。ユーザーはクエリを入力し、システムはこれらのクエリを処理してベクトルデータベースから関連する情報を検索し、ソースコンテンツへの回答と参照を提供します。
LangChainのドキュメントローダー
ドキュメントローダーを使用して、ドキュメントの形式でソースからデータを読み込みます。ドキュメントはテキストと関連するメタデータの一部です。たとえば、簡単な.txtファイルを読み込むためのドキュメントローダーや、記事やブログのテキストコンテンツを読み込むためのドキュメントローダー、YouTubeビデオのトランスクリプトを読み込むためのドキュメントローダーなどがあります。
多種多様な種類のドキュメントローダーが存在します:
例 – TextLoader
このコードでは、LangChainのTextLoaderの機能を示しています。既存のファイル「Langchain.txt」からテキストデータをTextLoaderクラスに読み込み、さらなる処理に向け準備を行います。「file_path」変数には将来の目的のためにロードされるファイルのパスが格納されています。
# langchain.document_loadersモジュールからTextLoaderクラスをインポートfrom langchain.document_loaders import TextLoader# ロードするファイルを指定してTextLoaderクラスを考慮する。ここでは「Langchain.txt」となっています。loader = TextLoader("Langchain.txt")# 提供されたファイル(「Langchain.txt」)からコンテンツをTextLoaderクラスにロードするloader.load()# 'loader'インスタンスのタイプを確認する('TextLoader'である必要があります)type(loader)# TextLoaderに関連付けられたファイルパスを'file_path'変数で確認するloader.file_path
LangChainのテキストスプリッター
テキストスプリッターはドキュメントをより小さなドキュメントに分割する責任を持ちます。これにより、コンテンツの処理を効率的に行いやすくなります。ResearchBotプロジェクトの文脈では、テキストスプリッターを使用してデータをさらなる分析と検索のために準備します。
なぜテキストスプリッターが必要なのでしょうか?
LLMはトークンの制限があります。そのため、トークン制限内に収まるように大きなテキストを小さなチャンクに分割する必要があります。
テキストをチャンクに分割する手動の方法
# Wikipediaからいくつかのランダムなテキストを取得しますtext# LLMのトークン制限が100であると仮定します。コードでは以下のように簡単にできますtext[:100]
しかし、完全な単語を希望し、テキスト全体でこれを行いたい場合は、Pythonのsplit関数を使用することができます。
words = text.split(" ")len(words)chunks = []s = ""for word in words: s += word + " " if len(s)>200: chunks.append(s) s = "" chunks.append(s)chunks[:2]
データをチャンクに分割することは、ネイティブのPythonで行うことができますが、手間のかかるプロセスです。また、必要に応じて、各チャンクがそれぞれのLLMのトークン長制限を超えないように、複数の区切り文字を連続して実験する必要があります。
Langchainでは、テキスト分割クラスを通じてより良い方法が提供されています。Langchainには、これを行うための複数のテキスト分割クラスがあります。
1. 文字テキストスプリッター
このクラスは、特定の区切り記号に基づいてテキストを小さなチャンクに分割するために設計されています。段落、ピリオド、カンマ、および改行(\n)のようなものです。テキストをさらなる処理のために複数のチャンクに分解するのにより便利です。
from langchain.text_splitter import CharacterTextSplittersplitter = CharacterTextSplitter( separator = "\n", chunk_size=200, chunk_overlap=0)chunks = splitter.split_text(text)len(chunks)for chunk in chunks: print(len(chunk))
ご覧の通り、200チャンクサイズを指定しても、\nに基づいて分割されるため、サイズ200より大きなチャンクが作成されています。
Langchainからは、テキストを再帰的に区切るための別のクラスを使用することができます。このクラスはRecursiveTextSplitterです。それがどのように機能するか見てみましょう。
2. 再帰テキストスプリッター
これはテキストの文字を再帰的に解析して動作する一種のテキストスプリッターです。テキストを異なる文字で分割しようとし、異なる文字の組み合わせを繰り返し特定し、テキストを効果的に分割してさまざまなタイプのシェルを見つけるまで行います。
from langchain.text_splitter import RecursiveCharacterTextSplitterr_splitter = RecursiveCharacterTextSplitter( separators = ["\n\n", "\n", " "], # 区切り記号のリスト chunk_size = 200, # 作成される各チャンクのサイズ chunk_overlap = 0, # チャンク間の重複のサイズ length_function = len # サイズを計算するための関数,)chunks = r_splitter.split_text(text)for chunk in chunks: print(len(chunk)) first_split = text.split("\n\n")[0]first_splitlen(first_split) second_split = first_split.split("\n")second_splitfor split in second_split: print(len(split)) second_split[2]second_split[2].split(" ")
これらのチャンクがどのように形成されたかを理解しましょう:
再帰テキストスプリッターは、区切り記号のリスト、すなわちseparators = [“\n\n”, “\n”, “.”]を使用します。
したがって、最初に\n\nで分割し、その結果のチャンクサイズがこの場面では200を超えている場合、次のセパレータである\nを使用します。
Third split exceeds chunk size 200. Now it will further try to split that using the third separator which is ’ ’ (space)
この場合、スペース(すなわちsecond_split[2].split(” “))を使用して分割すると、各単語が分離され、それらのチャンクがサイズが200に近くなるようにマージされます。
ベクトルデータベース
では、何百万、さらには何十億もの単語の埋め込みを保存する場面を考えてみましょう。それは現実世界のアプリケーションでは重要な場面です。関係データベースは、構造化データを保存する能力はあるものの、そのような大量のデータを扱う能力に制限があります。
ここで登場するのが、ベクトルデータベースです。ベクトルデータベースは、ベクトルデータを効率的に保存して取得するために設計されており、単語の埋め込みに適しています。
ベクトルデータベースは、意味検索を利用することで情報の検索を革新しています。単語の埋め込みとスマートなインデックス技術のパワーを活用して、検索をより高速かつ正確に行うことができます。
ベクトルインデックスとベクトルデータベースの違いは何ですか?
独立したベクトルインデックス(たとえばFAISS(Facebook AI Similarity Search))は、ベクトル埋め込みの検索と取得を改善することができますが、1つのデータベースの中で存在する機能がない場合もあります。一方、ベクトルデータベースは、ベクトル埋め込みを管理するために特別に設計されており、独立したベクトルインデックスを使用することに比べて多くの利点を提供します。
手順:
1:テキストカラムのソース埋め込みを作成する
2:ベクトルのためのFAISSインデックスを構築する
3:ソースベクトルを正規化し、インデックスに追加する
4:同じエンコーダーを使用して検索テキストをエンコードし、出力ベクトルを正規化する
5:作成されたFAISSインデックスで類似のベクトルを検索する
df = pd.read_csv("sample_text.csv")df# Step 1 : Create source embeddings for the text columnfrom sentence_transformers import SentenceTransformerencoder = SentenceTransformer("all-mpnet-base-v2")vectors = encoder.encode(df.text)vectors# Step 2 : Build a FAISS Index for vectorsimport faissindex = faiss.IndexFlatL2(dim)# Step 3 : Normalize the source vectors and add to indexindex.add(vectors)index# Step 4 : Encode search text using same encodersearch_query = "looking for places to visit during the holidays"vec = encoder.encode(search_query)vec.shapesvec = np.array(vec).reshape(1,-1)svec.shape# Step 5: Search for similar vector in the FAISS indexdistances, I = index.search(svec, k=2)distancesrow_indices = I.tolist()[0]row_indicesdf.loc[row_indices]
このデータセットを確認すると、
これらのテキストを単語の埋め込みを使用してベクトルに変換します
検索クエリとして”looking for places to visit during the holidays”を考慮すると
Travel Categoryに関連するクエリに基づいてもっとも類似した2つの結果を提供しています。
検索クエリを実行すると、データベースはLocality-Sensitive Hashing(LSH)といった技術を使用してプロセスを高速化します。LSHは類似したベクトルをバケットにグループ化し、より速くてターゲットにした検索が可能になります。つまり、クエリベクトルをすべての保存されたベクトルと比較する必要はありません。
リトリーバル
ユーザーがシステムにクエリを送信すると、同じ埋め込みモデルがクエリのための埋め込みを作成するために使用されます。これらのクエリ埋め込みは、ベクトルデータベースを検索するために使用され、類似のベクトル埋め込みと関連する元のコンテンツソースと一緒に取得されます。
リトリーバルの課題
セマンティックサーチでのリトリーバルには、GPT-3などの言語モデルによって設けられるトークン制限など、いくつかの課題があります。関連するデータチャンクが複数存在する場合、応答の制限を超えることがあります。
スタッフメソッド
このモデルでは、ベクトルデータベースから関連するデータチャンクを収集し、それらをプロンプト(個々の)に組み合わせることが含まれます。このプロセスの主な欠点は、トークンの制限を超えることであり、それによって不完全な応答が生成されることです。
マップリデュースメソッド
トークン制限の課題を克服し、リトリーバルQAプロセスをスムーズにするために、このプロセスは関連チャンクをプロンプト(個々の)に結合する代わりに、4つのチャンクがある場合はすべてを分離されたLLMに渡します。これらの質問は文脈情報を提供し、言語モデルが各チャンクの内容に焦点を当てることができます。これにより、各チャンクに対して単一の回答のセットが生成されます。最後に、すべての単独の回答を組み合わせて、各チャンクから収集された洞察に基づいて最適な回答を見つけるために最終のLLM呼び出しが行われます。
ResearchBotのワークフロー
(1) データの読み込み
このステップでは、テキストやドキュメントなどのデータがインポートされ、さらなる処理のために準備され、分析に利用できる状態になります。
#データのスクレイピングのためのURLを提供する loaders = UnstructuredURLLoader(urls=[ "", ""])data = loaders.load() len(data)
(2) データの分割
データは小さな、より管理しやすいセクションまたはチャンクに分割され、大量のテキストやドキュメントの効率的な処理と取り扱いを容易にします。
text_splitter = RecursiveCharacterTextSplitter( chunk_size=1000, chunk_overlap=200)#チャンクを取得するためにsplit_textではなくsplit_documentsを使用します。docs = text_splitter.split_documents(data)len(docs)docs[0]
(3) これらのチャンクの埋め込みの作成とFAISSインデックスへの保存
テキストチャンクは、数値ベクトル表現(埋め込み)に変換され、Faissインデックスに格納されます。これにより、類似したベクトルの検索が最適化されます。
#openAIEmbeddingsを使用して、チャンクの埋め込みを作成しますembeddings = OpenAIEmbeddings()#ドキュメントと埋め込みを渡して、FAISSベクトルインデックスを作成しますvectorindex_openai = FAISS.from_documents(docs, embeddings)#ローカルに作成されたベクトルインデックスを保存しますfile_path="vector_index.pkl"with open(file_path, "wb") as f: pickle.dump(vectorindex_openai, f) if os.path.exists(file_path): with open(file_path, "rb") as f: vectorIndex = pickle.load(f)
(4) 特定の質問に対して類似の埋め込みを取得し、LLMを呼び出して最終的な回答を取得する
特定のクエリに対して類似の埋め込みを取得し、これらのベクトルを言語モデル(LLM)との対話に使用して情報検索を効率化し、ユーザーの質問に対する最終的な回答を提供します。
# 必要なパラメータでLLMを初期化する
llm = OpenAI(temperature=0.9, max_tokens=500)
chain = RetrievalQAWithSourcesChain.from_llm(
llm=llm,
retriever=vectorIndex.as_retriever()
)
chainquery = "" #クエリを入力してください
chain.debug=True
chain({"question": query}, return_only_outputs=True)
最終アプリケーション
これらのステージ(ドキュメントローダー、テキストスプリッター、ベクトルDB、検索、プロンプト)を使用し、streamlitのヘルプを借りてアプリケーションを作成しました。ResearchBotの構築が完了しました。
これはページ内のセクションで、ブログや記事のURLが挿入されます。私は2023年にリリースされた最新のiPhoneモバイルのリンクを入れました。このResearchBotの構築を始める前に、みなさんはChatGPTが既にあるのでなぜResearchBotを構築しているのか疑問に思うでしょう。ここに答えがあります。
ChatGPTの回答:
ResearchBotの回答:
ここで私のクエリは「Apple iPhone 15の価格はいくらですか?」
このデータは2023年のもので、ChatGPT 3.5には存在しませんが、私たちはResearchBotを最新のiPhoneに関する情報でトレーニングしました。したがって、ResearchBotによって求めていた回答を得ました。
ChatGPTを使用する際の3つの課題は以下の通りです:
- 記事の内容をコピー&ペーストすることが煩雑です。
- 集約された知識ベースが必要です。
- 単語制限 – 3000単語
結論
実世界のシナリオでセマンティックサーチとベクトルデータベースの概念を目撃しました。ResearchBotはセマンティックサーチを使用してベクトルデータベースから効率的に回答を取得する能力を持ち、情報検索と質問応答システムの領域において深いLLMs(adv)の驚異的な潜在能力を示しています。重要な情報を高い能力と検索機能で簡単に見つけて要約することができる、非常に需要の高いツールを作りました。知識を求める人にとって、これは強力なソリューションです。この技術は情報検索と質問応答システムに新たな可能性を開き、データ駆動型の洞察を求める人々にとってゲームチェンジャーとなります。
よくある質問
この記事に表示されるメディアはAnalytics Vidhyaの所有ではなく、著者の裁量で使用されています。
We will continue to update VoAGI; if you have any questions or suggestions, please contact us!
Was this article helpful?
93 out of 132 found this helpful
Related articles