深入浅出 LangGraph —— 第3章:图的核心概念:节点、边与状态

深入浅出LangGraph AI Agent智能体开发教程(一)—全面认识LangGraph 本期分享从LangGraph与LangChain的对比出发,介绍了LangGraph的三层核心架构、完整生态工具,带大家全面认识最火热最全面的智能体开发框架LangGraph。 阅读详情

📖 本章学习目标

  • ✅ 深刻理解节点(Node)、边(Edge)、状态(State)三者的关系
  • ✅ 掌握使用 Annotation 定义类型安全的自定义状态
  • ✅ 学会添加普通边、条件边和自环边
  • ✅ 理解图的编译与执行流程
  • ✅ 能够独立设计并实现一个多节点工作流图
  • ✅ 避免常见的状态管理和路由错误

一、为什么用"图"来建模 Agent

1、传统链式调用的局限

在 LangChain 早期,开发者使用 链(Chain) 来组织 LLM 调用。链是线性的——输入进去,依次经过每个步骤,输出出来。这在简单场景下没问题,但当业务逻辑复杂时,麻烦就来了:

  • ❌ 无法根据 LLM 的输出动态决定"下一步走哪"
  • ❌ 无法在某个步骤"等待人类审批"后继续
  • ❌ 无法在出错时跳回某个节点重试
  • ❌ 多 Agent 协作时的状态共享极其复杂

输入

步骤1

步骤2

步骤3

输出

链就像工厂的流水线,产品只能按固定顺序经过每个工位,无法根据产品质量决定是否需要返工或跳过某些工序。

2、图模型的优势

图(Graph)天然支持这些场景:节点表示"做什么",边表示"走哪里",状态表示"记住什么"。

维度链(Chain)图(Graph)
执行路径固定线性动态分支
循环支持❌ 不支持✅ 原生支持
状态管理手动传递自动共享
人机交互❌ 困难✅ 内置支持
可视化调试❌ 困难✅ 图结构清晰

需要搜索

直接回答

▶ START

节点A
分析问题

条件判断

节点B
搜索信息

节点C
生成回复

⏹ END

图就像城市的交通网络,你可以根据实时路况(状态)选择不同的路线(边),到达不同的目的地(节点)。


二、三大核心概念

1、状态(State)——图的"记忆"

状态是整个图的共享数据容器。你可以把它想象成一个白板——图中的每个节点都能读取白板上的内容,也能往白板上写新内容。

读取 State

更新 State

读取 State

更新 State

📋 State
{messages, count, ...}

节点A

节点B

关键特性:状态在节点之间自动传递和合并,你不需要手动把一个节点的输出传给下一个节点。

状态的生命周期:

  1. 初始化:调用 graph.invoke() 时提供初始状态
  2. 传递:每个节点接收当前完整的 State
  3. 更新:节点返回需要更新的字段
  4. 合并:LangGraph 使用 Reducer 合并新旧状态
  5. 持久化(可选):通过 Checkpointer 保存到数据库

2、节点(Node)——图的"工人"

节点是图中的处理单元,是一个纯函数(或异步函数):

节点函数签名:(state: State) => Partial<State> | Promise<Partial<State>>
  • 输入:当前完整的 State
  • 输出:需要更新的 State 字段(只需返回变化的部分)

节点就像流水线上的工人——拿到当前工件(State),加工后把变化的部分交回去。

节点的最佳实践:

✅ 好的节点设计:

  • 单一职责:每个节点只做一件事
  • 纯函数:相同的输入产生相同的输出
  • 无副作用:不修改外部变量,只操作 State
  • 快速执行:避免长时间阻塞

❌ 不好的节点设计:

  • 承担多个职责(既分析又搜索又回复)
  • 依赖全局变量或外部状态
  • 直接修改传入的 state 对象
  • 执行时间不可控(如无限循环)

3、边(Edge)——图的"道路"

边决定节点执行完后"下一步去哪"。LangGraph 支持三种边:

边类型说明方法适用场景
普通边A 执行完永远去 BaddEdge(A, B)顺序执行的固定流程
条件边根据 State 动态决定去哪addConditionalEdges(A, routerFn)分支逻辑、动态路由
起止边连接内置的起点/终点addEdge('__start__', A)图的入口和出口

