教程連結 — https://youtu.be/w6wOhSThnoo
摘要是自然語言處理(NLP)的一個關鍵方面,它能夠將大量文字濃縮成簡潔的摘要。LangChain,作為NLP領域中的一個強大工具,提供了三種不同的摘要技術:stuff
、map_reduce
和refine
。每種方法都有其獨特的優點和侷限性,使它們適用於不同的情況。本文深入探討了這些技術的細節、它們的優缺點以及理想的應用場景。
教程中使用的完整實現程式碼和資料可在以下儲存庫中找到。
摘要技術
來自langchain
- Stuff Chain
stuff
鏈特別適用於處理大型文件。它的工作原理是將文件轉換為較小的塊,分別處理每個塊,然後將摘要組合起來生成最終摘要。這種方法適用於管理龐大的檔案,並且可以透過遞迴字元文字分割器的幫助來實現。
優點:
- 高效處理大型文件。
- 允許逐塊摘要,適合管理龐大的檔案。
缺點:
- LLM上下文視窗
from langchain.chains.combine_documents.stuff import StuffDocumentsChain
from langchain.chains.llm import LLMChain
from langchain.prompts import PromptTemplate # 定義提示
prompt_template = """Write a concise summary of the following:
"{text}"
CONCISE SUMMARY:"""
prompt = PromptTemplate.from_template(prompt_template)
# 定義 LLM 鏈
llm = ChatOpenAI(temperature=0, model_name="gpt-3.5-turbo-16k")
llm_chain = LLMChain(llm=llm, prompt=prompt)
# 定義 StuffDocumentsChain
stuff_chain = StuffDocumentsChain(llm_chain=llm_chain, document_variable_name="text")
docs = loader.load()
print(stuff_chain.run(docs))
Map-Reduce 方法
對映-歸約方法涉及分別對每個文件進行摘要(對映步驟),然後將這些摘要組合成最終摘要(歸約步驟)。這種方法更可擴充套件,並且可以處理更大量的文字。map_reduce
技術旨在摘要超出語言模型令牌限制的大型文件。它涉及將文件分成塊,為每個塊生成摘要,然後將這些摘要組合起來建立最終摘要。這種方法對處理大型檔案高效,並且顯著減少了處理時間。
優點:
- 透過將大型文件分成可管理的塊來有效處理。
- 透過分別處理塊來減少處理時間。
缺點:
- 需要額外的步驟來組合單獨的摘要,這可能會增加過程的複雜性。
以下是如何實現對映-歸約方法的示例:
from langchain.chains import MapReduceDocumentsChain, ReduceDocumentsChain
from langchain_text_splitters import CharacterTextSplitter # 對映
map_template = """The following is a set of documents
{docs}
Based on this list of docs, please identify the main themes
Helpful Answer:"""
map_prompt = PromptTemplate.from_template(map_template)
map_chain = LLMChain(llm=llm, prompt=map_prompt)
# 歸約
reduce_template = """The following is set of summaries:
{docs}
Take these and distill it into a final, consolidated summary of the main themes.
Helpful Answer:"""
reduce_prompt = PromptTemplate.from_template(reduce_template)
reduce_chain = LLMChain(llm=llm, prompt=reduce_prompt)
# 透過對映鏈組合文件,然後組合結果
map_reduce_chain = MapReduceDocumentsChain(
llm_chain=map_chain,
reduce_documents_chain=reduce_documents_chain,
document_variable_name="docs",
return_intermediate_steps=False,
)
text_splitter = CharacterTextSplitter.from_tiktoken_encoder(chunk_size=1000, chunk_overlap=0)
split_docs = text_splitter.split_documents(docs)
print(map_reduce_chain.run(split_docs))
Refine 方法
Refine方法透過迴圈遍歷輸入文件來迭代更新其答案。對於每個文件,它將所有非文件輸入、當前文件和最新的中間答案傳遞給LLM鏈以獲得新答案。這種方法適用於根據新上下文細化摘要。
refine
技術是map_reduce
技術的簡單替代方案。它涉及為第一個塊生成摘要,將其與第二個塊組合,生成另一個摘要,並繼續這個過程,直到最終摘要完成。這種方法適用於大型文件,但與map_reduce
相比,需要的複雜性較小。
優點:
- 比
map_reduce
技術更簡單。 - 對於大型文件,以較小的複雜性實現了類似的結果。
缺點:
- 與其它技術相比,功能有限。
以下是如何實現Refine方法的示例:
from langchain.chains.summarize import load_summarize_chain
prompt = """
Please provide a summary of the following text.
TEXT: {text}
SUMMARY:
"""
question_prompt = PromptTemplate(
template=question_prompt_template, input_variables=["text"]
)
refine_prompt_template = """
Write a concise summary of the following text delimited by triple backquotes.
Return your response in bullet points which covers the key points of the text.
```{text}```
BULLET POINT SUMMARY:
"""
refine_template = PromptTemplate(
template=refine_prompt_template, input_variables=["text"]
# Load refine chain
chain = load_summarize_chain(
llm=llm,
chain_type="refine",
question_prompt=question_prompt,
refine_prompt=refine_prompt,
return_intermediate_steps=True,
input_key="input_documents",
output_key="output_text",
)
result = chain({"input_documents": split_docs}, return_only_outputs=True)
選擇合適的技術
摘要技術的選擇取決於當前任務的具體要求。對於大型文件,建議使用map_reduce
和refine
技術,因為它們能夠有效地進行分塊摘要。stuff
鏈特別適合於太大而無法一次性處理的文件,為管理龐大的檔案提供了實用的解決方案。
每種方法都有其優勢,適用於不同場景。Stuff方法簡單但可能不適用於處理大量文字。Map-Reduce方法更可擴充套件,可以處理更大的文件,但需要更多的設定。Refine方法適用於基於新上下文迭代細化摘要,使其成為動態摘要任務的良好選擇。