【LangChain高级系列】LangGraph第一课

news2025/5/10 12:31:54

前言

我们今天直接通过一个langgraph的基础案例,来深入探索langgraph的核心概念和工作原理。

基本认识

LangGraph是一个用于构建具有LLMs的有状态、多角色应用程序的库,用于创建代理和多代理工作流。与其他LLM框架相比,它提供了以下核心优势:循环、可控性、持久性。

LangGraph允许您定义涉及循环的流程,这对于大多数代理架构至关重要。作为一种非常底层的框架,它提供了对应用程序的流程和状态的精细控制,这对创建可靠的代理至关重要。

此外,LangGraph包含内置的持久性,可以实现高级的"人机交互"和内存功能。LangGraph是LangChain的高级库,为大型语言模型(LLM)带来循环计算能力。它超越了LangChain的线性工作流,通过循环支持复杂的任务处理。

核心概念

状态(State):维护计算过程中的上下文,实现基于累积数据的动态决策。
节点(Node):代表计算步骤,执行特定任务,可定制以适应不同工作流。
边(Edge):连接节点,定义计算流程,支持条件逻辑,实现复杂工作流

 Langgraph执行细节

from typing import Literal
from langchain.tools import tool
from langgraph.graph import END, MessagesState, StateGraph
from langgraph.checkpoint.memory import MemorySaver
from langgraph.prebuilt import ToolNode
from langchain_deepseek import ChatDeepSeek
import os
# 执行轨迹上报
os.environ["LANGSMITH_TRACING"] = "true"
os.environ["LANGSMITH_API_KEY"] = "lsv2_pt_3df2ddbe15e308db82d935249e9e2_7668b99099"     
os.environ["LANGCHAIN_PROJECT"] = "langgraph_base"
os.environ["LANGSMITH_ENDPOINT"] = "https://api.smith.langchain.com"

# 工具函数,用于查询天气
@tool(description="查询天气")
def query_weather(words: str):
    if "上海" in words.lower() or "shanghai" in words.lower():
        return "天气晴朗,适合出行"
    else:
        return "天晴欠佳,不宜出行"

# 工具函数,用于查询天气
@tool(description="查询交通")
def query_thransport(words: str):
    if "交通" in words.lower() or "transport" in words.lower():
        return "交通通畅,可自驾"
    else:
        return "交通拥堵,不宜出行"

# 将查询天气的工具函数添加到工具列表中
tools = [query_weather, query_thransport]

# 将工具列表转换为工具节点,便于langgraph调用工具
tool_nodes = ToolNode(tools)

llm = ChatDeepSeek(
    model="deepseek-chat",
    temperature=0,
    max_tokens=None,
    timeout=None,
    max_retries=2,
    api_key="sk-37c6b1c6517141e644c5ba1c81782",
).bind_tools(tools) # 将工具绑定到llm模型上,以便模型可以调用工具函数

def action_router(state: MessagesState) -> Literal["tools", END]: # 定义动作路由函数,用于根据当前状态选择下一步动作
    messages = state["messages"] # 获取当前消息列表,用于判断最后一条消息的类型,以便选择下一步动作
    last_message = messages[-1] # 获取最后一条消息,用于判断最后一条消息的类型,以便选择下一步动作
    if last_message.tool_calls: # 如果最后一条消息包含工具调用,则选择工具节点
        return "tools"
    else: # 否则结束
        return END

def call_llm(state: MessagesState) -> MessagesState: # 定义调用llm模型的函数,用于生成回复消息
    messages = state["messages"] # 获取当前消息列表,用于生成回复消息
    response = llm.invoke(messages) # 调用llm模型生成回复消息
    return {"messages": [response]} # 返回回复消息

workflow = StateGraph(MessagesState) # 创建状态图,用于管理消息状态

workflow.add_node("agent", call_llm) # 将工具节点添加到状态图中,以便工具节点可以被调用
workflow.add_node("tools", tool_nodes) # 将调用llm模型的函数添加到状态图中,以便llm模型可以被调用

workflow.set_entry_point("agent") # 设置入口点,即从工具节点开始

workflow.add_conditional_edges( # 添加条件边,即根据当前状态选择下一步动作
    "agent", # 从工具节点开始
    action_router # 选择下一步动作的函数
) # 结束添加条件边

workflow.add_edge("tools", "agent") # 将工具节点和调用llm模型的函数连接起来,以便工具节点可以调用llm模型生成回复消息

app = workflow.compile(checkpointer=MemorySaver()) # 编译状态图,以便可以被调用

final_state = app.invoke(
    {"messages": [{"role": "user", "content": "交通状态如何?"}]}, 
    config={"configurable": {"thread_id": "123"}} # 调用状态图,生成回复消息,传入配置参数,以便可以被调用
) # 调用状态图,生成回复消息

print(final_state) # 打印回复消息

#将生成的图片保存到文件
graph_png = app.get_graph().draw_mermaid_png()
with open("langgraph_base.png", "wb") as f:
    f.write(graph_png)

 当我们输入:交通状况如何?大模型会选择query_transport工具

 当我们输入:上海天气如何?大模型会选择query_weather工具

 上图中,_start_和_end_是虚拟节点,其中虚线是条件边,实线是一定会执行的,也就是说执行完tools后,一定会再次调用agent逻辑。

