Type something to search...
使用 LangGraph 框架以多代理方式实施复杂的 LLM 应用程序

使用 LangGraph 框架以多代理方式实施复杂的 LLM 应用程序

将LangGraph添加到您的GenAI相关技能库中。这项技能可以立即使您能够创建复杂的AI系统。当然,前提是您需要了解LangChain的使用方法。

介绍

LangGraph 是一个强大的工具,旨在使用大型语言模型 (LLMs) 创建有状态的多参与者应用程序。通过扩展 LangChain 库的功能,LangGraph 使得多个链(或参与者)能够在各种计算步骤中以循环方式进行协调。在这篇博客文章中,我们将介绍 LangGraph,探讨其基本概念,并解决初学者常见的困惑。

什么是 LangGraph?

LangGraph 是一个建立在 LangChain 之上的库,专门设计用于将循环计算能力整合到您的 LLM 应用程序中。虽然 LangChain 允许定义计算链(有向无环图或 DAG),但 LangGraph 引入了添加循环的能力。这一增强功能促进了更复杂的类代理行为,使您能够在循环中调用 LLM,并根据其响应确定下一步行动。

关键概念

有状态图:

LangGraph 的核心概念是有状态图。图中的每个节点代表计算中的一个步骤,图保持一个状态,该状态在计算进展时不断更新。

**节点:**节点是 LangGraph 的基本构建块。每个节点代表一个特定的功能或计算步骤。您可以定义节点来执行各种任务,例如处理输入、做出决策或与外部 API 交互。

**边:**边连接图中的节点,定义计算的流程。LangGraph 支持条件边,允许根据图的当前状态动态确定下一个要执行的节点。

代码示例

安装

我期待你已经在你的 Python 环境中安装了 langchain 和 openai。如果没有,请创建一个新环境并安装以下库。

### general packages
numpy
pandas
matplotlib
pydantic
tqdm
python-dotenv

### llm & other models
openai==1.12.0
sentence-transformers
faiss-cpu
chromadb

### frameworks
langchain
langchain-community
langchain-experimental
langchain-core
langchainhub
langgraph

使用 pip install langgraph 安装 LangGraph。

导入

## usual libraries
from typing import List
from typing_extensions import TypedDict
import re
from pydantic import BaseModel, Field

## langchain related libraries
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import JsonOutputParser, StrOutputParser

## langgraph related libraries
from langgraph.graph import StateGraph, START, END

定义一个状态

class AgentState(TypedDict):
    question: str
    llm_output: str
    documents: list[str]
    cnt_retries: int

节点方法

节点 — 问题范围分类器

class QuestionScopeClass(BaseModel):
    """问题的范围"""
    score: str = Field(
        description="布尔值,用于检查问题是关于什么、哪里或比较。如果是 -> 'Yes',否则为 'No'"
    )


def question_intent_classifier(state: AgentState):
    question = state["question"]
    state['cnt_retries'] = 0
    parser = JsonOutputParser(pydantic_object=QuestionScopeClass)
    output_format = parser.get_format_instructions()
    system = """您是一个问题分类器。检查问题是否与以下主题之一相关: 
        1. 定义
        2. 可用性
        3. 比较
        如果问题确实与这些主题相关,请回答“是”,否则请回答“否”。
        
        输出格式为: `{output_format}`
        """

    intent_prompt = ChatPromptTemplate.from_messages(
        [
            ("system", system),
            ("human", "用户问题: {question}"),
        ]
    )

    llm = openAI()
    grader_llm = intent_prompt | llm | parser
    result = grader_llm.invoke({"question": question, 'output_format': output_format})
    print(f"to_proceed: {result['score']}")
    state["on_topic"] = result['score']
    return state

## 启用条件边缘的路由
def on_topic_router(state: AgentState):
    print('ontopic router ... ')
    on_topic = state["on_topic"]
    if on_topic.lower() == "yes":
        return "on_topic"
    return "off_topic"

节点 — 答案评分器