普通边

addEdge

节点A

节点B

条件边

return 'B'

return 'C'

节点A

routerFn

节点B

节点C

起止边

addEdge

addEdge

__start__

节点A

__end__


三、使用 Annotation 定义状态

1、内置注解:MessagesAnnotation

LangGraph 提供了开箱即用的消息状态注解:

import { MessagesAnnotation, StateGraph } from '@langchain/langgraph';

// MessagesAnnotation 等价于以下定义:
// { messages: BaseMessage[], 带自动追加(append)的 reducer }
const graph = new StateGraph(MessagesAnnotation);

MessagesAnnotation内置了 messages 字段,其 reducer 是"追加"语义:新消息追加到历史,而不是替换。 这是对话类 Agent 最常用的状态定义,无需手动定义,直接使用即可

2、自定义注解:Annotation.Root

当你需要除消息之外的自定义字段时,使用 Annotation.Root:

import { Annotation, StateGraph } from '@langchain/langgraph';

// 定义自定义状态
const AgentState = Annotation.Root({
  // 字符串字段:默认 reducer 是"覆盖"
  topic: Annotation<string>(),
  
  // 数字字段:自定义 reducer(累加)
  retryCount: Annotation<number>({
    reducer: (current, update) => current + update,
    default: () => 0,
  }),
  
  // 数组字段:自定义 reducer(追加)
  results: Annotation<string[]>({
    reducer: (current, update) => [...current, ...update],
    default: () => [],
  }),
});
  • Annotation.Root({}):创建状态定义,每个字段对应状态的一部分
  • Annotation<T>():简单字段,默认 reducer 是"用新值覆盖旧值"
  • reducer:自定义合并逻辑,(当前值, 新值) => 合并后的值
  • default:字段的初始值工厂函数,必须提供以避免 undefined

常见 Reducer 模式:

  1. 覆盖(默认):(curr, update) => update
  2. 追加:(curr, update) => [...curr, ...update]
  3. 累加:(curr, update) => curr + update
  4. 合并对象:(curr, update) => ({ ...curr, ...update })

3、访问状态类型

// 从注解中提取 TypeScript 类型,用于函数签名
type AgentStateType = typeof AgentState.State;

// 在节点函数中使用
async function myNode(state: AgentStateType) {
  console.log('当前话题:', state.topic);
  console.log('重试次数:', state.retryCount);
  
  return {
    retryCount: 1,  // 触发 reducer:retryCount += 1
    results: ['新结果'],  // 触发 reducer:追加到数组
  };
}

通过AgentState.State提取状态的 TypeScript 类型定义。节点执行后只需返回需要更新的字段,未返回的字段保持不变,其返回值经过 reducer 处理后才写入 State,TypeScript 会检查返回值的类型是否正确

4、组合内置和自定义状态

实际项目中,经常需要同时使用消息历史和自定义字段:

import { Annotation, MessagesAnnotation } from '@langchain/langgraph';

const CustomAgentState = Annotation.Root({
  // 继承 MessagesAnnotation 的消息管理能力
  ...MessagesAnnotation.spec,
  
  // 添加自定义字段
  userId: Annotation<string>(),
  sessionId: Annotation<string>(),
  metadata: Annotation<Record<string, any>>({
    reducer: (curr, update) => ({ ...curr, ...update }),
    default: () => ({}),
  }),
});

通过MessagesAnnotation.spec继承内置的消息状态, 这样既能享受消息自动追加,又能添加自定义字段,
metadata使用合并对象 Reducer,适合存储灵活的 KV 数据。


四、构建多节点工作流

步骤 1:设计工作流

我们以构建一个文章写作助手为例: 接受话题 → 生成大纲 → 根据大纲写作 → 输出结果 。

__start__

📝 生成大纲节点

✍️ 撰写文章节点

📊 统计字数节点

__end__

步骤 2:定义状态

import * as dotenv from 'dotenv';
dotenv.config();

import { Annotation, StateGraph } from '@langchain/langgraph';
import { ChatOpenAI } from '@langchain/openai';
import { HumanMessage } from '@langchain/core/messages';

