🐥

LangChainを使った文章の要約方法

2023/05/06に公開

データの準備

from langchain import OpenAI, PromptTemplate, LLMChain
from langchain.chains.mapreduce import MapReduceChain
from langchain.prompts import PromptTemplate

# 要約に使用したいモデルを定義
llm = OpenAI(temperature=0)

long_text = "(要約したい長文)"

from langchain.text_splitter import CharacterTextSplitter
# 長文を分割するオブジェクトを定義
text_splitter = CharacterTextSplitter()

# 要約したい長文の分割
texts = text_splitter.split_text(long_text)


from langchain.docstore.document import Document
# 分割した長文を書く文章ごとにDocumentオブジェクト化
docs = [Document(page_content=t) for t in texts]

要約の実行

from langchain.chains.summarize import load_summarize_chain

chain = load_summarize_chain(llm=llm, 
														 chain_type="map_reduce", # 要約の仕方 stuff, map_reduce, refineから選ぶ
														 return_intermediate_steps=True # 分割された文章ごとの要約結果を返すか
               )

# 要約の実行
chain.run(docs)

chain_typeについて

stuff

  • 分割された文章を一つの文章にまとめてプロンプトに詰め込み、言語モデルに渡す
  • 文章サイズが入力トークンを超える場合には使えない

map_reduce

  • 分割された文章ごとにプロンプトを作成して、プロンプトを一つずつ言語モデルに渡し、返ってきた複数の結果を結合してプロンプトに詰め込み、再度言語モデルに渡す
  • 複数のプロンプトを言語モデルに渡す処理は並列で実行されるため処理は早い
  • 文章ごとに要約した後、要約結果を再度要約するためプロンプトの設定によっては情報が欠落する

refine

  • 分割された文章を順番に処理する。この際、前の文章の言語モデルの結果を次の文章の入力に使用するため情報の欠落が少ない
  • ただし、処理を順番に実行するため、処理が遅くなる

トークンの制限を超える長文を要約する場合には、map_reduceかrefineを使わないと処理できない

要約させるプロンプトのカスタマイズ方法

stuff

公式ドキュメント

map_reduce

https://python.langchain.com/en/latest/modules/chains/index_examples/summarize.html#the-map-reduce-chain

プロンプトの設定をファイルに書き出し

{
    "_type": "prompt",
    "input_variables": ["text", "reference"],
    "template_path": "map_prompt_template.txt"
}

map_promptでは、要約させずエッセンス的なのを箇条書きにさせる方が情報の欠落が少なそう

あなたの仕事は与えられた文章から重要なエッセンスを抽出することです。文章と参考文書が与えられた場合、参考文章に関する内容についてのエッセンスを箇条書きにして、日本語で書き出してください。

文章:{text}
参考文章:{reference}
{
    "_type": "prompt",
    "input_variables": ["text"],
    "template_path": "prompt_templates/combine5.txt"
}
あなたの仕事は箇条書きのリストを整理することです。箇条書きのリストが与えられた場合、内容が重複する箇所はひとつの文章にまとめた箇条書きのリストを書き出してください。

箇条書きのリスト:{text}

プロンプトのカスタム方法

long_text = "(要約したい長文)"
chat = ChatOpenAI(model_name='gpt-3.5-turbo',
                  max_tokens=512)
texts = text_splitter.split_text(long_text)
docs = [Document(page_content=t) for t in texts[:]]

map_prompt_template_path = 'map_prompt.json'
combine_prompt_template_path = 'combine_prompt.json'

chain = load_summarize_chain(llm, 
                             chain_type="map_reduce", return_intermediate_steps=True, 
                             map_prompt=load_prompt(map_prompt_template_path), # load_promptはpromtの設定をファイルで読み込んでいる。json, py, yamlファイルで読み込める
                             combine_prompt=load_prompt(combine_prompt_template_path))
result = chain({"input_documents": docs, 'reference':reference}, return_only_outputs=True)

refine

https://python.langchain.com/en/latest/modules/chains/index_examples/summarize.html#the-refine-chain

Discussion