使用LangChain、LangGraph和LangSmith来创建AI Agent

LangGraph

LangGraph是建立在LangChain之上的一个框架,它使得创建和管理智能体(Agent)及其运行时环境变得更加简单。

在LangChain的架构中,智能体是指由语言模型控制的系统,它能够自主决策接下来要执行的操作。而智能体运行时则负责维持这个系统的持续运行,它不断地进行决策、记录执行过程中的观察结果,并维持这样的循环直到智能体完成既定任务。

LangChain通过其特有的表达语言,使得定制智能体变得更加简便。而LangGraph在此基础上,为智能体运行时提供了更加灵活和动态的自定义功能。在LangChain中,传统的智能体运行时是通过AgentEX类实现的,而LangGraph的引入为智能体运行时带来了更多的多样性和适应性。

LangGraph的一个显著特点是为智能体运行时引入了循环机制,这对于智能体的操作至关重要。

在LangGraph中,有两种主要的智能体运行时:

  1. Agent Executor:它与LangChain中的类似,但在LangGraph中需要进行重新构建。
  2. Chat Agent Executor:它以消息列表的形式来处理智能体状态,这使得它非常适合于基于聊天的模型,这些模型通常通过消息来进行功能调用和响应。

通过LangGraph,开发者可以更加高效地构建和定制智能体,以及管理它们的运行时环境,从而实现更加强大和灵活的智能体应用。

LangSmith

LangSmith 是个先进的平台,专为创建生产级别的语言模型应用程序而设计。这个平台赋予了用户强大的能力,可以轻松地对任何基于语言模型的框架进行调试、测试、评估和监控。更值得一提的是,LangSmith 与 LangChain 实现了无缝对接。LangChain 公司,作为 LangChain 框架的主要支持者,也是 LangSmith 的开发者。

虽然 LangSmith 仍处于发展的早期阶段,但其已经展现出了巨大的潜力。目前,LangSmith 最显著的优势在于它能够对 LangChain 应用进行高效的调试和跟踪,这一功能极大地缩短了学习 LangChain 的曲线,并显著提升了开发效率。

尽管使用 LangChain 来构建语言模型应用原型或代理很简单,但要将这些原型转化为实际可用的产品却充满了挑战。这通常涉及到对模型的大量定制工作,以及不断地优化提示语(Prompt)、链和其他组件。LangSmith 的出现正是为了解决这些难题,它可以帮助开发者迅速地调试和优化链、代理或工具集,直观地展示不同组件间的交互情况,并对各种提示语进行有效评估。

注册地址:https://smith.langchain.com/。

LANGCHAIN_TRACING_V2是设置LangChain是否开启日志跟踪模式。

LANGCHAIN_PROJECT 是要跟踪的项目名称,如果LangSmith平台上还没有这个项目,会自动创建。如果不设置这个环境变量,会把相关信息写到default项目。这里的项目不需要跟实际的项目对应,可以理解为分类或者标签。

代码实现

from langchain_community.tools.tavily_search import TavilySearchResults
from langgraph.prebuilt import ToolExecutor
from langchain.tools.render import format_tool_to_openai_function
from langchain_core.messages import HumanMessage
from typing import TypedDict, Annotated, Sequence
import operator
from langchain_core.messages import BaseMessage
from langgraph.prebuilt import ToolInvocation
from langchain_core.messages import FunctionMessage
from langgraph.graph import StateGraph, END
from langchain_core.messages import AIMessage
import json
import os
from langchain.chat_models import AzureChatOpenAI

# 替换key
os.environ["OPENAI_API_TYPE"] = "azure"
os.environ["OPENAI_API_VERSION"] = "2023-03-15-preview"
os.environ["OPENAI_API_BASE"] = "https://xxxxxx.openai.azure.com/"
os.environ['OPENAI_API_KEY'] = ""

os.environ['TAVILY_API_KEY'] = "tvly-xxxxxx"

os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_PROJECT"] = f"langchain_to_graph"
os.environ["LANGCHAIN_ENDPOINT"] = "https://api.smith.langchain.com"
os.environ["LANGCHAIN_API_KEY"] = "ls__xxxxxx"

model = AzureChatOpenAI(deployment_name="dev", temperature=0)

tools = [TavilySearchResults(max_results=1)]
tool_executor = ToolExecutor(tools)

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]


