大模型 LangChain-LangGraph 初探

news2025/1/8 12:41:09

大模型 LangChain-LangGraph 初探

一、LangGraph 简介

LangGraph(https://langchain-ai.github.io/langgraph/)是一个用于构建有状态、多参与者应用程序的库,在创建代理和多代理工作流方面发挥着重要作用。与其他大语言模型(LLM)框架相比,它具备一些独特的核心优势:

(一)循环

LangGraph 允许定义涉及循环的流程,这一特性对于大多数代理架构而言是不可或缺的。许多实际应用场景中,任务的处理可能需要多次迭代或重复某些操作,LangGraph 的循环功能使得在这些情况下能够更加灵活地设计和实现工作流,使其区别于基于有向无环图(DAG)的解决方案。

(二)可控性

作为一个低级框架,LangGraph 提供了对应用程序流程和状态的细粒度控制。在开发复杂的代理应用时,开发人员需要精确掌控每一个环节和状态的变化,LangGraph 能够满足这一需求,这对于创建可靠、稳定且高效的代理应用至关重要。

(三)持久性

LangGraph 包含内置持久性,这一特性为实现高级的人机循环和记忆功能提供了有力支持。例如,在一个持续交互的聊天机器人应用中,它可以记住之前的对话内容和状态,从而为用户提供更加连贯和个性化的服务,提升用户体验。

LangGraph 主要用于搭建和设计 agents 的复杂工作流,比如调用搜索引擎 API、调用第三方接口等,并能够细致地设计各个节点细节和状态流转。

二、官方示例

(一)构建一个简单的聊天机器人

在官方示例中,遇到的坑:

最初尝试使用 deepseek 模型来构建聊天机器人,但遇到了 function calling 一直不返回结果的问题,这导致大模型节点和 tool 节点陷入循环无法结束。经过排查和尝试,将模型更换为豆包的大模型后,function calling 能够正常返回结果,从而使整个流程得以正常运行。这一过程凸显了在开发过程中模型选择和适配的重要性,不同模型在功能实现和性能表现上可能存在差异,需要根据具体需求和实际情况进行选择。

(二)代码实现细节

  1. 导入必要的模块和类
from langchain_core.runnables import RunnableLambda
from langgraph.prebuilt import ToolNode, tools_condition
from typing import Annotated
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import add_messages
from langchain_openai import ChatOpenAI
from IPython.display import Image, display
from langchain_community.tools import DuckDuckGoSearchRun, DuckDuckGoSearchResults
import json
from langchain_core.messages import ToolMessage
from langgraph.checkpoint.memory import MemorySaver
from langchain_core.messages import AIMessage, ToolMessage

这些导入的模块和类涵盖了构建 LangGraph 应用所需的各种功能,包括定义可运行对象、工具节点、状态图、消息处理、大模型调用、搜索工具、内存管理以及消息类型等。

  1. 定义状态类(State)
class State(TypedDict):
    messages: Annotated[list, add_messages]

这里定义了一个名为 State 的类,它继承自 TypedDict。其中包含一个键为 messages 的属性,其值为一个列表,并且通过 add_messages 注解指定了新消息的添加方式(即每次添加新消息而不是覆盖原有消息)。这个状态类用于管理应用程序在运行过程中的状态信息,特别是与消息相关的状态。

  1. 定义聊天模型(chatModel 函数)
def chatModel():
    llm = ChatOpenAI(
        model='ep-20250106175109-npkpj',
        openai_api_key='<api-key>',
        openai_api_base='https://ark.cn-beijing.volces.com/api/v3',
        max_tokens=1024)
    return llm

该函数用于创建并返回一个 ChatOpenAI 模型实例,指定了模型的名称、API 密钥、API 基础地址以及最大令牌数。这个聊天模型将作为应用程序的核心组件,负责处理用户输入并生成相应的回复。

  1. 定义搜索工具(serach_tool 函数)
def serach_tool():
    search = DuckDuckGoSearchResults(max_results=1)
    return search

此函数创建并返回一个 DuckDuckGoSearchResults 实例,用于执行网络搜索操作。通过设置 max_results=1,限制每次搜索返回的结果数量为 1 个,以便在后续处理中更加方便地获取和处理最相关的搜索结果。

  1. 定义聊天机器人(chatbot 函数)
def chatbot(state: State):
    return {"messages": [llm_with_tools.invoke(state["messages"])]}

聊天机器人函数接受一个 State 类型的参数,它通过调用绑定了工具的大模型(llm_with_tools)的 invoke 方法,传入当前状态中的消息列表,获取模型的回复,并将回复包装在一个包含 messages 键的字典中返回。

  1. 定义状态机图(graph 函数)
def graph():
    memory = MemorySaver()
    tool_node = ToolNode(tools=tools)
    graph_builder = StateGraph(State)
    graph_builder.add_node("tools", tool_node)
    graph_builder.add_node("chatbot", chatbot)
    graph_builder.add_conditional_edges(
        "chatbot",
        tools_condition
    )
    graph_builder.add_edge("tools", "chatbot")
    graph_builder.set_entry_point("chatbot")
    graph = graph_builder.compile(checkpointer=memory)
    return graph

在 graph 函数中,首先创建了一个 MemorySaver 实例用于内存管理,接着定义了一个 ToolNode 工具节点并传入之前定义的搜索工具列表。然后构建了一个 StateGraph 状态机图,向其中添加了工具节点和聊天机器人节点,并设置了条件边和普通边来定义节点之间的流转关系。最后通过 compile 方法编译状态机图,并传入内存管理对象,返回构建好的状态机图。

在这里插入图片描述

  1. 定义聊天交互循环(chat 函数)
def chat():
    while True:
        try:
            user_input = input("User: ")
            if user_input.lower() in ["退下吧"]:
                print("再见!")
                break
            print("User:", user_input)
            stream_graph_updates(user_input)
        except:
            user_input = "no"
            print("User: " + user_input)
            stream_graph_updates(user_input)
            break

聊天函数实现了一个持续循环,等待用户输入。当用户输入 “退下吧” 时,循环结束并打印再见信息。对于其他用户输入,首先打印用户输入内容,然后调用 stream_graph_updates 函数来更新状态机图并获取模型的回复。如果在输入过程中出现异常,将用户输入设置为 “no” 并继续处理。

  1. 定义工具集合(tools 列表)和绑定工具的大模型(llm_with_tools)
tools = [serach_tool()]
llm_with_tools = chatModel().bind_tools(tools)
graph = graph()
config = {"configurable": {"thread_id": "1"}}

这里创建了一个包含搜索工具的列表 tools,并通过调用 chatModel 函数获取大模型实例,然后使用 bind_tools 方法将工具绑定到大模型上,得到一个可以在处理过程中调用工具的模型实例。

  1. 主程序入口
if __name__ == '__main__':
    show()
    chat()

在主程序入口部分,首先调用 show 函数来展示状态机图(如果相关依赖满足),然后调用 chat 函数启动聊天交互循环,使整个应用程序开始运行并与用户进行交互。

(三)示例运行结果分析

结果:

User: 你好,我叫彦祖
Assistant: 你好,彦祖,很高兴认识你呀。
User: 北京的天气怎么样
Assistant: 
当前提供了 1 个工具,分别是["duckduckgo_results_json"],需求是查询北京的天气,需要调用 duckduckgo_results_json 获取信息。
Assistant: snippet: 据最新天气预报显示,今天,北京天气晴转多云,最高气温6℃,最低气温零下6℃,昼夜温差较大,并且周末两天,北京以晴到多云天气为主,气温变化不大,最低气温零下3℃至零下4℃,而且根据天气预报还提供的其他气象信息,如空气质量、湿度等,公众在 ..., title: 北京 天气预报15, link: https://www.tianqi.com/beijing/15/, snippet: 周末两天北京以晴到多云天气为主 气温变化不大. 据最新天气预报显示,今天,北京天气晴转多云,最高气温6℃,最低气温零下6℃,昼夜温差较大,并且周末两天,北京以晴到多云天气为主,气温变化不大,最低气温零下3℃至零下4℃,而且根据天气预报还提供的其他气象信息,如空气质量、湿度 ..., title: 【北京天气预报】北京天气预报一周,北京天气预报15,30,今天,明天,7,10,未来北京一周天气预报查询—天气网, link: https://www.tianqi.com/beijing/, snippet: Beijing Weather Forecasts. Weather Underground provides local & long-range weather forecasts, weatherreports, maps & tropical weather conditions for the Beijing area., title: Beijing, People's Republic of China Weather Conditions, link: https://www.wunderground.com/weather/cn/beijing, snippet: Weather report for Beijing. During the night and in the first hours of the day a few clouds are expected, the sky clears in the afternoon. It is a sunny day., title: Weather Beijing - meteoblue, link: https://www.meteoblue.com/en/weather/week/beijing_china_1816670
Assistant: 根据查询到的信息,当前北京天气晴转多云,最高气温 6℃,最低气温零下 6℃。周末两天北京以晴到多云天气为主,气温变化不大,最低气温在零下 3℃至零下 4℃。同时,你还可以通过相关的天气预报网站或应用获取更详细准确的实时天气信息。
User: 好的,我叫什么名字
Assistant: 你说你叫彦祖呀。
再见!
  1. 初次交互
    当用户输入 “你好,我叫彦祖” 时,聊天机器人回复 “你好,彦祖,很高兴认识你呀。” 这表明聊天机器人能够正常理解用户的问候并做出相应的友好回复,说明大模型在基本的文本生成和对话处理方面功能正常。
  2. 查询北京天气
    用户询问 “北京的天气怎么样” 时,聊天机器人首先识别出需要查询天气信息,然后利用绑定的 DuckDuckGoSearchResults 工具进行网络搜索。从返回的结果可以看到,它获取了多个来源的天气预报信息,包括天气网、Weather Underground 等。最终,聊天机器人整合这些信息并回复给用户:“根据查询到的信息,当前北京天气晴转多云,最高气温 6℃,最低气温零下 6℃。周末两天北京以晴到多云天气为主,气温变化不大,最低气温在零下 3℃至零下 4℃。同时,你还可以通过相关的天气预报网站或应用获取更详细准确的实时天气信息。” 这展示了 LangGraph 如何通过工具调用和大模型的信息处理能力,为用户提供准确的实时信息查询服务。
  3. 回忆用户姓名
    当用户询问 “好的,我叫什么名字” 时,聊天机器人准确地回答 “你说你叫彦祖呀。” 这体现了聊天机器人在对话过程中能够保持一定的记忆能力,记住之前用户提到的姓名信息,这得益于 LangGraph 的内置持久性和状态管理机制。

(四)总结与思考

通过对 LangGraph 官方示例的详细分析,我们可以看到它在构建复杂的代理应用程序方面的强大功能和灵活性。它不仅能够整合大模型的语言处理能力,还能够方便地调用外部工具,实现诸如信息查询等功能,并通过状态管理和流程控制来确保整个应用的稳定运行和良好交互体验。然而,在实际应用中,仍然可能会遇到一些问题,如模型适配问题,这提醒我们在开发过程中需要充分测试和评估不同模型和工具的组合,以选择最适合项目需求的方案。同时,随着技术的不断发展,LangGraph 等类似框架在多模态处理、更复杂的工作流设计以及性能优化等方面还有很大的提升空间,值得我们持续关注和深入研究。

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

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

相关文章

yolov5核查数据标注漏报和误报

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、误报二、漏报三、源码总结 前言 本文主要用于记录数据标注和模型预测之间的漏报和误报思想及其源码 提示&#xff1a;以下是本篇文章正文内容&#xff0c;…

【Linux】进程间通信(一)

目录 一、进程间通信1.1 进程间通信目的1.2 理解进程间通信1.3 进程间通信发展1.4 进程间通信分类 二、管道2.1 什么是管道2.2 管道的原理2.3 匿名管道2.3.1 pipe函数2.3.2 匿名管道的实现2.3.3 匿名管道小结2.3.3.1 匿名管道的四种情况2.3.3.2 匿名管道的五种特性 2.3.4 匿名管…

【QT-QTableView实现鼠标悬浮(hover)行高亮显示+并设置表格样式】

1、自定义委托类 HoverDelegate hoverdelegate.h #ifndef HOVERDELEGATE_H #define HOVERDELEGATE_H#include <QObject> #include <QStyledItemDelegate>class hoverdelegate : public QStyledItemDelegate {Q_OBJECT // 添加 Q_OBJECT 宏public:explicit hoverde…

Elasticsearch:基础概念

这里写目录标题 一、什么是Elasticsearch1、基础介绍2、什么是全文检索3、倒排索引4、索引&#xff08;1&#xff09;创建索引a 创建索引基本语法b 只定义索引名&#xff0c;setting、mapping取默认值c 创建一个名为student_index的索引&#xff0c;并设置一些自定义字段 &…

RAG Logger:RAG日志记录工具

您听说过 RAG Logger 吗&#xff1f; 它是一款专为检索增强生成 (RAG) 应用程序设计的开源日志记录工具&#xff01; 据说它可以作为 LangSmith 的轻量级替代方案&#xff0c;满足 RAG 特定的日志记录需求。 查询、搜索结果、LLM 交互和性能指标可以以 JSON 格式记录。 特点 …

Spark-Streaming有状态计算

一、上下文 《Spark-Streaming初识》中的NetworkWordCount示例只能统计每个微批下的单词的数量&#xff0c;那么如何才能统计从开始加载数据到当下的所有数量呢&#xff1f;下面我们就来通过官方例子学习下Spark-Streaming有状态计算。 二、官方例子 所属包&#xff1a;org.…

gesp(C++四级)(4)洛谷:B3851:[GESP202306 四级] 图像压缩

gesp(C四级)&#xff08;4&#xff09;洛谷&#xff1a;B3851&#xff1a;[GESP202306 四级] 图像压缩 题目描述 图像是由很多的像素点组成的。如果用 0 0 0 表示黑&#xff0c; 255 255 255 表示白&#xff0c; 0 0 0 和 255 255 255 之间的值代表不同程度的灰色&#xff0…

链地址法(哈希桶)

链地址法&#xff08;哈希桶&#xff09; 解决冲突的思路 开放定址法中所有的元素都放到哈希表⾥&#xff0c;链地址法中所有的数据不再直接存储在哈希表中&#xff0c;哈希表 中存储⼀个指针&#xff0c;没有数据映射这个位置时&#xff0c;这个指针为空&#xff0c;有多个数…

【通识安全】煤气中毒急救的处置

1.煤气中毒的主要症状与体征一氧化碳中毒&#xff0c;其中毒症状一般分为轻、中、重三种。 (1)轻度&#xff1a;仅有头晕、头痛、眼花、心慌、胸闷、恶心等症状。如迅速打开门窗&#xff0c;或将病人移出中毒环境&#xff0c;使之吸入新鲜空气和休息&#xff0c;给些热饮料&am…

Synthesia技术浅析(二):虚拟人物视频生成

Synthesia 的虚拟人物视频生成模块是其核心技术之一&#xff0c;能够将文本输入转换为带有同步语音和口型的虚拟人物视频。该模块如下所示&#xff1a; 1.文本输入处理 2.语音生成&#xff08;TTS, Text-to-Speech&#xff09; 3.口型同步&#xff08;Lip Syncing&#xff0…

【算法】算法初步

要学好数据结构和算法的设计与分析&#xff0c;请务必先打好C语言基础&#xff0c;因为C语言中的数据存储、内存映射、指针等等概念最接近计算机的底层原理&#xff0c;数据结构是数据在内存空间当中的组织形式&#xff0c;而算法则是提供了解决某个问题的一种思路&#xff0c;…

年会抽奖Html

在这里插入图片描述 <!-- <video id"backgroundMusic" src"file:///D:/background.mp3" loop autoplay></video> --> <divstyle"width: 290px; height: 580px; margin-left: 20px; margin-top: 20px; background: url(D:/nianhu…

LLM 实现Malleable 软件

All computer users may soon have the ability to author small bits of code. What structural changes does this imply for the production and distribution of software? 如果每个终端用户都能修改一部分代码&#xff0c; 这个将会对软件的生产和分发有何重大改变&#…

国产编辑器EverEdit - 两种删除空白行的方法

1 使用技巧&#xff1a;删除空白行 1.1 应用场景 用户在编辑文档时&#xff0c;可能会遇到很多空白行需要删除的情况&#xff0c;比如从网页上拷贝文字&#xff0c;可能就会存在大量的空白行要删除。 1.2 使用方法 1.2.1 方法1&#xff1a; 使用编辑主菜单 选择主菜单编辑 …

出租号平台网站系统源码/单合租用模式 提供用户提现功能

这是一款租号平台源码&#xff0c;采用常见的租号模式对接的易支付。目前网络上还很少见到此类类型的源码。 程序采用thinkphp6.0开发&#xff0c;前端采用layui 程序开发&#xff1a;PHPMySQL 程序演示&#xff1a;zh1.yetukeji.top, 账户 13112215717 &#xff0c;密码qq2…

C++:位与运算符

& 一&#xff0c;位与运算符的运算规则 有0则0。 二&#xff0c;判断奇偶性 %&#xff1a;优先级高&#xff0c;效率低 &&#xff1a;优先级低&#xff0c;效率高 数与1的位与运算结果为1则为奇数&#xff0c;结果为0则为偶数 三&#xff0c;获取一个数二进制的后…

第 31 章 - 源码篇 - Elasticsearch 写入流程深入分析

写入源码分析 接收与处理 请求首先会被 Netty4HttpServerTransport 接收&#xff0c;接着交由 RestController 进行路由分发。 private void tryAllHandlers(final RestRequest request, final RestChannel channel, final ThreadContext threadContext) throws Exception {…

C语言----指针

目录 1.概念 2.格式 3.指针操作符 4.初始化 1. 将普通变量的地址赋值给指针变量 a. 将数组的首地址赋值给指针变量 b. 将指针变量里面保存的地址赋值给另一个指针变量 5.指针运算 5.1算术运算 5.2 关系运算 指针的大小 总结&#xff1a; 段错误 指针修饰 1. con…

Java高频面试之SE-09

hello啊&#xff0c;各位观众姥爷们&#xff01;&#xff01;&#xff01;本牛马baby今天又来了&#xff01;哈哈哈哈哈嗝&#x1f436; final关键字有什么作用&#xff1f; 在 Java 中&#xff0c;final 关键字有多个用途&#xff0c;它可以用于类、方法和变量。根据使用的上…

ChatGPT 主流模型GPT-4/GPT-4o mini的参数规模是多大?

微软论文又把 OpenAI 的机密泄露了&#xff1f;&#xff1f;在论文中明晃晃写着&#xff1a; o1-preview 约 300B&#xff1b;o1-mini 约 100BGPT-4o 约 200B&#xff1b;GPT-4o-mini 约 8BClaude 3.5 Sonnet 2024-10-22 版本约 175B微软自己的 Phi-3-7B&#xff0c;这个不用约…