// 定义state
const WriterState = Annotation.Root({
  topic: Annotation<string>(),           // 写作话题
  outline: Annotation<string>(),         // 文章大纲
  article: Annotation<string>(),         // 最终文章
  wordCount: Annotation<number>(),       // 字数统计
});

// 提取state类型定义
type WriterStateType = typeof WriterState.State;

// 创建模型
const model = new ChatOpenAI({ 
  model: 'gpt-4o-mini', 
  temperature: 0.8 
});

步骤 3:定义节点函数

// 节点1:生成大纲
async function generateOutline(state: WriterStateType) {
  const response = await model.invoke([
    new HumanMessage(
      `请为以下话题生成一篇文章的大纲(3-5个要点):\n话题:${state.topic}`
    ),
  ]);
  return { outline: response.content as string };
}

代码流程解读:
先读取 state.topic 获取写作主题,调用 LLM 生成大纲,最后返回 { outline: ... },只更新 outline 字段,其他字段(topic, article, wordCount)保持不变。

// 节点2:撰写文章
async function writeArticle(state: WriterStateType) {
  const response = await model.invoke([
    new HumanMessage(
      `请根据以下大纲,撰写一篇完整的文章:\n${state.outline}`
    ),
  ]);
  const article = response.content as string;
  return {
    article,
    wordCount: article.length,
  };
}

有了之前的节点生成的大纲(state.outline ),就可以再次调用 LLM 根据大纲撰写完整文章,同时返回 article 和 wordCount 两个字段的更新,LangGraph 会自动将这两个字段合并到 State 中。

// 节点3:统计字数(演示多节点协作)
async function calculateStats(state: WriterStateType) {
  const words = state.article.split(/\s+/).length;
  const chars = state.article.length;
  
  console.log(`📊 统计完成: ${words} 词, ${chars} 字符`);
  
  // 这里可以添加更多统计逻辑
  return {};  // 不更新任何字段,仅做日志记录
}

最终返回空对象 {},表示不更新 State, 这种节点适合做日志记录、监控埋点等副作用操作。虽然返回空对象,但节点仍会被执行。

步骤 4:组装图并运行

const writerGraph = new StateGraph(WriterState)
  .addNode('generateOutline', generateOutline)
  .addNode('writeArticle', writeArticle)
  .addNode('calculateStats', calculateStats)
  .addEdge('__start__', 'generateOutline')
  .addEdge('generateOutline', 'writeArticle')
  .addEdge('writeArticle', 'calculateStats')
  .addEdge('calculateStats', '__end__')
  .compile();

代码解读:

  • addNode + addEdge 链式调用:声明式地描述图的结构
  • 每个节点必须先注册(addNode),才能被边引用
  • __start__ 和 __end__ 是 LangGraph 内置的特殊节点
  • compile():将图定义编译成可执行的 Runnable 对象,这一步非常关键,未编译的图无法执行

主运行函数:

async function main() {
  const result = await writerGraph.invoke({ 
    topic: 'TypeScript 5.0 新特性' 
  });
  
  console.log('📋 大纲:\n', result.outline);
  console.log('\n📄 文章:\n', result.article);
  console.log(`\n📊 字数:${result.wordCount} 字`);
}

main().catch(console.error);

代码解读:

  • invoke({ topic: '...' }):提供初始状态,启动图执行
  • 只提供 topic 字段,其他字段会使用 default 值或 undefined
  • 执行顺序:start → generateOutline → writeArticle → calculateStats → end
  • result 包含执行完成后的完整最终 State
  • .catch(console.error):捕获并打印异步错误

期望输出:

📊 统计完成: 856 词, 4523 字符

📋 大纲:
 1. TypeScript 5.0 概述
 2. 装饰器改进
 3. 枚举增强
 4. 性能优化
 5. 总结与展望

📄 文章:
 TypeScript 5.0 带来了许多令人兴奋的新特性...

📊 字数:4523 字

五、条件边:动态路由

1、概念

条件边允许根据当前 State 动态决定下一步走哪个节点:

需要搜索

直接回答

分析节点

路由函数

搜索节点

回答节点

__end__

2、实现条件边

const RouterState = Annotation.Root({
  question: Annotation<string>(),
  needsSearch: Annotation<boolean>(),
  answer: Annotation<string>(),
});