def grade_answer(state: AgentState):
    answer = state['llm_output']
    print('评分中 ...')    
    # print('生成的答案类型:', type(answer))
    # 答案中是否包含 '不知道'
    pattern = r'do not know|apolog|sorry'
    is_answer = '是' if not re.search(pattern, answer.lower()) else '否'
    state['is_answer_ok'] = is_answer
    print(f"答案评分: {is_answer}")
    return state

def is_answer_router(state: AgentState):
    print('评分路由 ... ')
    is_answer = state["is_answer_ok"]
    if state['cnt_retries'] >2:  # 允许最多 3 次重试 (0 到 2)
        return "hit_max_retries"
    if is_answer.lower() == "yes":
        return "is_answer"
    return "is_not_answer"

节点 — 问题重述器

def question_rephraser(state: AgentState):
    print('重述中 ...')
    question = state['question']
    print(f"重试次数: {state['cnt_retries']+1}")
    llm = openAI()

    template = """
        您是一个擅长重述英语问题的专家。\
        您的任务是重述来自零售和供应链领域的问题。\
        在重述时,您可以执行以下操作:
        1. 从原始问题中提取关键词
        2. 根据需要扩展或创建问题的缩写
        3. 理解问题的意图
        4. 包括上述信息以生成原始问题的重述版本。\
        除重述问题外,不要输出任何其他内容。\
        
        问题: {question}
        """

    prompt = ChatPromptTemplate.from_template(
        template=template,
    )
    chain = prompt | llm | StrOutputParser()
    result = chain.invoke({"question": question})
    # print(result)
    state['question'] = result
    state['cnt_retries'] +=1
    return state

节点 — 检索器(可选)

## 创建向量存储的检索器的某些函数
retriever = get_retriever(config_vector_store) 

def retrieve_docs(state: AgentState):
    question = state["question"]
    documents = retriever.invoke(input=question)
    state["documents"] = documents
    print(f"检索到的文档数量: {len(documents)}")
    return state

节点 — 响应生成

def generate_answer(state: AgentState):
    question = state['question']
    context = [doc.page_content for doc in state['documents']]
    print('生成答案 ... ')
    llm = openAI()

    template = """
        您是一个客户支持聊天机器人,旨在回答来自零售和电子商务行业的用户查询。\
        保持对话和专业的语气。\
        请记住,提到的缩写与这些领域相关。\
        严格根据提供的上下文回答问题。\
        避免在响应中提到参考了上下文。\
        避免在生成的响应中使用“当然”和“看起来像”等词。\
        除答案外,不要输出任何其他内容。\
        
        {context}

        问题: {question}
        """

    prompt = ChatPromptTemplate.from_template(
        template=template,
    )
    chain = prompt | llm | StrOutputParser()
    result = chain.invoke({"question": question, "context": context})
    print(f"生成结果: {result}")
    state['llm_output'] = result
    return state

节点 — 后备响应

def get_default_reply(state:AgentState):
    print('获取默认答案 ...')
    state['llm_output'] = '我没有答案。'
    return state

组成语言图

这是连接我们上面创建的不同节点的流程。这也通过利用上面定义的路由器启用条件边。

workflow = StateGraph(AgentState)

## 添加节点
workflow.add_node('intent_classifier', question_intent_classifier)
workflow.add_node('retrieve_docs', retrieve_docs)
workflow.add_node('generate_answer', generate_answer)
workflow.add_node('grade_answer', grade_answer)
workflow.add_node('question_rephraser', question_rephraser)
workflow.add_node('default_reply', get_default_reply)

## 添加边,包括条件边
workflow.add_edge('intent_classifier', START)
workflow.add_conditional_edges(
    'intent_classifier', on_topic_router, 
    {
        'on_topic': 'retrieve_docs', 
        'off_topic': 'default_reply'
    }
)
workflow.add_edge('retrieve_docs', 'generate_answer')
workflow.add_edge('generate_answer', 'grade_answer')
workflow.add_conditional_edges(
    'grade_answer', is_answer_router,
    {
        'is_answer':END, 
        'is_not_answer':'question_rephraser', 
        'hit_max_retries':'default_reply'
    }
)
workflow.add_edge('question_rephraser', 'retrieve_docs')
workflow.add_edge('default_reply', END)

## 编译工作流
app = workflow.compile()

可视化工作流

