langchain系列(九)- LangGraph 子图详解

一、导读

环境:OpenEuler、Windows 11、WSL 2、Python 3.12.3 langchain 0.3 langgraph 0.2

背景:前期忙碌的开发阶段结束,需要沉淀自己的应用知识,过一遍LangGraph

时间:20250307

说明:技术梳理,LangGraph 的多代理(多智能体)基于子图实现,此处对子图进行说明,案例基于官方文档进行部分的修改

官方文档地址:LangGraph 子图实现

 二、原理说明

1、简介

子图允许您构建具有多个组件的复杂系统,这些组件本身是图。使用子图的常见用例是构建多代理系统。

在添加子图时,主要问题是父图和子图如何进行通信,即它们如何在图执行期间相互传递状态。这里有两种情况:

父图和子图共享schema keys。在这种情况下,您可以添加一个编译后的子图节点

父图和子图具有不同的schemas。在这种情况下,您必须添加一个调用子图的节点函数:当父图和子图具有不同的状态模式时,这在调用子图之前或之后需要转换状态时很有用

2、子图图示

3、使用说明

一种常见的情况是父图和子图通过共享状态键(通道)进行通信。例如,在多代理系统中,代理通常通过共享的消息键进行通信。

如果你的子图与父图共享状态键,你可以按照以下步骤将其添加到父图中:

定义子图工作流(如下例中的subgraph_builder)并进行编译

在定义父图工作流时,将编译后的子图传递给.add_node方法

三、代码实现

1、实现功能

开始节点进行意图分类,如果天气相关则走天气相关的子图;否则走智能助手节点。

2、Graph 图示

3、代码实现

from langgraph.graph import StateGraph, END, START, MessagesState
from langchain_core.tools import tool
from langchain_openai import ChatOpenAI
from typing import Literal
from langgraph.checkpoint.memory import MemorySaver

@tool
def get_weather(city: str):
    """获取天气信息"""
    return f"{city},晴空万里,阳光明媚!"

# 添加记忆存储
memory = MemorySaver()

# 配置信息,用于记录对话记录
config = {"configurable": {"thread_id": "1"}}


# 指定大模型的API Key 等相关信息
llm = ChatOpenAI(
    base_url="https://lxxxxx.enovo.com/v1/", 
    api_key="sxxxxxxxwW",
    model_name="qwen2.5-instruct"
    )


# 绑定工具
model = raw_model.bind_tools([get_weather])

# 子图的state
class SubGraphState(MessagesState):
    city: str

# 识别地点(城市)
def model_node(state: SubGraphState):
    system_message = """用户的问题是某个地方的天气问题,请辨别具体城市名称,并输出城市名称。"""
    messages = [{"role": "system", "content": system_message}] + state["messages"]
    result = raw_model.invoke(messages)
    return {"city": result.content}

# 天气工具节点
def weather_node(state: SubGraphState):
    result = get_weather.invoke({"city": state["city"]})
    return {"messages": [{"role": "assistant", "content": result}]}

# 子图的添加节点、边以及编译图
subgraph = StateGraph(SubGraphState)
subgraph.add_node(model_node)
subgraph.add_node(weather_node)
subgraph.add_edge(START, "model_node")
subgraph.add_edge("model_node", "weather_node")
subgraph.add_edge("weather_node", END)
subgraph = subgraph.compile()

# 意图分类state
class RouterState(MessagesState):
    route: Literal["天气", "其他"]

# 意图分类节点
def router_node(state: RouterState):
    system_message = """用户输入与天气相关则输出"天气",与天气无关返回"其他”"""
    messages = [{"role": "system", "content": system_message}] + state["messages"]
    route = raw_model.invoke(messages)
    return {"route": route.content}

# 智能助手节点
def normal_llm_node(state: RouterState):
    response = raw_model.invoke(state["messages"])
    return {"messages": [response]}

# 选择边函数
def route_after_prediction(state: RouterState):
    if state["route"] == "天气":
        return "weather_graph"
    else:
        return "normal_llm_node"

# 父图的添加边、节点以及编译父图
graph = StateGraph(RouterState)
graph.add_node(router_node)
graph.add_node(normal_llm_node)
# 将子图作为一个节点添加到父图中
graph.add_node("weather_graph", subgraph)
graph.add_edge(START, "router_node")
graph.add_conditional_edges("router_node", route_after_prediction)
graph.add_edge("normal_llm_node", END)
graph.add_edge("weather_graph", END)
graph = graph.compile(checkpointer=memory)