type RouterStateType = typeof RouterState.State;

// 路由函数:返回下一个节点的名称(字符串)
function routerFunction(state: RouterStateType): string {
  if (state.needsSearch) {
    return 'searchNode';
  }
  return 'answerNode';
}

关键点:

  • 路由函数接收 State,返回"字符串"(下一节点名称)
  • 也可以返回字符串数组,实现同时触发多个节点(并行执行)
  • 路由函数是纯函数,不做实际处理,只做"导航"
  • 返回值必须与已注册的节点名完全一致,否则报错
const routerGraph = new StateGraph(RouterState)
  .addNode('analyzeNode', analyzeNode)
  .addNode('searchNode', searchNode)
  .addNode('answerNode', answerNode)
  .addEdge('__start__', 'analyzeNode')
  // 条件边:analyzeNode 执行后,调用 routerFunction 决定下一步
  .addConditionalEdges('analyzeNode', routerFunction, {
    searchNode: 'searchNode',
    answerNode: 'answerNode',
  })
  .addEdge('searchNode', 'answerNode')
  .addEdge('answerNode', '__end__')
  .compile();

代码解读:

  • addConditionalEdges参数:(源节点, 路由函数, 映射表)
  • 映射表将路由函数返回值映射到实际节点名(可省略,名称相同时)
  • searchNode → answerNode:搜索完后还是要回答
  • 如果路由函数返回的节点名不在映射表中,会抛出错误

3、高级用法:并行执行

路由函数可以返回字符串数组,触发多个节点并行执行,适合需要聚合多个数据源的场景:

function parallelRouter(state: RouterStateType): string[] {
  // 同时触发搜索和缓存查询
  return ['searchNode', 'cacheNode'];
}

const parallelGraph = new StateGraph(RouterState)
  .addNode('analyzeNode', analyzeNode)
  .addNode('searchNode', searchNode)
  .addNode('cacheNode', cacheNode)
  .addNode('mergeNode', mergeNode)
  .addEdge('__start__', 'analyzeNode')
  .addConditionalEdges('analyzeNode', parallelRouter)
  .addEdge('searchNode', 'mergeNode')
  .addEdge('cacheNode', 'mergeNode')
  .addEdge('mergeNode', '__end__')
  .compile();

六、最佳实践和踩坑指南

💡 实践 1:Reducer 的选择

❌ 错误:对消息使用默认覆盖 Reducer

// 错误:每次节点返回消息都会覆盖历史!
const BadState = Annotation.Root({
  messages: Annotation<BaseMessage[]>(), // 默认 reducer = 覆盖
});

✅ 正确:使用 messagesStateReducer 或 MessagesAnnotation

import { messagesStateReducer } from '@langchain/langgraph';

const GoodState = Annotation.Root({
  messages: Annotation<BaseMessage[]>({
    reducer: messagesStateReducer,  // 追加语义
    default: () => [],
  }),
});

原因:对话历史应当累积,而不是被每次新消息覆盖。

💡 实践 2:节点函数的纯度

❌ 不好的做法:节点依赖外部变量

let globalCounter = 0;

async function badNode(state: MyState) {
  globalCounter++;  // 副作用!难以测试和调试
  return { count: globalCounter };
}

✅ 推荐做法:节点是纯函数

async function goodNode(state: MyState) {
  // 只依赖 state,不修改外部变量
  return { count: state.count + 1 };
}

原因:纯函数易于测试、调试和并行执行。

💡 实践 3:状态的粒度控制

❌ 不好的做法:State 过于庞大

const BloatedState = Annotation.Root({
  rawHtmlContent: Annotation<string>(),     // 可能几百KB!
  fullDocumentText: Annotation<string>(),   // 大量文本
  embeddings: Annotation<number[][]>(),     // 向量数据
  // ...更多大字段
});

✅ 推荐做法:只存关键摘要

const LeanState = Annotation.Root({
  contentSummary: Annotation<string>(),     // 摘要
  documentRef: Annotation<string>(),        // 存 URL 或 ID 引用
  embeddingRef: Annotation<string>(),       // 向量存储的引用
});

