探索LangGraph的强大功能:从MapReduceDocumentsChain迁移到LangGraph实现

234 阅读3分钟
# 探索LangGraph的强大功能:从MapReduceDocumentsChain迁移到LangGraph实现

## 引言

在处理长文本时,MapReduceDocumentsChain提供了一种有效的策略,通过将文本拆分为更小的文档,执行映射操作,然后整合结果。然而,随着需求的演变和工具的更新,LangGraph作为一种更灵活的解决方案应运而生。本文将详细介绍如何从MapReduceDocumentsChain迁移到LangGraph,以实现更高效的文本处理。

## 主要内容

### MapReduceDocumentsChain的实现

首先,让我们回顾一下MapReduceDocumentsChain的工作流程。它通过以下步骤来处理文本:

1. **拆分**:将长文本拆分为更小的文档。
2. **映射**:对小文档应用处理,如文本总结。
3. **归约**:合并处理结果,通常是通过递归的方式生成最终总结。

以下是一个示例代码,展示了MapReduceDocumentsChain的实现:

```python
from langchain.chains import MapReduceDocumentsChain, ReduceDocumentsChain
from langchain.chains.llm import LLMChain
from langchain_core.prompts import ChatPromptTemplate

# 定义用于映射和归约的提示模板
map_template = "Write a concise summary of the following: {docs}."
reduce_template = """
The following is a set of summaries:
{docs}
Take these and distill it into a final, consolidated summary
of the main themes.
"""

# 创建Map和Reduce链
map_prompt = ChatPromptTemplate([("human", map_template)])
map_chain = LLMChain(llm=llm, prompt=map_prompt)

reduce_prompt = ChatPromptTemplate([("human", reduce_template)])
reduce_chain = LLMChain(llm=llm, prompt=reduce_prompt)

# 使用MapReduceDocumentsChain进行处理
map_reduce_chain = MapReduceDocumentsChain(
    llm_chain=map_chain,
    reduce_documents_chain=ReduceDocumentsChain(
        combine_documents_chain=StuffDocumentsChain(llm_chain=reduce_chain, document_variable_name="docs"),
        token_max=1000
    )
)

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"})]

result = map_reduce_chain.invoke(documents)
print(result["output_text"])

输出总结各类水果的颜色,通过Map和Reduce步骤实现了文本处理的分工与集成。

LangGraph的实现

LangGraph提供了更灵活的图形化工作流,允许实时流处理和错误恢复。以下是使用LangGraph实现相同功能的示例:

import operator
from typing import Annotated, List, TypedDict
from langgraph.graph import StateGraph, Send, START, END

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]}

def map_summaries(state: OverallState):
    return [Send("generate_summary", {"content": content}) for content in state["contents"]]

async def generate_final_summary(state: OverallState):
    response = await reduce_chain.ainvoke(state["summaries"])
    return {"final_summary": 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)

LangGraph允许通过图形结构实时监控和干预执行步骤,这对于复杂的文本处理任务尤其有用。

常见问题和解决方案

总结和进一步学习资源

LangGraph提供了一种灵活而强大的方式来处理大量文本,特别是在需要多次处理和重复归约的场景中。推荐的进一步学习资源包括:

参考资料

如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!

---END---