LangChain で N 個の可能性を試した後、ブロックの秘密を発見しました。


チャンク化は、検索拡張世代 (RAG) (https://zilliz.com.cn/use-cases/llm-retrieval-augmented-generation) アプリケーションを構築する際の最も困難な問題です。チャンクとは、テキストを分割するプロセスのことを指します。非常に単純そうに見えますが、処理する必要がある詳細は数多くあります。テキスト コンテンツのタイプに応じて、さまざまなチャンク化戦略が必要になります。

このチュートリアルでは、同じテキストに対してさまざまなチャンキング戦略を使用して、さまざまなチャンキング戦略の効果を調べます。この記事に含まれるコードを入手するには、リンク (https://github.com/ytang07/llm-experimentation/blob/main/test_langchain_chunking.py) にアクセスしてください。


01.

LangChain ブロッキングの概要


LangChain は、ドキュメントのチャンク化とロードのための組み込みツールを備えた LLM 調整フレームワークです。このチャンク化チュートリアルは、チャンク化パラメータの設定と LLM の最小限の使用に焦点を当てています。つまり、関数を記述してそのパラメーターを設定することにより、ドキュメントをロードしてチャンク化し、結果をチャンク化されたテキスト ブロックとして出力します。以下に説明する実験では、この関数を通じて複数のパラメーター値を実行します。


  • LangChain チャンクコードのインポートとセットアップ


コードの最初の部分は主にツールのインポートとセットアップに関するものです。次のコードには多くの import ステートメントがあり、osdotenvはどちらも一般的に使用されます。これらは環境変数にのみ使用されます。


次に、LangChain とpymilvusに関連するコードについて詳しく説明します  。


まず、ドキュメントを取得するために使用される 3 つのインポートです。

NotionDirectoryLoader は、マークダウン/Notion ドキュメントを含むディレクトリをロードするために使用されます。その後、MarkdownHeader および RecursiveCharacter テキスト スプリッターは、ヘッダー (見出しスプリッター) または事前に選択された文字区切り文字のセット (再帰的スプリッター) に基づいてマークダウン ドキュメント内のテキストを分割します。


次に、レトリーバーのインポートです。Milvus、OpenAIEmbeddings モデル、OpenAI Large Language Model (LLM) を使用します。SelfQueryRetriever は LangChain のネイティブ レトリバーであり、ベクトル データベースが「それ自体にクエリ」を実行できるようにします。


最後の LangChain インポートはAttributeInfoで情報を含む属性を SelfQueryRetriever に渡します。


pymilvusインポートに関しては、通常、データベースをクリーンアップするために最後にのみ使用します。


関数を作成する前の最後のステップは、環境変数をロードし、いくつかの定数を宣言することです。headers_to_split_on変数には、マークダウンで分割するすべてのヘッダーがリストされます。パスは、LangChain が Notion ドキュメントの場所を理解するのに役立ちます。


import osfrom langchain.document_loaders import NotionDirectoryLoader
from langchain.text_splitter import MarkdownHeaderTextSplitter, RecursiveCharacterTextSplitter
from langchain.vectorstores import Milvus
from langchain.embeddings import OpenAIEmbeddings
from langchain.llms import OpenAI
from langchain.retrievers.self_query.base import SelfQueryRetriever
from langchain.chains.query_constructor.base import AttributeInfo
from pymilvus import connections, utility
from dotenv import load_dotenv


load_dotenv()
zilliz_uri = os.getenv("ZILLIZ_CLUSTER_01_URI")
zilliz_token = os.getenv("ZILLIZ_CLUSTER_01_TOKEN")


headers_to_split_on = [
("##", "Section"),
]
path='./notion_docs'


  • チャンク化された実験関数を構築する


チャンク実験関数の構築は、このチュートリアルの最も重要な部分です。前に述べたように、この関数にはファイルのインポートとチャンク化のためのいくつかのパラメーターが必要です。ドキュメントへのパス、分割するタイトル (スプリッター)、チャンク サイズ、チャンクの重複、およびコレクションを削除してデータベースをクリーンアップするかどうかを指定する必要があります。デフォルトでは、このパラメータは True に設定されています。これは、コレクションを削除してデータベースをクリーンアップすることを意味します。


不要なオーバーヘッドを避けるために、コレクションの作成と削除はできるだけ少なくする必要があることに注意してください。


関数の最初の部分では、Notion Directory Loader を介してパスからドキュメントがロードされます。ここでは、最初のページのコンテンツのみがキャプチャされます。


次にスプリッターを入手します。まず、マークダウン スプリッターを使用して、上で渡されたタイトルに基づいて分割します。次に、再帰的スプリッターを使用して、チャンク サイズとオーバーラップに基づいて分割します。


セグメンテーションが完了したら、環境変数、OpenAI 埋め込み、チャンキング ツール、およびコレクション名を使用して、LangChain Milvus インスタンスを初期化します。さらに、 SelfQueryRetriever がテキスト ブロックが属する「章」を理解できるように、 AttributeInfoオブジェクトを通じてメタデータ フィールドのリストも作成します。


上記の設定をすべて完了したら、LLM を取得し、SelfQueryRetriever に渡します。クローラーは、文書について質問するときに活躍します。また、どのチャンキング戦略をテストしているかを認識できるように関数を設定しました。最後に、コレクションはオンデマンドで削除できます。


def test_langchain_chunking(docs_path, splitters, chunk_size, chunk_overlap, drop_collection=True):


path=docs_path
loader = NotionDirectoryLoader(path)
docs = loader.load()
md_file=docs[0].page_content


# Let's create groups based on the section headers in our page
markdown_splitter = MarkdownHeaderTextSplitter(headers_to_split_on=splitters)
md_header_splits = markdown_splitter.split_text(md_file)


# Define our text splitter
text_splitter = RecursiveCharacterTextSplitter(chunk_size=chunk_size, chunk_overlap=chunk_overlap)
all_splits = text_splitter.split_documents(md_header_splits)


test_collection_name = f"EngineeringNotionDoc_{chunk_size}_{chunk_overlap}"


vectordb = Milvus.from_documents(documents=all_splits,
embedding=OpenAIEmbeddings(),
connection_args={"uri": zilliz_uri,
"token": zilliz_token},
collection_name=test_collection_name)


metadata_fields_info = [
AttributeInfo(
name="Section",
description="Part of the document that the text comes from",
type="string or list[string]"
),
]
document_content_description = "Major sections of the document"


llm = OpenAI(temperature=0)
retriever = SelfQueryRetriever.from_llm(llm, vectordb, document_content_description, metadata_fields_info, verbose=True)


res = retriever.get_relevant_documents("What makes a distinguished engineer?")
print(f"""Responses from chunking strategy:
{chunk_size}, {chunk_overlap}""")
for doc in res:
print(doc)


# this is just for rough cleanup, we can improve this# lots of user considerations to understand for real experimentation use cases thoughif drop_collection:
connections.connect(uri=zilliz_uri, token=zilliz_token)
utility.drop_collection(test_collection_name)

02.

LangChain チャンキングの実験と結果


さあ、エキサイティングな時間の到来です!チャンキング実験の結果を見てみましょう。


  • LangChain ブロッキングのテスト


次のコード ブロックは、実験的な関数を実行する方法を示しています。5 つの実験を追加しました。このチュートリアルでは、チャンキング長が 32 ~ 64、128、256、および 512 の範囲で、チャンキング オーバーラップが 4 ~ 8、16、32、および 64 の範囲であるチャンキング戦略をテストします。テストするには、タプルのリストを反復処理し、上で記述した関数を呼び出します。


chunking_tests = [(32, 4), (64, 8), (128, 16), (256, 32), (512, 64)]for test in chunking_tests:
test_langchain_chunking(path, headers_to_split_on, test[0], test[1])

以下は出力です。次に、各実験セットの出力結果を詳しく見てみましょう。私たちが使用したテスト問題は、「優れたエンジニアとは何ですか?」というものでした。



  • ブロック長 32、オーバーラップ 4



明らかに、32 という長さは短すぎるため、このチャンク化戦略は完全に無効です。


  • ブロック長64、オーバーラップ8



この戦略は最初はうまく機能しませんでしたが、最終的には質問に対する答えを与えてくれました - Amazon の最高技術責任者 (CTO) のヴェルナー・フォーゲルス氏。


  • ブロック長128、オーバーラップ16


長さが 128 になると、回答にはより完全な文が含まれ、「エンジニア」タイプの回答が少なくなるように見えます。この戦略はうまく機能し、ヴェルナー フォーゲルに関連したテキストの断片を抽出できます。ただし、この戦略の欠点は、 \xa0や \nなどの特殊文字が応答に現れること です 。チャンクの長さが長すぎる可能性があります。


  • ブロック長 256、オーバーラップ 32



回答は関連するコンテンツを返しますが、チャンクの長さが長すぎます。


  • ブロック長 512、オーバーラップ 64



ブロック長 256 は長すぎることが知られています。ただし、長さを 512 に設定すると、セクション全体の内容が抽出されます。この時点で、次のことを考慮する必要があります。結果として返されるテキストは 1行、それともセクションの内容全体でしょうか。利用シーンに応じて判断する必要があります。


03.

要約する


このチュートリアルでは、5 つの異なるチャンキング戦略の効果を検討します。チャンキング戦略を選択するときは、期待されるリターン結果に基づいて最適なチャンキング長を決定する必要があり、その後、さまざまなチャンキングの重複による影響をテストします。乞うご期待!


本文作者

Yujian Tang
Zilliz 开发者布道师

推荐阅读



本文分享自微信公众号 - ZILLIZ(Zilliztech)。
如有侵权,请联系 [email protected] 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

阿里云严重故障,全线产品受影响(已恢复) 汤不热 (Tumblr) 凉了 俄罗斯操作系统 Aurora OS 5.0 全新 UI 亮相 Delphi 12 & C++ Builder 12、RAD Studio 12 发布 多家互联网公司急招鸿蒙程序员 UNIX 时间即将进入 17 亿纪元(已进入) 美团招兵买马,拟开发鸿蒙系统 App 亚马逊开发基于 Linux 的操作系统,以摆脱 Android 依赖 Linux 上的 .NET 8 独立体积减少 50% FFmpeg 6.1 "Heaviside" 发布
{{o.name}}
{{m.name}}

おすすめ

転載: my.oschina.net/u/4209276/blog/10142197