原因:State 在检查点时会被序列化存储,过大的 State 会造成性能问题。

⚠️ 常见问题

问题现象解决方案
节点返回完整 State 而不是部分更新某些字段被意外重置为初始值节点只返回需要变化的字段
忘记 compile()graph.invoke is not a function所有 .addNode/.addEdge 调用后必须 .compile()
路由函数返回了不存在的节点名运行时报找不到节点路由函数的返回值必须与已注册的节点名完全一致
State 字段初始值未定义节点访问字段时报 undefined为每个自定义 Annotation 设置 default 工厂函数
直接修改 state 对象状态更新不生效或产生副作用永远返回新对象,不直接修改 state.xxx = value
Reducer 函数不纯随机行为、难以复现的 BugReducer 必须是纯函数,不能有副作用或随机性

📝 本章小结

核心知识点回顾

知识点关键要点应用场景
State全图共享的数据容器,通过 Annotation 定义所有图都需要
Node(state) => Partial<state> 的纯函数业务逻辑处理单元
普通边addEdge(A, B) 固定路径顺序执行的步骤
条件边addConditionalEdges 动态路由分支逻辑
Reducer控制 State 字段的合并方式消息追加、计数累加等
compile()将图定义编译为可执行对象所有图必须调用

🎯 动手练习

练习 1:设计三节点工作流

  • 目标:构建"问题分析→方案生成→结果优化"三节点图
  • 要求:
    1. 每个节点读取前节点的输出,逐步完善结果
    2. 使用自定义 State 追踪每个阶段的输出
    3. 添加字数统计功能
  • 验收标准:最终输出包含经过三轮优化的完整方案,且能查看每轮的中间结果

练习 2:实现动态分支

  • 目标:根据用户输入的语言(中文/英文),路由到不同的回复节点
  • 要求:
    1. 使用 addConditionalEdges 实现
    2. 创建语言检测函数(可用正则或简单关键词匹配)
    3. 中文节点和英文节点使用不同的 System Prompt
  • 验收标准:中文输入触发中文节点,英文触发英文节点,混合语言能正确识别主要语言

练习 3:自定义 Reducer

  • 目标:创建一个"只保留最新5条消息"的自定义 Reducer
  • 要求:
    1. 实现 reducer: (current, update) => [...current, ...update].slice(-5)
    2. 测试超过5条消息时的行为
    3. 验证旧消息是否被正确丢弃
  • 验收标准:超过5条消息时,旧消息自动被丢弃,State 中始终只有最近5条

练习 4:并行节点实验

  • 目标:实现一个并行搜索 Agent,同时查询多个数据源
  • 要求:
    1. 路由函数返回多个节点名称,触发并行执行
    2. 创建3个搜索节点(模拟不同数据源)
    3. 添加合并节点,汇总所有搜索结果
  • 验收标准:3个搜索节点并发执行,总耗时接近最慢的那个节点,而非三者之和

📚 延伸阅读


下一章:第4章 —— 状态管理深入:如何设计 State