def should_continue(state):
    """
    Define the function that determines whether to continue or not
    """
    messages = state['messages']
    last_message = messages[-1]
    if "function_call" not in last_message.additional_kwargs:
        return "end"
    else:
        return "continue"


def call_model(state):
    """
    Define the function that calls the model,控制代理如何与其消息历史进行交互
    """
    messages = state['messages'][-5:]
    response = model.invoke(messages)
    # return a list, because this will get added to the existing list
    return {"messages": [response]}


def first_model(state):
    """
    the first call of the model we want to explicitly hard-code some action
    """
    human_input = state['messages'][-1].content
    return {
        "messages": [
            AIMessage(
                content="",
                additional_kwargs={
                    "function_call": {
                        "name": "tavily_search_results_json",
                        "arguments": json.dumps({"query": human_input})
                    }
                }
            )
        ]
    }


def call_tool(state):
    """
    Define the function to execute tools
    """
    messages = state['messages']
    # Based on the 'continue' condition,the last message involves a function call
    last_message = messages[-1]
    action = 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 response
    response = tool_executor.invoke(action)
    function_message = FunctionMessage(content=str(response), name=action.tool)
    return {"messages": [function_message]}


# Define a new graph
workflow = StateGraph(AgentState)
# Define the new entrypoint
workflow.add_node("first_agent", first_model)
# 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 node is the first one called
workflow.set_entry_point("first_agent")
# We now add a conditional edge
workflow.add_conditional_edges(
    "agent",
    should_continue,
    {
        "continue": "action",
        "end": END
    }
)
# We now add a normal edge from `tools` to `agent`,after `tools` is called, `agent` node is called next.
workflow.add_edge('action', 'agent')
# After we call the first agent, we know we want to go to action
workflow.add_edge('first_agent', 'action')
# 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 sf")]}
print(app.invoke(inputs))

 

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

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

相关文章

js算法记录

> 更多请前往 https://www.passerma.com/article/86 滑动窗口 1 给定一个矩阵,包含N*M个整数,和一个包含K个整数的数组。现在要求在这个矩阵中找一个宽度最小的子矩阵,要求子矩阵包含数组中所有的整数 function minSubmatrixWidth(mat…

【Redis教程0x07】Redis持久化之AOF日志

引言 在【Redis教程0x06】中我们说到过,Redis的持久化有3种策略:RDB快照、AOF日志、RDB和AOF混合持久化。 本篇博客我们就将介绍一下AOF日志是怎么回事,以及混合持久化是怎么实现的。 AOF持久化 AOF日志 AOF是Append Only File的缩写&…

c语言知识点整理------基础c语言框架,数据类型,变量常量,注释

前言 本文不涉及讲解原理,用简洁明了的风格,去整理方便查阅的知识点。 (适合有编程基础,或者需要作为笔记的人群使用) 程序基本框架 结果会输出hello world。 程序的执行 c语言属于编译型语言。 代码执行分为五个…

阿里云服务器租用价格表-2024最新(附明细报价)

2024年阿里云服务器优惠价格表,一张表整理阿里云服务器最新报价,阿里云服务器网aliyunfuwuqi.com整理云服务器ECS和轻量应用服务器详细CPU内存、公网带宽和系统盘详细配置报价单,大家也可以直接移步到阿里云CLUB中心查看 aliyun.club 当前最新…

如何在家中使用手机平板电脑 公司iStoreOS软路由实现远程桌面

文章目录 简介一、配置远程桌面公网地址二、家中使用永久固定地址 访问公司电脑**具体操作方法是:** 简介 软路由是PC的硬件加上路由系统来实现路由器的功能,也可以说是使用软件达成路由功能的路由器。 使用软路由控制局域网内计算机的好处&#xff1a…

el-select动态禁用

在一个el-form表单中有5个el-form-item; 每个el-form-item是一个el-select控件; 这5个el-select控件遵循这样的规则,都是使用同一个list集合,如果第一个el-select选择了list中的某一项,那么这一项就被禁用;其他的el-…

数据库-索引快速学

索引 当表中数据量庞大时,往往搜索一条数据就会耗费很长的时间等待 索引是帮助数据库高效获取数据的数据结构 create index 索引名 on 数据表名(字段名);为该表下的某一字段创建索引,检索耗时会大大的减小 索引的优缺点 优点&…

linux下关闭swap文件系统

临时关闭(马上生效) 永久关闭(重启计算机才能生效) vim /etc/fstab

libVLC 动态视频壁纸