Langsmith监控分析

 1、上图展示的是执行轨迹的瀑布流模式的展现形式

2、从上图看,以此调用一共耗时12.48秒

3、然后是agent节点的执行,耗时6.88秒,agent会调用deepseek,我们看看deepseek返回的数据:

{
  "generations": [
    [
      {
        "text": "",
        "generation_info": {
          "finish_reason": "tool_calls",
          "logprobs": null
        },
        "type": "ChatGeneration",
        "message": {
          "lc": 1,
          "type": "constructor",
          "id": [
            "langchain",
            "schema",
            "messages",
            "AIMessage"
          ],
          "kwargs": {
            "content": "",
            "additional_kwargs": {
              "tool_calls": [
                {
                  "id": "call_0_3d3d77c8-919e-42c1-a402-b4f87bf248be",
                  "function": {
                    "arguments": "{\"words\":\"上海的天气\"}",
                    "name": "query"
                  },
                  "type": "function",
                  "index": 0
                }
              ],
              "refusal": null
            },
            "response_metadata": {
              "token_usage": {
                "completion_tokens": 18,
                "prompt_tokens": 98,
                "total_tokens": 116,
                "completion_tokens_details": null,
                "prompt_tokens_details": {
                  "audio_tokens": null,
                  "cached_tokens": 64
                },
                "prompt_cache_hit_tokens": 64,
                "prompt_cache_miss_tokens": 34
              },
              "model_name": "deepseek-chat",
              "system_fingerprint": "fp_8802369eaa_prod0425fp8",
              "id": "4e9ca352-44d5-4612-a02f-da0340c9dffc",
              "finish_reason": "tool_calls",
              "logprobs": null
            },
            "type": "ai",
            "id": "run--b6cf271e-a3b3-4d6a-805c-e15a921be943-0",
            "tool_calls": [
              {
                "name": "query",
                "args": {
                  "words": "上海的天气"
                },
                "id": "call_0_3d3d77c8-919e-42c1-a402-b4f87bf248be",
                "type": "tool_call"
              }
            ],
            "usage_metadata": {
              "input_tokens": 98,
              "output_tokens": 18,
              "total_tokens": 116,
              "input_token_details": {
                "cache_read": 64
              },
              "output_token_details": {}
            },
            "invalid_tool_calls": []
          }
        }
      }
    ]
  ],
  "llm_output": {
    "token_usage": {
      "completion_tokens": 18,
      "prompt_tokens": 98,
      "total_tokens": 116,
      "completion_tokens_details": null,
      "prompt_tokens_details": {
        "audio_tokens": null,
        "cached_tokens": 64
      },
      "prompt_cache_hit_tokens": 64,
      "prompt_cache_miss_tokens": 34
    },
    "model_name": "deepseek-chat",
    "system_fingerprint": "fp_8802369eaa_prod0425fp8",
    "id": "4e9ca352-44d5-4612-a02f-da0340c9dffc"
  },
  "run": null,
  "type": "LLMResult"
}

 我们重点看其中这部分:

 deepseek告诉langgraph,需要调用tool,名称是query,参数是:上海的天气。

4、根据条件边的设置,下一步会调用action_router决定下一步做什么,从返回的数据来看,下一步会调用query方法查询天气,

 5、执行完query之后,会再次调用deepseek,让deepseek生成结果

 6、结束本次执行

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

常见降维算法分析

一、常见的降维算法 LDA线性判别PCA主成分分析t-sne降维 二、降维算法原理 2.1 LDA 线性判别 原理 :LDA(Linear Discriminant Analysis)线性判别分析是一种有监督的降维方法。它的目标是找到一个投影方向,使得不同类别的数据在…

计算机二级(C语言)已过

非线性结构:树、图 链表和队列的结构特性不一样,链表可以在任何位置插入、删除,而队列只能在队尾入队、队头出队 对长度为n的线性表排序、在最坏情况下时间复杂度,二分查找为O(log2n),顺序查找为O(n),哈希查…

2025年3月,​韩先超对国网宁夏进行Python线下培训

大家好,我是韩先超!在2025年3月3号和4号,为 宁夏国网 的运维团队进行了一场两天的 Python培训 ,培训目标不仅是让大家学会Python编程,更是希望大家能够通过这门技术解决实际工作中的问题,提升工作效率。 对…

[计算机网络]物理层

文章目录 物理层的概述与功能传输介质双绞线:分类:应用领域: 同轴电缆:分类: 光纤:分类: 无线传输介质:无线电波微波:红外线:激光: 物理层设备中继器(Repeater):放大器:集线器(Hub)&…

幂等操作及处理措施

利用token模式去避免幂等操作 按以上图所示,除了token,应该也可以把传入的参数用MD5加密,当成key放入redis里面,业务执行完后再删除这个key.如还没有执行完,则请不要重复操作。纯属个人理解

Matlab 数控车床进给系统的建模与仿真

