LangChain ドキュメントの読み込みと分割

以前の記事では手動でテキストを入力しましたが、実際のプロジェクトでは、ドキュメントは PDF、Web ページ、Markdown ファイルなどから取得される場合があります。

このセクションでは、Document Loader を使ってさまざまなドキュメントを読み込む方法と、Text Splitter を使ってドキュメントを検索に適した小さなチャンクに分割する方法を紹介します。


Document Loader——ドキュメントの読み込み

LangChain は数十種類のドキュメントローダーを提供しており、一般的なファイル形式をカバーしています:

Loaderソースインストールパッケージ
TextLoader.txt ファイルlangchain(組み込み)
PyPDFLoaderPDF ファイルlangchain-community + pypdf
WebBaseLoaderウェブページ URLlangchain-community + beautifulsoup4
CSVLoaderCSV ファイルlangchain-community
UnstructuredMarkdownLoaderMarkdown ファイルlangchain-community + unstructured

例

# テキストファイルを読み込む(組み込み、追加インストール不要)
from langchain_community.document_loaders import TextLoader

loader = TextLoader("knowledge.txt", encoding="utf-8")
docs = loader.load()

print(f"{len(docs)} 個のドキュメントを読み込みました")
print(f"内容プレビュー: {docs)

# ウェブページを読み込む
# pip install langchain-community beautifulsoup4
from langchain_community.document_loaders import WebBaseLoader

loader = WebBaseLoader("https://www.example.com/python/python-tutorial.html")
docs = loader.load()
print(f"\nウェブページの内容: {docs)

Text Splitter——ドキュメントの分割

ドキュメントは通常長すぎるため、効果的に検索するには小さなチャンク(chunk)に分割する必要があります。分割戦略は RAG の効果に直接影響します:

例

from langchain_text_splitters import RecursiveCharacterTextSplitter

# 分割器を作成
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=500,         # 各チャンクは最大500文字
    chunk_overlap=50,       # チャンク間は50文字重複
    separators=["\n\n", "\n", "。", "!", "?", ";", ",", " ", ""],
    # 段落、次に文、最後に文字の順で分割
)

# サンプルドキュメント
long_text = """サンプルは無料のプログラミング学習プラットフォームです。

このプラットフォームは、以下のような豊富なプログラミング言語チュートリアルを提供しています:
- Python チュートリアル:基本構文からデータ分析まで
- Java チュートリアル:オブジェクト指向プログラミングから Spring フレームワークまで
- フロントエンドチュートリアル:HTML、CSS、JavaScript とそのフレームワーク

すべてのチュートリアルには、詳細なコード例とオンライン実行環境が付属しています。
学習者は、学びながら練習することで、プログラミングスキルを素早く習得できます。"""


# ドキュメントを分割
chunks = text_splitter.split_text(long_text)

print(f"原文の長さ: {len(long_text)} 文字")
print(f"分割後: {len(chunks)} チャンク\n")

for i, chunk in enumerate(chunks):
    print(f"--- チャンク {i+1} ({len(chunk)} 文字) ---")
    print(chunk)
    print()

実行結果:

元の長さ: 153 字
分割後のチャンク: 3 块

--- 块 1 (54 字) ---
サンプルは無料のプログラミング学習プラットフォームです。
平台提供了丰富的编程语言教程,包括但不限于:

--- 块 2 (49 字) ---
- Python 教程:从基础语法到数据分析
- Java 教程:面向对象编程到 Spring 框架

--- 块 3 (50 字) ---
- 前端教程:HTML、CSS、JavaScript 及其框架
所有教程都配有详细的代码示例和在线运行环境。

chunk_overlap は非常に重要です。チャンク間に重複がないと、完全な文が半分に切られ、検索時に重要な情報を見逃す可能性があります。50〜100文字の重複が一般的な設定です。


分割パラメータ設定ガイド

シナリオchunk_sizechunk_overlap理由
FAQ 質疑応答200~50020~50質疑応答ペアは短いため、小さなチャンクで十分
技術ドキュメント500~100050~100技術的な内容にはより多くのコンテキストが必要
長文/論文1000~2000100~200段落の完全性を保つ必要がある
コードベース500~15000~50関数/クラスを自然な境界とする

完全なフロー:読み込み → 分割 → ベクトル化

例

from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_openai import OpenAIEmbeddings
from langchain_chroma import Chroma
# from langchain_community.document_loaders import TextLoader


# フロー 1:読み込み
# loader = TextLoader("サンプル_knowledge.txt", encoding="utf-8")
# docs = loader.load()

# デモのため、サンプルテキストを直接使用
docs = [
    "サンプルは無料のプログラミング学習ウェブサイトです。",
    "このウェブサイトでは、Python、Java、HTML など、さまざまなプログラミング言語のチュートリアルを提供しています。",
    "Python3 基礎チュートリアルは全30章で、初心者の入門学習に適しています。",
    "HTML 基礎チュートリアルは全25章で、フォーム、マルチメディアなどの内容を含みます。",
    "サンプルのすべての基礎チュートリアルは無料です。",
]

# フロー 2:分割
text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=100,
    chunk_overlap=20,
)
chunks = text_splitter.create_documents(docs)

# フロー 3:ベクトル化と保存
embeddings = OpenAIEmbeddings(model="text-embedding-3-small")
vector_store = Chroma.from_documents(
    documents=chunks,
    embedding=embeddings,
    persist_directory="./サンプル_db",
)

print(f"インデックスを作成しました:{len(chunks)} 個のドキュメントチャンク")

# フロー 4:検索
results = vector_store.similarity_search("Python チュートリアルは全部で何章ですか?", k=2)
for doc in results:
    print(f"検索結果: {doc.page_content}")

実行結果:

インデックス作成済み:5 个文档块
検索結果: Python3 基础教程共 30 章,适合零基础入门学习。
検索結果: サンプルは無料のプログラミング学習ウェブサイトです。
その他の拡張