# 以流式调用图
def stream_graph_updates(user_input: str):
    for event in graph.stream({"messages": [{"role": "user", "content": user_input}]}, config=config, stream_mode="updates"):
        if event.get("router_node"):
            continue
        else:
            for value in event.values():
                print("Assistant:", value["messages"][-1].content)

# 设置聊天退出方法
while True:
    try:
        user_input = input("User: ")
        if user_input.lower() in ["quit", "exit", "q"]:
            print("Goodbye!")
            break

        stream_graph_updates(user_input)
    except Exception as e:
        print(e)
        user_input = "What do you know about LangGraph?"
        print("User: " + user_input)
        stream_graph_updates(user_input)
        break

4、输出

User: 北京天气怎么样
Assistant: 北京,晴空万里,阳光明媚!
User: hi
Assistant: Hello! How can I assist you today?
User: 天津的天气怎么样
Assistant: 天津,晴空万里,阳光明媚!

5、分析

据上述输出可知,询问天气则会返回相关信息;其他对话内容会按照普通助手功能回复

未完待续

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/982949.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Kotlin和Java区别

哈哈哈,前段时间,面试的时候,突然问到我Kotlin和Java的区别,一下子把我问懵逼了,确实没遇到问这个的,想了下,说了下Kotlin的编译时空检查机制,代码更简洁,很多封装好的AP…

ADSP21569 SPORT使用静态配置驱动方法

ADSP Driver除了可以使用提供API配置,还可以使用静态配置文件进行配置 1,ADI的API比如SPORT驱动API 截图如下所示 可以查看帮助文档获取并使用,调用简洁方便,但不会直观与寄存器联系,不利于调试 2、驱动静态配置可以找…

Web网页开发——水果忍者

1.介绍 复刻经典小游戏——水果忍者 2.预览 3.代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title&…

Manus详细介绍,Manus核心能力介绍

文章目录 前言Manus产品定位与核心理念:Manus产品特性与未来体验战略:Manus商业价值与创新指标:Manus技术特点与竞争优势:Manus用户反馈与展望:Manus市场竞争优势与团队战略:Manus深度总结与启发: 前言 这是一篇关于Manus智能体产品的用户体验评价报告&#xff0c;主要介绍了M…

上线DeepSeek大模型,黄山“大位”智算中心正式点亮

2月28日&#xff0c;智启黄山&#xff0c;算领未来——黄山“大位”智算中心点亮仪式在黄山市大位人工智能计算中心举行&#xff0c;标志着黄山“大位”智算中心正式投入运营。同日&#xff0c;DeepSeek-R1大模型在黄山“大位”正式上线&#xff0c;通过“顶尖大模型普惠算力底…

深入理解 C 语言函数的定义

在 C 语言的编程世界里&#xff0c;函数是构建复杂程序的基石。理解函数的定义与运用&#xff0c;对于编写高效、可维护的代码至关重要。​ 函数定义的基本概念​ 函数是一组执行特定任务的代码块。它将一个复杂的问题分解为一个个小的、可管理的部分&#xff0c;提高了代码的…

解锁STM32外设:开启嵌入式开发新世界

✨✨✨这里是小韩学长yyds的BLOG(喜欢作者的点个关注吧) ✨✨✨想要了解更多内容可以访问我的主页 小韩学长yyds-CSDN博客 目录 探索 STM32 强大的外设家族 初窥门径&#xff1a;STM32 外设开发基础 开发方式与工具 外设配置基础步骤 深入剖析&#xff1a;常见外设应用实例…

基于Spring Boot的高校就业招聘系统的设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…

审批流AntV框架蚂蚁数据可视化X6饼图(附注释)

大家好&#xff0c;这次使用的是AntV的蚂蚁数据可视化X6框架&#xff0c;类似于审批流的场景等&#xff0c;代码如下&#xff1a; X6框架参考网址&#xff1a;https://x6.antv.vision/zh/examples/showcase/practices#bpmn 可以进入该网址&#xff0c;直接复制下方代码进行调试…

kettle工具使用从入门到精通(一)