Silvaco TCAD仿真例库——肖特基二极管正向特性(例子) 此示例演示了肖特基二极管正向特性的仿真。 展示了: 使用 Atlas 语法形成二极管结构 设置阳极的肖特基势垒高度 正向偏置阳极 代码 第一部分:描述设备 mesh(网格) electrodes locations(电极位置) doping distribution(掺杂分布) 这是位于结构左侧和右侧的,2维n型器件,具有重掺杂浮动 p 型保护环区域, (2D n-type device with heavily doped floating p-type guard ring regio. 阅读详情

相关推荐

STM32使用 jansson 处理 Json格式字符

STM32 Json 字符的创建和解析1、Json简介2、jansson库的下载安装和报错解决2.1、下载安装2.2、STM32工程文件中导入jansson库2.3、报错解决2.4、修改堆栈空间3、Json 字符的创建4、Json 字符的解析4.1 纯键值对4.2、键的值是一个对象4.3、键的值是一个数组   STM32处理json字符串一般不常见,大部分都是不需要处理的数据,但是在一些通信中需要处理上传或者下传的数据,就别比如在物联网中,有一部分数据就是以json格式传输的,那么就需要对数据经行解析。我简

青烨慕容 7418

【langgraph基础入门】

比如在执行过程中,如果需要检索信息,则可以利用搜索工具来实现,如。

qq_58158950的博客 1769

保姆级教程:用Kalibr搞定Intel D435i三目(RGB+双目)相机联合标定,附完整ROSbag录制避坑指南

本文详细介绍了如何使用Kalibr工具对Intel D435i三目相机(RGB+双目)进行高精度联合标定,包括硬件准备、ROSbag录制技巧、Kalibr标定实战及结果验证。特别针对实际工程中的常见问题提供了解决方案,帮助开发者提升SLAM和三维重建等应用的精度。

weixin_42524762的博客 405

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

本文主要说明LangGraph的子图代码实现以及原理简介,涉及到子图通信、人机交互、历史回溯、子图更改state、更改节点、更改子图等内容,本文也是作为多智能体的铺垫。多智能体结束后,本系列文章也就结束了。

forevercui的博客 3654

Potplayer + LAVFilters + madVR 配置教程

文章目录Potplayer + LAVFilters + madVR 配置教程工具安装篇设置调教1.potplayer播放器设置加载LAVFilters和madVR1.选择“源滤镜/分离器”选项,选择“滤镜/解码器管理”2.“添加外部滤镜”3.浏览到刚才LAVFilters解压的文件夹,分别添加图示项。4.添加后回到管理界面设置,点击左边的”LAV AudioDecoder”,将右边”音频解码器”...

re 16万+

飞书多维表格省钱攻略:1个专业版账号,全员合规用、权限全掌控

像运动馆、 托管班、作业辅导、少儿美术、书法、口才班等等。对于大多数中小团队而言,飞书多维表格的核心需求是“协作高效、数据可控、成本可控”,而“1个专业版账号+多联系人”的模式,恰好完美契合这三点——既不用为不必要的席位付费,又能解锁全部专业功能,还能通过精细化权限管控保障数据安全。尤其是餐饮店、乒乓球训练馆这类个体经营或小型团队,人员分工清晰、权限需求明确,采用这种模式能最大化节省成本,同时提升管理效率。无需复杂的配置,无需额外的技术支持,5分钟就能搭建起全员协作的省钱体系。

涛涛讲AI 2217

3. 使用LangGraph创建和编辑图状态

接下来,我们将创建一个简单的图状态,它包含三个步骤。每个步骤都是一个函数,打印出当前步骤的名称。接下来,我们将设置一个工具,并使用LangChain Core的模型。我们可以在运行过程中编辑图状态。首先,我们需要导入一些必要的库和定义一个状态类型。构建器来添加这些步骤作为节点,并定义它们之间的边。这样,我们就完成了图状态的创建、运行和编辑。现在,我们可以运行图状态并查看输出。继续运行图状态并查看更新后的输出。设置内存检查点,并编译图状态。然后,更新状态并再次打印。运行图状态并查看输出。

The cure for boredom is curiosity. This is the log of its adventures. 1995

用ESP32-S3+OV2640摄像头+ILI9488屏,DIY一个能联网的智能猫眼(附完整代码)

本文详细介绍了如何利用ESP32-S3微控制器搭配OV2640摄像头和ILI9488显示屏,DIY一个功能强大的智能猫眼系统。从硬件选型、电路设计到软件开发,提供了完整的解决方案和优化技巧,包括图像采集显示、WiFi远程访问及低功耗设计,适合智能家居爱好者动手实践。

weixin_30897233的博客 501

33、LangGraph开发框架(二)-- LangGraph底层原理介绍

前面介绍了LangGraph基本概念,也使用create_react_agent做了简单的实验,如果说create_react_agent是一些图模板,那底层API就指的是允许用户手动去创建这些图的API。采用底层API构建智能体的话要求开发者掌握更加复杂的构建图的语法,但借助底层API,能够更加灵活的完成各类智能体的开发,而且在某些场景下,如实现人在闭环(Human in the loop)或者搭建多智能体(Multi Agent)系统时,必须要使用更加底层的图结构API才能够完成。

Andy_shenzl的博客 2802

【系列06】端侧AI:构建与部署高效的本地化AI模型 第5章:模型剪枝(Pruning)

结构化剪枝移除的是模型中的整个结构,比如一个完整的神经元、一个卷积核或一个通道。修剪后的模型权重矩阵仍然是稠密的,因此能够充分利用现代硬件和软件的并行计算优势,从而显著提升推理速度。非结构化剪枝是最细粒度的剪枝方法。对于需要极致压缩但对推理速度要求不高的场景,非结构化剪枝是好的选择。它就像修剪一棵树,通过移除模型中不必要的“枝叶”,让模型变得更精简、更高效,从而适应资源受限的设备。,开发者可以方便地对模型的不同层进行剪枝,并根据需求进行微调,从而在不影响太多性能的前提下,获得一个更轻量、更高效的模型。

学习,输出==》再学习再输出 649

MATLAB GUI 水果成熟度分级系统设计与实现

本文基于 MATLAB GUI 设计并实现了一款水果成熟度分级系统,能够准确地评估水果的成熟程度。在实现过程中,我们运用了 MATLAB 中的函数实现对图像的处理和分析,同时使用 GUI 界面增加了系统的易用性。值得一提的是,在实际操作中,我们应该结合实际需求对系统进行相应的改进与完善,以满足不同领域和应用场景下的需求。实验结果表明,本系统可以有效地检测出水果的成熟度,并对其进行精准的评分。因此,本文设计并实现了一款基于 MATLAB GUI 的水果成熟度分级系统。三、MATLAB 代码实现。

uote_e的博客 708

LangGraph核心概念拆解——图、节点、边与状态

从技术角度看,LangGraph中的图是“有向图”(Directed Graph),意味着边是有方向的(只能从A节点流向B节点,不能反向,除非额外定义反向边)。定义流程的“结构”:包含哪些节点、节点之间的连接关系;控制流程的“执行”:从起始节点开始,按边的方向依次执行节点,直到到达结束节点。输入:从“状态”中读取数据(比如前面例子中,clean_node从状态读user_text输出:处理后的数据写回“状态”(比如clean_node将写回状态)。

sinat_20277079的博客 1009

实战 | OpenCV实现扫描文本矫正应用与实现详解(附源码)

导读 本文主要介绍使用OpenCV对扫描文本矫正的应用实例及详细实现步骤。 背景介绍 在使用打印机或扫描仪扫描文档时,由于摆放位置差异难免造成扫描文档的倾斜。本文将使用OpenCV将倾斜的文档矫正水平并去除黑边。 实现步骤 本文只针对包含大部分文字的文档做倾斜矫正,思路来源是大部分文字倾斜后同一行的也在同一条直线,通过拟合直线计算文本倾斜角度,然后旋转来实现文本倾斜矫正。 详细步骤: ①加载倾斜图像 ②灰度转换+腐蚀+膨胀 ③Canny边缘检测 + 霍夫线变换检测直线 ...

Color Space的博客 3400

LangGraph1.0速通指南(一)—— LangGraph1.0 核心概念、点、边

LangGraph是开发复杂可靠AI应用的强大底层框架,本期内容分享了其核心概念,通过节点与边编排工作流,由状态统一管理数据,并依靠Reducer机制处理并发更新,并通过构建图代码实战掌握其基本使用。

weixin_42782643的博客 1068

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

深入浅出 LangGraph —— 第5章:条件边与动态路由

深入掌握LangGraph的条件边与动态路由机制,包括基于State的路由函数、多目标并行分发、Send API实现动态并行、以及结合LLM输出的智能路由设计,让Agent能够根据运行时状态灵活决策执行路径。包含完整的实战案例和最佳实践指南。

FrontAI的博客 742

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

深入浅出LangGraph AI Agent智能体开发教程(六)—LangGraph 底层API入门

本期内容分享了LangGraph底层自定义图API点、边、状态State的设计理念,并通过简单加减法串联结构图演示了底层API的使用方法,同时介绍了如何使用Pydantic约束State使代码更健壮。

weixin_42782643的博客 884

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

LangGraph 1.0入门:从节点与边到智能体工作流构建完全指南

摘要:本文系统介绍了LangGraph 1.0的核心架构,重点解析了状态管理、节点设计、边类型(普通边与条件边)以及Reducer处理并行冲突的机制。通过编程语言类比阐述了LangGraph作为智能体开发框架的核心理念,并提供了构建简单图、实现并行执行和条件分支的代码示例,为开发复杂智能体工作流奠定了技术基础。

ytt0523_com的博客 1156

LangGraph 1.0核心概念详解:从零开始构建智能体工作流

本文介绍了LangGraph 1.0框架的核心概念,包括状态(State)、节点(Node)和边(Edge)三大组件。状态作为数据载体在节点间传递更新,节点通过函数对状态进行操作,边则控制执行流程。文章详细讲解了普通边和条件边的应用,并针对并行执行时的状态冲突问题,介绍了Reducer机制来解决更新合并问题。通过代码示例展示了如何构建简单工作流,为开发者提供了构建复杂AI智能体系统的基础知识。

2401_85375151的博客 850

Langgraph框架深度解析:节点与边的运作机制与实战技巧,程序员必备收藏指南

本文深入解析了Langgraph框架的核心组件——节点(Nodes)和边(Edges)。节点负责执行具体业务逻辑,可以是模型调用或工具调用;边则控制节点间的数据流转和任务流程。详细介绍了START和END特殊节点、节点缓存机制、条件边以及入口点等概念。要真正掌握Langgraph并应用于复杂业务场景,必须深入理解其设计哲学和运作机制,而不仅仅是学习简单的官方案例。

Gaga246的博客 1040

深入浅出 LangGraph —— 导读

介绍《深入浅出LangGraph》的写作背景、与《深入浅出LangChain》的关系、目标读者、内容结构与阅读建议。帮助已掌握LangChain基础的工程师顺利进阶到生产级Agent系统开发。

FrontAI的博客 645

LangGraph1.0速通指南(一)从状态、节点到边的智能体工作流构建指南

在之前的系列中,笔者已经系统梳理了LangChain 1.0 的核心知识点,并通过一个多模态 RAG 项目带领大家实践了 LangChain 1.0 的关键技术。从本篇开始,笔者将为大家进一步分享的相关知识。与 LangChain 1.0 相比,LangGraph 1.0 的整体架构变动不大,但其定位发生了重要转变:在 1.0 版本之后,LangGraph 不再是 LangChain 的能力延伸,而是成为 LangChain 的能力底座。

HUANGXIN9898的博客 473

深入浅出 LangGraph —— 第4章:状态管理深入:如何设计State

深入探讨LangGraph状态设计的核心原则与进阶技巧,包括Reducer的高级用法、私有状态与输入输出状态分离、状态持久化策略、复杂嵌套状态设计,以及如何根据业务场景选择合适的状态结构,构建可维护的Agent应用。本章包含完整的实战案例和最佳实践指南。

FrontAI的博客 822

深入浅出 LangGraph —— 第1章:初识LangGraph

本章从LangChain的Agent概念出发,快速回顾核心要点,重点讲解为什么需要LangGraph来编排复杂Agent工作流,介绍LangGraph的定位与核心优势,带你理解图执行模型的设计哲学,并完成第一个可运行的LangGraph程序。包含完整的生态系统对比和实战示例。

FrontAI的博客 825

深入浅出LangGraph图结构:大模型智能体工作流设计与实现(附完整代码)

深入浅出LangGraph图结构:大模型智能体工作流设计与实现(附完整代码)

m0_48891301的博客 1416

深入浅出 LangGraph

专为正在做或想要转入 AI Agent 开发领域的开发者量身打造的技术系列教程。全教程以 LangGraph TypeScript 最新版为核心,带你从零开始,由浅入深,最终具备独立构建生产级 AI Agent 系统的能力。

FrontAI的博客 490

深入浅出LangGraph AI Agent智能体开发教程(七)—构建条件分支图和循环图

本期内容分享了利用LangGraph底层API构建条件分支图和循环图的基本技巧,学会本期内容大家将掌握了利用LangGraph构造复杂图的能力。

weixin_42782643的博客 925
上一篇: 深入浅出 LangGraph —— 第2章:环境搭建与第一个Agent
下一篇: 深入浅出 LangGraph —— 第4章:状态管理深入:如何设计State
FrontAI
博客等级 码龄1年 61粉丝 61原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值