try:
    display(Image(app.get_graph(xray=True).draw_mermaid_png()))
except:
    pass

使用应用程序

query = "Capital of India"
response = app.invoke(input={"question": query})

print(result['llm_output'])

结论

通过理解这些基础元素,用户可以利用 LangGraph 设计更复杂、动态的 LLM 应用,超越简单的线性任务链。无论是开发基于代理的系统还是管理多步骤工作流程,LangGraph 都提供了一个强大的框架,以应对生成式人工智能不断发展的领域中的挑战。

Related Posts

使用 ChatGPT 搜索网络功能的 10 种创意方法

使用 ChatGPT 搜索网络功能的 10 种创意方法

例如,提示和输出 你知道可以使用 ChatGPT 的“搜索网络”功能来完成许多任务,而不仅仅是基本的网络搜索吗? 对于那些不知道的人,ChatGPT 新的“搜索网络”功能提供实时信息。 截至撰写此帖时,该功能仅对使用 ChatGPT 4o 和 4o-mini 的付费会员开放。 ![](https://images.weserv.nl/?url=https://cdn-im

阅读更多
在人工智能和技术领域保持领先地位的 10 项必学技能 📚

在人工智能和技术领域保持领先地位的 10 项必学技能 📚

在人工智能和科技这样一个动态的行业中,保持领先意味着不断提升你的技能。无论你是希望深入了解人工智能模型性能、掌握数据分析,还是希望通过人工智能转变传统领域如法律,这些课程都是你成功的捷径。以下是一个精心策划的高价值课程列表,可以助力你的职业发展,并让你始终处于创新的前沿。 1. 生成性人工智能简介课程: [生成性人工智能简介](https://genai.works

阅读更多
10 个强大的 Perplexity AI 提示,让您的营销任务自动化

10 个强大的 Perplexity AI 提示,让您的营销任务自动化

在当今快速变化的数字世界中,营销人员总是在寻找更智能的方法来简化他们的工作。想象一下,有一个个人助理可以为您创建受众档案,建议营销策略,甚至为您撰写广告文案。这听起来像是一个梦想? 多亏了像 Perplexity 这样的 AI 工具,这个梦想现在成为现实。通过正确的提示,您可以将 AI 转变为您的 个人营销助理。在本文中,我将分享 10 个强大的提示,帮助您自动

阅读更多
10+ 面向 UI/UX 设计师的顶级 ChatGPT 提示

10+ 面向 UI/UX 设计师的顶级 ChatGPT 提示

人工智能技术,如机器学习、自然语言处理和数据分析,正在重新定义传统设计方法。从自动化重复任务到实现个性化用户体验,人工智能使设计师能够更加专注于战略思维和创造力。随着这一趋势的不断增长,UI/UX 设计师越来越多地采用 AI 驱动的工具来促进他们的工作。利用人工智能不仅能提供基于数据的洞察,还为满足多样化用户需求的创新设计解决方案开辟了机会。 1. 用户角色开发 目的

阅读更多
在几分钟内完成数月工作的 100 种人工智能工具

在几分钟内完成数月工作的 100 种人工智能工具

人工智能(AI)的快速发展改变了企业的运作方式,使人们能够在短短几分钟内完成曾经需要几周或几个月的任务。从内容创作到网站设计,AI工具帮助专业人士节省时间,提高生产力,专注于创造力。以下是按功能分类的100个AI工具的全面列表,以及它们在现实世界中的使用实例。 1. 研究工具 研究可能耗时,但人工智能工具使查找、分析和组织数据变得更加容易。**ChatGPT, Cop

阅读更多
你从未知道的 17 个令人惊叹的 GitHub 仓库

你从未知道的 17 个令人惊叹的 GitHub 仓库

Github 隐藏的宝石!! 立即收藏的代码库 学习编程相对简单,但掌握编写更好代码的艺术要困难得多。GitHub 是开发者的宝藏,那里“金子”是其他人分享的精心编写的代码。通过探索 GitHub,您可以发现如何编写更清晰的代码,理解高质量代码的样子,并学习成为更熟练开发者的基本步骤。 1. notwaldorf/emoji-translate *谁需

阅读更多