在 Windows 上,你可能需要使用 Windows API 来设置壁纸,而在 Linux 上,你可能需要使用某种桌面环境特有的方法。在 macOS 上,这一功能可能受到限制。 效果图如下所示: 以下是一个简单的示例,说明了如何在 …

MICS:流量分析

前言&#xff1a; 有时候得到的文件后缀为pcap、pcapng等流量包的题&#xff0c;则需要我们分析流量包找出flag。 一、无线流量数据爆破 打开wirshark分析&#xff0c;发现都是那种WLAN的包&#xff0c;则可以判断为无线密码加密。 命令&#xff1a;aircrack-ng <包文件>…

访问者模式(数据与行为解耦)

目录 前言 UML plantuml 类图 实战代码 SimpleFileVisitor FileVisitor 接口 删除指定文件夹 模板 IVisitor IVisitable Client 前言 一个类由成员变量和方法组成&#xff0c;成员变量即是类的数据结构&#xff0c;方法则是类的行为。 如果一个类的数据结构稳定&am…

微分几何:曲线基本理论

参数曲线基本理论 曲线的定义 假设有一个运动的质点&#xff0c;从0到T时刻&#xff0c;质点从A点运动到B点&#xff0c;质点运动的轨迹形成了一条曲线&#xff0c;我们可以将这条路径曲线看成是时间 t ∈ [ 0 , T ] t \in [0,T] t∈[0,T]到空间位置 R R R的映射。 映射的概念…

Flink SQL 基于Update流出现空值无法过滤问题

问题背景 问题描述 基于Flink-CDC &#xff0c;Flink SQL的实时计算作业在运行一段时间后&#xff0c;突然发现插入数据库的计算结果发生部分主键属性发生失败&#xff0c;导致后续计算结果无法插入&#xff0c; 超过失败次数失败的情况问题报错 Caused by: java.sql.BatchUp…

MySQL面试汇总(一)

MySQL 如何定位慢查询 如何优化慢查询 索引及其底层实现 索引是一个数据结构&#xff0c;可以帮助MySQL高效获取数据。 聚簇索引和非聚簇索引 覆盖索引 索引创建原则 联合索引

前端学习<二>CSS基础——04-CSS选择器:伪类

伪类&#xff08;伪类选择器&#xff09; 伪类&#xff1a;同一个标签&#xff0c;根据其不同的种状态&#xff0c;有不同的样式。这就叫做“伪类”。伪类用冒号来表示。 比如div是属于box类&#xff0c;这一点很明确&#xff0c;就是属于box类。但是a属于什么类&#xff1f;…

前端js计算日期 实现倒计时效果

<!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <title>倒计时示例</title> <style> #countdown { font-size: 24px; } #countdown span { margin-right: 10p…

未来制造:机器人行业新质生产力提升策略

机器人行业新质生产力提升咨询方案 一、机器人行业目前发展现状及特点&#xff1a; 创新活跃、应用广泛、成长性强。 二、机器人企业发展新质生产力面临的痛点&#xff1a; 1、高端人才匮乏 2、核心技术受限 3、竞争日益国际化 4、成本控制挑战 5、用户体验提升需求 三…

Linux软件安装:源代码与Tarball

文章目录 Linux源码包的安装与升级什么是源代码、编译器与可执行文件什么是函数库什么是make与configure什么是Tarball的软件如何安装与升级软件 使用gcc进行编译的简单实例单一程序&#xff1a;打印 Hello World主、子程序链接&#xff1a;子程序的编译调用外部函数库&#xf…

三轴工作台激光焊接机:实现高精度、高效率焊接的新选择

三轴工作台激光焊接机是一种先进的焊接设备&#xff0c;结合了激光焊接技术与三轴工作台的运动控制&#xff0c;实现了焊接过程的高效、精准与自动化。这种设备主要利用激光束的高能量密度和高速度特性&#xff0c;使工件在熔化的同时快速冷却凝固&#xff0c;从而达到高质量的…

AXI Memory Mapped to PCI Express学习笔记(一)——PCIe事务

1 PCIe事务 AXI事务对于PCIe来说&#xff0c;主要涉及到在AXI总线和PCIe总线之间进行数据交换和通信的过程。在PCIe系统中&#xff0c;AXI总线作为一个连接不同组件的桥梁&#xff0c;可以实现高效的数据传输和事务处理。 AXI事务通常包括读事务和写事务。在读事务中&#xf…