引言
在处理长文本时,RefineDocumentsChain提供了一种有效的分析策略。它通过将文本分割为较小的文档,依次处理并逐渐完善结果。然而,随着技术的进步,LangGraph实现能够提供更多优势,如监控执行步骤、支持逐步执行结果流等。本文将详细探讨如何从RefineDocumentsChain迁移到LangGraph,并用实际代码示例说明这一转变。
主要内容
RefineDocumentsChain解析
RefineDocumentsChain的策略是将长文本分成小块,每个小块经过处理后逐步更新总结。典型应用场景是总结文本内容,这在大文本相对于给定语言模型的上下文窗口很大时特别有用。
LangGraph的优势
LangGraph不仅能逐步监控执行过程,还允许流式传输执行步骤和单个tokens。此外,由于LangGraph是由模块化组件构成的,因此它易于扩展和修改,如整合工具调用等。
模型加载
我们可以选择不同的聊天模型,如OpenAI、Anthropic等。请注意,由于网络限制,开发者在使用某些API时可能需要考虑使用API代理服务。
# 使用API代理服务提高访问稳定性
import getpass
import os
os.environ["OPENAI_API_KEY"] = getpass.getpass()
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o-mini")
示例:总结文档序列
让我们通过生成一些简单的文档来进行示例演示。
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
from langchain.chains import LLMChain, RefineDocumentsChain
from langchain_core.prompts import ChatPromptTemplate, PromptTemplate
from langchain_openai import ChatOpenAI
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
)
# 执行链
result = chain.invoke(documents)
print(result["output_text"])
转向LangGraph
import operator
from typing import List, Literal, TypedDict
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnableConfig
from langchain_openai import ChatOpenAI
from langgraph.graph import END, START, StateGraph
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
summarize_prompt = ChatPromptTemplate(
[("human", "Write a concise summary of the following: {context}")])
initial_summary_chain = summarize_prompt | llm | StrOutputParser()
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_summary_chain = refine_prompt | llm | StrOutputParser()
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()
async for step in app.astream({"contents": [doc.page_content for doc in documents]}, stream_mode="values"):
if summary := step.get("summary"):
print(summary)
常见问题和解决方案
-
如何监控和调试LangGraph的执行过程?
LangGraph允许流式传输执行步骤和单个tokens,通过详细的日志记录和可视化工具可以实现有效的调试。 -
如何处理API访问时的网络限制?
在某些地区,开发者可能需要使用API代理服务来提高访问稳定性。
总结和进一步学习资源
从RefineDocumentsChain迁移到LangGraph提供了更大的灵活性和扩展能力。在使用LangGraph进行复杂文本分析时,可以更好地控制执行过程和即时响应。
进一步学习资源
参考资料
- LangChain Documentation: www.langchain.com/docs
- LangGraph API Reference: www.langgraph.com/api
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
---END---