見出し画像

LangChainの新機能:メタデータを保持するTextSplitter

LangChain 0.0.203で実装された、Markdownファイルのヘッダ情報をメタデータとして保持しながらテキスト分割を行う、MarkdownHeaderTextSplitter 機能を試してみました。

1.前準備(Google Colab)

# ライブラリーのインストール
!pip install langchain
!pip install openai
!pip install chromadb
!pip install tiktoken

# 環境変数の準備
import os
os.environ["OPENAI_API_KEY"] = "Your OPENAI_API_KEY"

今回はサンプルとしてlangchainのgithubのREADME.mdを使ってみます。(適宜ダウンロードして/contentフォルダに保存してください。)

path ="./README.md"
with open(path) as f:
    md = f.read()
    print(md)

# 🦜️🔗 LangChain
⚡ Building applications with LLMs through composability ⚡
(以下省略)

2.ヘッダーを指定してテキスト分割

  • MarkdownHeaderTextSplitterに、分割するヘッダーの種類および、分割方法として、return_each_line=Trueを指定して各行ごとに分割します。

  • return_each_line=Trueを指定しない場合は、ヘッダーで区切られたマークダウンの章・項ごとに分割されます。

from langchain.text_splitter import MarkdownHeaderTextSplitter

headers_to_split_on = [
    ("#", "Header 1"),
    ("##", "Header 2"),
    ("###", "Header 3"),
    ("####", "Header 4"),
]

markdown_splitter = MarkdownHeaderTextSplitter(
    headers_to_split_on=headers_to_split_on, 
    return_each_line=True
)
texts = markdown_splitter.split_text(md)
for text in texts:
    print(text)
  • 分割により、分割したテキストのcontent、およびメタデータmetadataとしてヘッダー情報が付与されたリストが返却されます。

{'content': '⚡ Building applications with LLMs through composability ⚡', 'metadata': {'Header 1': '🦜️🔗 LangChain'}}

(以下省略)

3.メタデータの活用

  • 分割したメタデータ付きのテキストをベクトルDBに保存して、RetrievalQAで試してみます。

# ベクトルDBの定義
from langchain.vectorstores import Chroma
from langchain.embeddings import OpenAIEmbeddings

embeddings = OpenAIEmbeddings()
vectordb = Chroma.from_texts([text['content'] for text in texts], embeddings, metadatas=[text['metadata'] for text in texts])

ChromaDBに保存時、embeddingsに加えて、metadatasを指定してテキスト毎のメタデータを保存します。

# RetrivalQAを定義
from langchain.chains import RetrievalQA
from langchain.chat_models import ChatOpenAI

qa = RetrievalQA.from_chain_type(llm=ChatOpenAI(), chain_type="stuff", retriever=vectordb.as_retriever(), return_source_documents=True)

4.検索実行

query = "What is langchain?"
result = qa({"query": query})

LangChain is a tool that provides a standard interface for chains and end-to-end chains for common applications. It involves sequences of calls to various utilities and offers integrations with other tools. It is available in a JavaScript/TypeScript version as well.

  • RetrievalQAにクエリを渡すと、'query'、'result'、'source_documents' をキーにした辞書リストが返ってきます。

5.ソース情報の表示

'source_documents'の中身は 'page_content'と 'metadata' です。

result["source_documents"]

[Document(page_content='Chains go beyond a single LLM call and involve sequences of calls (whether to an LLM or a different utility). LangChain provides a standard interface for chains, lots of integrations with other tools, and end-to-end chains for common applications.', metadata={'Header 1': '🦜️🔗 LangChain', 'Header 2': '🚀 What can this help with?'}),
(中略)
, Document(page_content='There are six main areas that LangChain is designed to help with.\nThese are, in increasing order of complexity:', metadata={'Header 1': '🦜️🔗 LangChain', 'Header 2': '🚀 What can this help with?'})]

for doc in result["source_documents"]:
    print(doc.metadata)

{'Header 1': '🦜️🔗 LangChain', 'Header 2': '🚀 What can this help with?'} {'Header 1': '🦜️🔗 LangChain'}
{'Header 1': '🦜️🔗 LangChain'}
{'Header 1': '🦜️🔗 LangChain', 'Header 2': '🚀 What can this help with?'}

6.まとめ

  • MarkdownHeaderTextSplitterを使うことで、「Markdownファイルの段落情報」と「埋め込みテキスト」がいい感じに紐付けできることが分かりました。

  • この機能を使うと、QAシステムを制作する場合などに、LLMからの回答に加えて、根拠となるマニュアルの章の名前や、法律の条文などの情報を簡単に付帯させることができると思います。想像以上に使い道があるかもしれませんね。すばらしい。

  • 今後、Markdown以外でも、PDF等もろもろのファイルの読み込み、書き出しがメタデータ対応になっていくと思います。たのしみです。

現場からは以上です。


この記事が気に入ったらサポートをしてみませんか?