langgraph入门
使用langgraph框架搭建一个简易agent。
最近想学习一下agent相关知识,langgraph似乎挺好的,于是就来试一试。langgraph。看了官网,起核心思想是将agent中的角色和工具都当作是图的Node,整个agent流程通过增加Node之间的边来设定。
官网用的是claude的api,我这里用的OPENAI的api。
import json
import operator
from typing import TypedDict, Annotated, Sequence
from langchain_core.messages import BaseMessage
from langchain.tools.render import format_tool_to_openai_function
from langgraph.prebuilt import ToolExecutor,ToolInvocation
from langchain_core.messages import FunctionMessage
from langgraph.graph import StateGraph, END
from langchain_core.messages import HumanMessage
from langchain_core.tools import toolimport os
from langchain.chat_models import ChatOpenAI# 用于创建一个LLM大模型对象, .1版本langchain的调用方法
from langchain.schema import HumanMessage# 用于区别是user发的消息
os.environ['OPENAI_API_KEY'] = "sk-....."
model_name="gpt-3.5-turbo"
model = ChatOpenAI(model_name=model_name,temperature=0)# 自定义工具
# @tool
# def search(query: str) -> str:
# """Look up things online."""
# print(f"search: {query}")
# return "sunny"@tool
def search(query: str):"""Call to surf the web."""# This is a placeholder, but don't tell the LLM that...if "sf" in query.lower() or "san francisco" in query.lower():return "It's 60 degrees and foggy."return "It's 90 degrees and sunny."@tool
def multiply(a: int, b: int) -> int:"""Multiply two numbers."""return a * b tools = [search,multiply]tool_executor = ToolExecutor(tools)# We will set streaming=True so that we can stream tokens
# See the streaming section for more information on this.
# model = ChatOpenAI(temperature=0, streaming=True)functions = [format_tool_to_openai_function(t) for t in tools]
model = model.bind_functions(functions)class AgentState(TypedDict):messages: Annotated[Sequence[BaseMessage], operator.add]# Define the function that determines whether to continue or not
def should_continue(state):messages = state['messages']last_message = messages[-1]# If there is no function call, then we finishif "function_call" not in last_message.additional_kwargs:return "end"# Otherwise if there is, we continueelse:return "continue"# Define the function that calls the model
def call_model(state):messages = state['messages']response = model.invoke(messages)# We return a list, because this will get added to the existing listreturn {"messages": [response]}# Define the function to execute tools
def call_tool(state):messages = state['messages']# Based on the continue condition# we know the last message involves a function calllast_message = messages[-1]# We construct an ToolInvocation from the function_callaction = ToolInvocation(tool=last_message.additional_kwargs["function_call"]["name"],tool_input=json.loads(last_message.additional_kwargs["function_call"]["arguments"]),)# We call the tool_executor and get back a responseresponse = tool_executor.invoke(action)# print(f"response:{response}")# We use the response to create a FunctionMessagefunction_message = FunctionMessage(content=str(response), name=action.tool)# print(f"function_message:{function_message}")# We return a list, because this will get added to the existing listreturn {"messages": [function_message]} # Define a new graph
workflow = StateGraph(AgentState)# Define the two nodes we will cycle between
workflow.add_node("agent", call_model)
workflow.add_node("action", call_tool)# Set the entrypoint as `agent`
# This means that this node is the first one called
workflow.set_entry_point("agent")# We now add a conditional edge
workflow.add_conditional_edges(# First, we define the start node. We use `agent`.# This means these are the edges taken after the `agent` node is called."agent",# Next, we pass in the function that will determine which node is called next.should_continue,# Finally we pass in a mapping.# The keys are strings, and the values are other nodes.# END is a special node marking that the graph should finish.# What will happen is we will call `should_continue`, and then the output of that# will be matched against the keys in this mapping.# Based on which one it matches, that node will then be called.{# If `tools`, then we call the tool node."continue": "action",# Otherwise we finish."end": END}
)# We now add a normal edge from `tools` to `agent`.
# This means that after `tools` is called, `agent` node is called next.
workflow.add_edge('action', 'agent')# Finally, we compile it!
# This compiles it into a LangChain Runnable,
# meaning you can use it as you would any other runnable
app = workflow.compile() #inputs = {"messages": [HumanMessage(content="what is the weather in Beijing?")]}
# inputs = {"messages": [HumanMessage(content="3乘以5等于多少,输出最终的结果")]}
response = app.invoke(# {"messages": [HumanMessage(content="3乘以5等于多少,输出最终的结果")]},{"messages": [HumanMessage(content="what is the weather in sf")]},config={"configurable": {"thread_id": 42}}
)
# print(type(response))
# print(f"last result:{response}")
# 输出如下信息:
# {'messages': [HumanMessage(content='3乘以5等于多少'), AIMessage(content='', additional_kwargs={'function_call': {'arguments': '{\n "a": 3,\n "b": 5\n}', 'name': 'multiply'}}, response_metadata={'finish_reason': 'function_call'}, id='run-bbf18160-747f-48ac-9a81-6c1ee3b70b07-0'), FunctionMessage(content='15', name='multiply'), AIMessage(content='3乘以5等于15。', response_metadata={'finish_reason': 'stop'}, id='run-0d1403cf-4ddb-4db2-8cfa-d0965666e62d-0')]}
print(response['messages'][-1].content)
输出结果为
The weather in San Francisco is currently 60 degrees and foggy.
整体的代码分为,调用模型call_model,调用工具call_tool,定义工具,定义终止条件,以及定义workflow。
这里主要是这个workflow,workflow = StateGraph(AgentState),langgraph里面核心的概念是state,这个state代表着整个环境的变量,message,状态信息,我认为是理解为一种agent的信息中心,每个agent要采取下一步的动作要根据这个信息中心来决定下一步的动作。
Limiation
1、这个只是一个很简单的agent框架,那么对于论文中那种复杂的包含rag等组件的agent,该如何使用langgraph进行搭建?
2、这里是用的是gpt的接口,如果要使用本地模型呢?如何把本地模型接入到langgraph框架里面?
相关文章:
langgraph入门
使用langgraph框架搭建一个简易agent。 最近想学习一下agent相关知识,langgraph似乎挺好的,于是就来试一试。langgraph。看了官网,起核心思想是将agent中的角色和工具都当作是图的Node,整个agent流程通过增加Node之间的边来设定。…...
【Python】爬虫程序打包成exe
上一篇写了爬虫获取汽车之家配置表,师父要更方便使用甚至推广(?),反正就是他们没有环境也能用嘛,我就直接打包了,界面不会做也懒得学了、、 1、下载pyinstaller(清华镜像)…...
【力扣专题栏】两两交换链表中的节点,如何实现链表中两两相邻节点的交换?
这里写目录标题 1、题目描述解释2、算法原理解析3、代码编写 1、题目描述解释 2、算法原理解析 3、代码编写 /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int…...
埋点采集的日志数据常见的格式简介
埋点采集的日志数据通常以结构化或半结构化的格式进行记录,以便于分析和处理。常见的格式包括: 1. JSON(JavaScript Object Notation) 特点:JSON 格式是一种轻量级的数据交换格式,具有良好的可读性和兼容…...
基于SSM高考志愿辅助填报系统设计与实现
前言 近年来,由于计算机技术和互联网技术的飞速发展,所以各企事业单位内部的发展趋势是数字化、信息化、无纸化,随着这一趋势,而各种决策系统、辅助系统也就应运而生了,其中,信息管理系统是其中重要的组成…...
elasticsearch 8.x 插件安装(六)之Hanlp插件
elasticsearch 8.x 插件安装(六)之Hanlp插件 elasticsearch插件安装合集 elasticsearch插件安装(一)之ik分词器安装(含MySQL更新) elasticsearch 8.x插件(二)之同义词安装如何解决…...
排序算法简记
列举几种基本的排序算法和排序思想 排序就是将一组对象按照某种逻辑顺序重新排列的过程。 一、选择排序 1、基本原理 最基本的排序,每次都从原有数据中选择最小或最大的数组放入新数据集中 2、步骤(以从小到大为例) 首先, 找到数组中最小的那个元素…...
Stable diffusion inference 多卡并行
stable diffusion 推理过程 多卡并行 注意事项 以SDXL为例,指定GPU,添加device_map参数信息 device_map {add_embedding: 1,decoder: 1,encoder: 1,conv_in: 1,conv_out: 1,post_quant_conv: 1,text_model: 6,conv_norm_out: 1,quant_conv: 1,time_em…...
Docker:namespace环境隔离 CGroup资源控制
Docker:namespace环境隔离 & CGroup资源控制 Docker虚拟机容器 namespace相关命令ddmkfsdfmountunshare 进程隔离文件隔离 CGroup相关命令pidstatstresscgroup控制 内存控制CPU控制 Docker 在开发中,经常会遇到环境问题,比如程序依赖某个…...
鼠标增强工具 MousePlus v5.3.9.0 中文绿色版
MousePlus 是一款功能强大的鼠标增强工具,它可以帮助用户提高鼠标操作效率和精准度。该软件可以自定义鼠标的各种功能和行为,让用户根据自己的习惯和需求来调整鼠标的表现。 详细功能 自定义鼠标按钮功能:可以为鼠标的各个按钮设置不同的功能…...
Android 圆形进度条CircleProgressView 基础版
一个最基础的自定义View 圆形进度条,可设置背景色、进度条颜色(渐变色)下载进度控制;可二次定制度高; 核心代码: Overrideprotected void onDraw(NonNull Canvas canvas) {super.onDraw(canvas);int mW g…...
理解磁盘结构---CHS---LAB---文件系统
1,初步了解磁盘 机械磁盘是计算机中唯的一个机械设备, 特点是慢,容量大,价格便宜。 磁盘上面的光面,由数不清的小磁铁构成,我们知道磁铁是有n/s极的,这刚好与二进制的&…...
我在1024谈华为
华为的发展历程与技术创新 华为自成立以来,一直是通信技术领域的重要参与者。让我们回顾一下华为的一些关键发展里程碑: 1987年,华为在深圳成立,起初专注于电话交换网络的研发和销售。 进入1990年代,华为转型为通信…...
NVR小程序接入平台/设备EasyNVR多品牌NVR管理工具/设备视频监控解决方案
随着科技的飞速发展,安防视频监控已成为维护公共安全、提升管理效率的重要手段。在这一领域中,NVR小程序接入平台/设备EasyNVR凭借其灵活的部署方式、强大的功能以及卓越的性能表现,脱颖而出,引领着安防视频监控的新纪元。 NVR小程…...
二叉树前序遍历的 Java 实现,包括递归和非递归两种方式
二叉树前序遍历是一种遍历树节点的方式,遵循特定的顺序。其基本过程可以总结为以下几个步骤: 前序遍历的顺序 访问根节点:首先处理当前节点。 递归遍历左子树:然后依次访问左子树。 递归遍历右子树:最后访问右子树。 …...
QT开发:构建现代UI的利器:深入详解QML和Qt Quick基础开发技术
目录 引言 目录 1. 什么是QML和Qt Quick QML的优势 2. QML基础语法 组件 属性 JavaScript表达式 3. 数据绑定 直接绑定 双向绑定 4. 属性和属性别名 属性 属性别名 5. 信号与槽机制 定义信号 处理信号 6. 动画与过渡效果 简单动画 过渡效果 7. 构…...
vue前端使用pdfjs与pdfdist-mergeofd 实现预览pdf并翻页,同时解决预览pdf显示模糊的问题
vue前端使用pdfjs与pdfdist-mergeofd 实现预览pdf并翻页,同时解决预览pdf显示模糊的问题 插件介绍 pdfdist-mergeofd插件的作用可查看这篇文章,同时使用ofdjs和pdfjs遇到的问题,和解决方法——懒加载 该插件主要是为了解决pdfjs和ofdjs同时…...
C语言——回调函数
1、回调函数 在学习了函数之后,我发现了一个比较难的函数——回调函数 回调函数 (Callback Function) 指的是一种函数,它被作为参数传递给另一个函数,并在满足特定条件或事件发生后被调用执行。 它允许你将一段代码延迟执行,或者…...
2016年ATom-1飞行活动期间以10秒间隔进行的一氧化碳(CO)观测数据
目录 简介 摘要 代码 引用 网址推荐 知识星球 机器学习 ATom: Observed and GEOS-5 Simulated CO Concentrations with Tagged Tracers for ATom-1 简介 该数据集包含2016年ATom-1飞行活动期间以10秒间隔进行的一氧化碳(CO)观测数据,…...
MLM之Emu3:Emu3(仅需下一个Token预测)的简介、安装和使用方法、案例应用之详细攻略
MLM之Emu3:Emu3(仅需下一个Token预测)的简介、安装和使用方法、案例应用之详细攻略 导读:这篇论文介绍了Emu3,一个基于单一Transformer架构,仅使用下一个token预测进行训练的多模态模型。 >> 背景痛点: 多模态任…...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...
阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...
Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...
自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...
Swagger和OpenApi的前世今生
Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章,二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑: 🔄 一、起源与初创期:Swagger的诞生(2010-2014) 核心…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...
关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...
Fabric V2.5 通用溯源系统——增加图片上传与下载功能
fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...