安装 可以从链接: 官网&#xff08;下载链接在Pentaho.pdf文件里&#xff09;或者网络上查找对应的版本安装 Kettle (PDI) 版本与 JDK 版本对应关系 Kettle (PDI) 版本支持的 JDK 版本备注PDI 9.x 及以上JDK 11 或更高版本推荐使用 OpenJDK 或 Oracle JDK 11。PDI 8.xJDK 8 …

深度分页介绍及优化建议

深度分页介绍 查询偏移量过大的场景我们称为深度分页&#xff0c;这会导致查询性能较低&#xff0c;例如&#xff1a; # MySQL 在无法利用索引的情况下跳过1000000条记录后&#xff0c;再获取10条记录 SELECT * FROM t_order ORDER BY id LIMIT 1000000, 10 深度分页问题的原…

深入剖析分布式事务:原理、方案与实战指南

引言&#xff1a;为什么分布式事务成为架构师的必修课&#xff1f; 在微服务架构大行其道的今天&#xff0c;单体应用被拆分成多个独立服务。当一次业务操作需要跨多个服务/数据库完成时&#xff0c;传统数据库事务的ACID特性不再适用。订单创建需要同时操作订单服务和库存服务…

NodeJS学习笔记

NodeJS软件安装 node环境安装&#xff1a; https://nodejs.org 安装好后的node通常在C:\Program Files\nodejs验证安装是否成功 node -v npm -v 进入REPL模式命令行模式 nodeNodeJS在REPL模式和编辑器使用 windos在dos下常用命令 windos命令&#xff1a; 1、cmd dos系统2、…

阿里云QwQ-32B模型发布:AI领域的新突破

在人工智能技术飞速发展的今天&#xff0c;每一次重大突破都可能改写行业的未来。近日&#xff0c;阿里云重磅发布通义千问 QwQ-32B 模型&#xff0c;这一消息如同一颗重磅炸弹&#xff0c;瞬间在 AI 领域掀起轩然大波&#xff0c;引发全球关注。 QwQ-32B 模型的惊艳之处&…

HarmonyOS NEXT开发实战:DevEco Studio中DeepSeek的使用

随着HarmonyOS Next的持续发布&#xff0c;鸿蒙系统对AI能力的支持显著增强。本文将深入探讨如何在鸿蒙应用中集成AI模型&#xff0c;结合接入DeepSeek&#xff0c;一起来探索开发鸿蒙原生应用的更多可能吧&#xff01; 第一步&#xff1a;安装使用 建议使用DevEco Studio 5.0…

VMware 安装部署RHEL9

目录 目标一&#xff1a;创建名为RHEL9_node2的虚拟机 1.环境搭建&#xff1a;VMware 2.下载RHEL9的ISO镜像&#xff08;官网可获取&#xff09; 3.打开VMware&#xff0c;新建虚拟机 3.1 自定义安装 3.2 默认操纵至下一步操作到稍后安装系统 3.3选择操作系统为linux以及…

基于Python实现的智能旅游推荐系统(Django)

基于Python实现的智能旅游推荐系统(Django) 开发语言:Python 数据库&#xff1a;MySQL所用到的知识&#xff1a;Django框架工具&#xff1a;pycharm、Navicat 系统功能实现 总体设计 系统实现 系统首页模块 统首页页面主要包括首页&#xff0c;旅游资讯&#xff0c;景点信息…

利用可变参数模板,可打印任意参数和参数值。(C++很好的调式函数)

很酷的应用&#xff1a; &#xff08;1&#xff09; 如何获取可变参数名 代码例子&#xff1a; #define _test(...) (test_t(#__VA_ARGS__, __VA_ARGS__))template<typename... Args> void test_t(const char* names, Args... args) {std::cout << names <<…

HarmonyOS 应用程序包结构 (编译态)

不同类型的Module编译后会生成对应的HAP、HAR、HSP等文件&#xff0c;开发态视图与编译态视图的对照关系如下&#xff1a; 从开发态到编译态&#xff0c;Module中的文件会发生如下变更&#xff1a; ets目录&#xff1a;ArkTS源码编译生成.abc文件。resources目录&#xff1a;A…

After Effects的图钉与关键帧动画

姜 子 博 引言 在数字媒体时代&#xff0c;动态图形和视觉效果在信息传播和表达中扮演着越来越重要的角色。After Effects 作为行业领先的软件&#xff0c;提供了丰富的工具和功能&#xff0c;帮助用户创作出令人惊叹的视觉作品。图钉工具和关键帧动画是 AE 中实现复杂动画效…