1、内容简介 Matlab217-数控车床进给系统的建模与仿真 可以交流、咨询、答疑 2、内容说明 略 摘 要:为提高数控车床的加工精度,对数控 车床进给系统中影响加工精度的主要因素进行了仿真分析研 动系统的数学模型,利用MATLAB软件中的动态仿真工具 究:依据机械动力学原理建立了…

低成本自动化改造的18个技术锚点深度解析

执行摘要 本文旨在深入剖析四项关键的低成本自动化技术,这些技术为工业转型提供了显著的运营和经济效益。文章将提供实用且深入的指导,涵盖老旧设备联网、AGV车队优化、空压机系统智能能耗管控以及此类项目投资回报率(ROI)的严谨…

我国脑机接口市场规模将破38亿元,医疗领域成关键突破口

当人类仅凭"意念"就能操控无人机编队飞行,当瘫痪患者通过"脑控"重新站立行走,这些曾只存在于科幻电影的场景,如今正通过脑机接口技术变为现实。作为"十四五"规划中重点发展的前沿科技,我国脑机接口…

Edu教育邮箱申请成功下号

这里是第2部分 如你所见,我根本就没有考虑流量的问题, 如果你有幸看到前面的内容,相信你能自己找到这个后续。

【Linux进程控制一】进程的终止和等待

【Linux进程控制一】进程的终止和等待 一、进程终止1.main函数的return2.strerror函数3.库函数exit4.系统调用_exit和库函数exit的区别5.异常信号6.变量errno 二、进程等待1.什么是进程等待?2.wait接口3.status4.waitpid接口 一、进程终止 1.main函数的return 写C…

今日行情明日机会——20250509

上证指数今天缩量,整体跌多涨少,走势处于日线短期的高位~ 深证指数今天缩量小级别震荡,大盘股表现更好~ 2025年5月9日涨停股主要行业方向分析 一、核心主线方向 服装家纺(消费复苏出口链驱动) • 涨停家数&#xf…

单片机-STM32部分:10、串口UART

飞书文档https://x509p6c8to.feishu.cn/wiki/W7ZGwKJCeiGjqmkvTpJcjT2HnNf 串口说明 电平标准是数据1和数据0的表达方式,是传输线缆中人为规定的电压与数据的对应关系,串口常用的电平标准有如下三种: TTL电平:3.3V或5V表示1&am…

RabittMQ-高级特性2-应用问题

文章目录 前言延迟队列介绍ttl死信队列存在问题延迟队列插件安装延迟插件使用事务消息分发概念介绍限流非公平分发(负载均衡) 限流负载均衡RabbitMQ应用问题-幂等性保障顺序性保障介绍1顺序性保障介绍2消息积压总结 前言 延迟队列介绍 延迟队列(Delaye…

React 播客专栏 Vol.5|从“显示”到“消失”:打造你的第一个交互式 Alert 组件!

👋 欢迎回到《前端达人 播客书单》第 5 期(正文内容为学习笔记摘要,音频内容是详细的解读,方便你理解),请点击下方收听 📌 今天我们不再停留在看代码,而是动手实现一个真正的 React…

解密火星文:LeetCode 269 题详解与 Swift 实现

文章目录 摘要描述题解答案题解代码分析构建图(Graph)拓扑排序(Topological Sort) 示例测试及结果时间复杂度空间复杂度实际场景类比总结 摘要 这篇文章我们来聊聊 LeetCode 269 题:火星词典(Alien Dictio…

动态规划-62.不同路径-力扣(LeetCode)

一、题目解析 机器人只能向下或向左,要从Start位置到Finish位置。 二、算法原理 1.状态表示 我们要求到Finish位置一共有多少种方法,记Finish为[i,j],此时dp[i,j]表示:到[i,j]位置时,一共有多少种方法,满…

5月9号.

v-for: v-bind: v-if&v-show: v-model: v-on: Ajax: Axios: async&await: Vue生命周期: Maven: Maven坐标:

从 Git 到 GitHub - 使用 Git 进行版本控制 - Git 常用命令

希望本贴能从零开始带您一起学习如何使用 Git 进行版本控制,并结合远程仓库 GitHub。这会是一个循序渐进的指南,我们开始吧! 学习 Git 和 GitHub 的路线图: 理解核心概念:什么是版本控制?Git 是什么&…

双指针算法详解(含力扣和蓝桥杯例题)

目录 一、双指针算法核心概念 二、常用的双指针类型: 2.1 对撞指针 例题1:盛最多水的容器 例题2:神奇的数组 2.2 快慢指针: 例题1:移动零 例题2:美丽的区间(蓝桥OJ1372) 3.总…

【网络编程】二、UDP网络套接字编程详解

文章目录 前言Ⅰ. UDP服务端一、服务器创建流程二、创建套接字 -- socketsocket 属于什么类型的接口❓❓❓socket 是被谁调用的❓❓❓socket 底层做了什么❓❓❓和其函数返回值有没有什么关系❓❓❓ 三、绑定对应端口号、IP地址到套接字 -- bind四、数据的发送和接收 -- sendto…