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

LangGraph 节点返回State , 数据自动拼接原理 定义状态合并函数# 定义状态类型messages: Annotated[List[BaseMessage], add_messages] # 使用注解指定合并策略# 节点函数定义"""分类用户请求的类型"""# 提示模板用于分类任务("system", "你是一个任务分类器。根据用户的请求,确定它是哪种类型的任务。\n输出格式必须是JSON,包含字段'task_type',值为'search'(搜索类)、'calculation'(计算类)或'general'(一般问答)。"), 阅读详情

📖 本章学习目标

  • ✅ 掌握 Reducer 的高级用法与自定义 Reducer 编写
  • ✅ 理解私有状态、输入状态与输出状态的分离设计
  • ✅ 学会设计复杂嵌套状态结构
  • ✅ 掌握状态的运行时更新与节点通信模式
  • ✅ 能够根据业务场景做出合适的状态设计决策
  • ✅ 避免常见的状态管理陷阱和性能问题

一、State 设计的重要性

1、State 是 Agent 的"大脑"

如果说节点是 Agent 的"手脚",那 State 就是 Agent 的"大脑"——它记录了 Agent 在任务执行过程中的一切信息。State 设计得好,Agent 就聪明;State 设计得差,Agent 就混乱。

糟糕的状态设计会带来:

  • ❌ 节点之间数据传递混乱,难以追踪
  • ❌ 状态膨胀,携带大量无用信息
  • ❌ 难以测试和调试
  • ❌ 扩展新功能时需要大量重构
  • ❌ 序列化/反序列化性能问题

好的State设计

精简字段

清晰语义

合适Reducer

高性能✅

差的State设计

冗余字段

命名混乱

默认覆盖

性能瓶颈❌

State就像旅行箱——带太多会超重(性能问题),带太少不够用(功能缺失),关键是精选必需品。

2、State 设计的核心原则

原则说明重要性
最小化只存必要的信息⭐⭐⭐⭐⭐
不可变性节点返回新数据,不直接修改 State⭐⭐⭐⭐⭐
语义清晰字段名表达明确的业务含义⭐⭐⭐⭐
Reducer 一致每个字段有明确的合并策略⭐⭐⭐⭐⭐
类型安全使用 TypeScript 严格类型⭐⭐⭐⭐

二、Reducer 深度解析

1、Reducer 的本质

Reducer 是一个函数,决定"当节点返回新值时,State 字段如何更新":

Reducer 签名:(currentValue: T, updateValue: T) => T

Reducer 的执行时机:

节点返回
{field: newValue}

LangGraph
查找字段的Reducer

执行 Reducer
(current, newValue)

更新 State
中的字段

传递给下一个节点

LangGraph 内置了几种常见 Reducer:

import { 
  messagesStateReducer,  // 消息追加,支持消息更新/删除
} from '@langchain/langgraph';

2、常用 Reducer 模式

模式1:覆盖(默认)
import { Annotation } from '@langchain/langgraph';

const CoverState = Annotation.Root({
  // 模式1:覆盖(默认)—— 新值直接替换旧值
  status: Annotation<string>(),
  currentPhase: Annotation<string>(),
});

这是默认的 Reducer 行为:(curr, update) => update,适用于状态标记(status/phase)、当前值等单一字段,比如status从"processing"变为"completed",旧值被完全替换(注意:如果未设置default值,首次访问可能为undefined)。

模式2:追加
const AppendState = Annotation.Root({
  // 模式2:追加 —— 新数组追加到旧数组
  logs: Annotation<string[]>({
    reducer: (curr, update) => [...curr, ...update],
    default: () => [],
  }),
  
  searchResults: Annotation<string[]>({
    reducer: (curr, update) => [...curr, ...update],
    default: () => [],
  }),
});

追加模式:(curr, update) => [...curr, ...update],适用于日志、错误列表、搜索结果等累积型数据。每次节点返回新数组,都会拼接到现有数组后面。 必须设置default: () => [],否则首次访问会报错。

模式3:累加
const AccumulateState = Annotation.Root({
  // 模式3:累加 —— 数值累加
  totalTokens: Annotation<number>({
    reducer: (curr, update) => curr + update,
    default: () => 0,
  }),
  
  retryCount: Annotation<number>({
    reducer: (curr, update) => curr + update,
    default: () => 0,
  }),
});

累加模式:(curr, update) => curr + update,适用于计数器、Token 消耗统计、分数等数值字段。节点返回增量值(如1),Reducer自动累加到总数必须设置default,提供初始值。

模式4:合并对象
const MergeState = Annotation.Root({
  // 模式4:合并对象 —— 新对象字段合并到旧对象
  metadata: Annotation<Record<string, unknown>>({
    reducer: (curr, update) => ({ ...curr, ...update }),
    default: () => ({}),
  }),
  
  entities: Annotation<Record<string, string>>({
    reducer: (curr, update) => ({ ...curr, ...update }),
    default: () => ({}),
  }),
});

合并模式:(curr, update) => ({ ...curr, ...update }),适用于灵活的元数据、配置项等 KV 结构,新对象的字段会覆盖同名字段,其他字段保留,适合在多轮对话中累积提取的实体信息。

完整示例对比:

// 四种模式的综合示例
const ReducerExamplesState = Annotation.Root({
  status: Annotation<string>(),  // 覆盖
  
  logs: Annotation<string[]>({   // 追加
    reducer: (curr, update) => [...curr, ...update],
    default: () => [],
  }),
  
  totalTokens: Annotation<number>({  // 累加
    reducer: (curr, update) => curr + update,
    default: () => 0,
  }),
  
  metadata: Annotation<Record<string, unknown>>({  // 合并
    reducer: (curr, update) => ({ ...curr, ...update }),
    default: () => ({}),
  }),
});

3、高级 Reducer:保留最新 N 条

// 只保留最近 N 条记录的 Reducer 工厂函数
function keepLatestN<T>(n: number) {
  return (curr: T[], update: T[]): T[] => {
    return [...curr, ...update].slice(-n);
  };
}

const SlidingWindowState = Annotation.Root({
  // 只保留最近 10 条消息(防止 Token 超限)
  recentLogs: Annotation<string[]>({
    reducer: keepLatestN(10),
    default: () => [],
  }),
  
  // 只保留最近 5 次搜索结果
  recentSearches: Annotation<string[]>({
    reducer: keepLatestN(5),
    default: () => [],
  }),
});
  • keepLatestN 是一个"Reducer 工厂函数"——返回一个 Reducer
  • slice(-n) 取数组最后 n 个元素,实现滑动窗口效果
  • 这是生产环境中控制上下文长度的常用技巧
  • 适用场景:聊天记录、搜索历史、操作日志等需要限制大小的列表

4、消息 Reducer 的特殊能力

messagesStateReducer 除了追加,还支持更新和删除已有消息:

import { messagesStateReducer } from '@langchain/langgraph';
import { RemoveMessage, AIMessage } from '@langchain/core/messages';

// 删除某条消息:传入带有相同 id 的 RemoveMessage
const state = {
  messages: [
    new HumanMessage({ id: 'msg-1', content: '你好' }),
    new AIMessage({ id: 'msg-2', content: '你好!' }),
  ]
};

// 删除 msg-1
const update = [new RemoveMessage({ id: 'msg-1' })];
const newMessages = messagesStateReducer(state.messages, update);
// 结果:只剩 msg-2

// 更新 msg-2 的内容
const update = [
  new AIMessage({ 
    id: 'msg-2', 
    content: '你好!很高兴见到你!'  // 新内容
  })
];

const updatedMessages = messagesStateReducer(state.messages, update);

RemoveMessage是特殊消息类型,指示 Reducer 删除对应 id 的消息,这是实现消息修剪(Memory Pruning)的底层机制,第10章的记忆管理大量使用这个特性。

消息的操作主要有三种:

  1. 追加:传入普通 Message,自动添加到末尾
  2. 更新:传入相同id的Message,替换原消息
  3. 删除:传入RemoveMessage,删除对应id的消息

三、输入/输出状态分离

1、为什么要分离

默认情况下,graph.invoke() 的输入和输出都是完整的 State。但在生产中,你往往希望:

  • 输入:只接受用户提供的必要字段
  • 输出:只返回对外有意义的结果字段
  • 内部:节点之间共享更多的中间状态

图内部状态

完整 State
{question, searchResults,
reasoning, answer, ...}

用户输入
{question}

图输出
{answer}

好处:

  • ✅ 保护内部实现细节,API更简洁
  • ✅ 减少网络传输的数据量
  • ✅ 避免因内部字段变化导致API破坏
  • ✅ 符合最小权限原则

2、使用 InputState 和 OutputState

图内部使用的完整状态定义:

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

// 完整的内部状态(节点间共享)
const OverallState = Annotation.Root({
  question: Annotation<string>(),
  searchResults: Annotation<string[]>({
    reducer: (c, u) => [...c, ...u],
    default: () => [],
  }),
  reasoning: Annotation<string>(),
  answer: Annotation<string>(),
});

定义输入和输出状态:

// 输入状态:只需要用户提供 question
const InputState = Annotation.Root({
  question: Annotation<string>(),
});

// 输出状态:只对外暴露 answer
const OutputState = Annotation.Root({
  answer: Annotation<string>(),
});
/**
 * 代码解读:
 * - InputState:用户调用 graph.invoke() 时需要提供的字段
 * - OutputState:graph.invoke() 返回给调用方的字段
 * - 这样外部用户不需要知道searchResults、reasoning等内部字段
 */

构建图时指定输入输出类型:

// 构建图时指定输入输出类型
const graph = new StateGraph({
  stateSchema: OverallState,
  input: InputState,
  output: OutputState,
})
  .addNode('search', searchNode)
  .addNode('reason', reasonNode)
  .addNode('answer', answerNode)
  .addEdge('__start__', 'search')
  .addEdge('search', 'reason')
  .addEdge('reason', 'answer')
  .addEdge('answer', '__end__')
  .compile();

完整使用示例:

async function main() {
  // 只需提供 input 中定义的字段
  const result = await graph.invoke({ 
    question: 'TypeScript 相比 JavaScript 有什么优势?' 
  });
  
  // result 只包含 output 中定义的字段
  console.log(result.answer);  // ✅ 可以访问
  console.log(result.searchResults);  // ❌ TypeScript 编译错误
}

四、私有状态与节点通信

1、节点私有状态

有时,两个节点之间需要传递一些临时数据,但这些数据不应该污染全局 State。LangGraph 支持节点私有通信。

场景示例: 写作流程中的草稿评审

私有状态

需要修改

通过

__start__

写作节点
生成草稿

评审节点
检查质量

输出最终结果

__end__

draftContent
reviewComments

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

// 主状态:对外暴露的字段
const MainState = Annotation.Root({
  topic: Annotation<string>(),
  finalResult: Annotation<string>(),
});

// 内部私有状态(仅在特定子流程中使用)
const PrivateState = Annotation.Root({
  topic: Annotation<string>(),
  draftContent: Annotation<string>(),   // 私有中间字段
  reviewComments: Annotation<string>(), // 私有中间字段
  finalResult: Annotation<string>(),
});

MainState负责对外暴露的简洁接口,PrivateState负责内部工作流使用的详细状态。draftContent/reviewComments只在写作-评审循环中使用,完成后只将finalResult写入MainState。

2、使用 Command 进行动态路由

Command 是 LangGraph 的高级特性,允许节点同时更新状态和决定下一步:

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

async function reviewNode(state: typeof PrivateState.State) {
  const needsRevision = state.draftContent.length < 100;
  
  if (needsRevision) {
    // 返回 Command:更新状态 + 跳转到特定节点
    return new Command({
      update: { reviewComments: '内容太短,需要扩充' },
      goto: 'writeNode',  // 重新跳回写作节点
    });
  }
  
  return new Command({
    update: { finalResult: state.draftContent },
    goto: '__end__',
  });
}

Command 对象同时携带状态更新(update)和路由决策(goto),这比 addConditionalEdges 更灵活——路由逻辑可以在节点内根据运行时数据决定。使用goto: '__end__' 直接结束图的执行。

注意:使用 Command 的节点不能再与 addConditionalEdges 混用。

Command 的优势:

  1. 路由决策可以基于复杂的业务逻辑
  2. 可以同时更新多个字段
  3. 支持动态跳转,不受预定义边限制

Command vs addConditionalEdges 对比:

特性CommandaddConditionalEdges
路由灵活性⭐⭐⭐⭐⭐ 运行时动态决定⭐⭐⭐ 预定义映射
状态更新✅ 可同时更新❌ 需单独节点
复杂度中等简单
适用场景复杂业务逻辑简单条件分支

五、复杂状态设计案例

1、研究助手的状态设计

下面是一个完整的研究助手 Agent 状态设计案例,展示真实场景中的状态结构:

import { Annotation, messagesStateReducer } from '@langchain/langgraph';
import { BaseMessage } from '@langchain/core/messages';

// 搜索结果的数据结构
interface SearchResult {
  url: string;
  title: string;
  snippet: string;
  relevanceScore: number;
}

定义研究报告结构:

// 研究报告的数据结构
interface ResearchReport {
  summary: string;
  keyFindings: string[];
  sources: string[];
  generatedAt: string;
}

完整状态定义:

const ResearchAgentState = Annotation.Root({
  // 用户的原始问题(覆盖)
  userQuery: Annotation<string>(),

  // 分解后的子问题列表(去重追加)
  subQuestions: Annotation<string[]>({
    reducer: (c, u) => [...new Set([...c, ...u])], // 去重追加
    default: () => [],
  }),

  // 搜索结果(按相关度合并并截断)
  searchResults: Annotation<SearchResult[]>({
    reducer: (curr, update) =>
      [...curr, ...update]
        .sort((a, b) => b.relevanceScore - a.relevanceScore)
        .slice(0, 20), // 只保留最相关的20条
    default: () => [],
  }),

  // 对话历史(消息追加)
  messages: Annotation<BaseMessage[]>({
    reducer: messagesStateReducer,
    default: () => [],
  }),

  // 最终报告(覆盖)
  report: Annotation<ResearchReport | null>({
    default: () => null,
  }),

  // 执行阶段追踪(覆盖)
  currentPhase: Annotation<'planning' | 'searching' | 'analyzing' | 'writing'>(),

  // Token 消耗统计(累加)
  totalTokensUsed: Annotation<number>({
    reducer: (c, u) => c + u,
    default: () => 0,
  }),
});

代码解读:

  • userQuery:用户原始问题,后续节点可能需要引用
  • subQuestions:去重追加,避免重复搜索相同问题
  • searchResults:智能合并策略
    • 拼接新旧结果
    • 按relevanceScore降序排序
    • 截取前20条,控制状态大小
  • messages:使用内置messagesStateReducer,支持追加/更新/删除
  • report:最终输出的研究报告,可为null表示未完成
  • currentPhase:枚举类型,追踪执行阶段,便于监控和调试
  • totalTokensUsed:累加模式,成本控制的关键指标

状态流转示意:

State演化

invoke
{userQuery}

planning阶段
分解子问题

searching阶段
并行搜索

analyzing阶段
分析结果

writing阶段
生成报告

输出
{report}

{userQuery,
currentPhase:'planning'}

{...,subQuestions:[...],
currentPhase:'searching'}

{...,searchResults:[...],
currentPhase:'analyzing'}

{...,report:{...},
currentPhase:'writing'}


六、最佳实践和踩坑指南

💡 实践 1:避免在 State 中存储大型对象

❌ 不好的做法:

const BadState = Annotation.Root({
  // 把完整的网页 HTML 存入 State —— 可能几百 KB!
  rawHtmlContent: Annotation<string>(),
  fullDocumentText: Annotation<string>(),
  embeddings: Annotation<number[][]>(),  // 向量数据
});

✅ 推荐做法:

const GoodState = Annotation.Root({
  // 只存关键摘要,大型数据存外部存储
  contentSummary: Annotation<string>(),
  documentRef: Annotation<string>(), // 存 URL 或 ID 引用
  embeddingRef: Annotation<string>(), // 向量数据库的引用
});

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

  • 内存占用高
  • 序列化/反序列化慢
  • 数据库存储成本高
  • 网络传输开销大

💡 实践 2:用类型枚举代替字符串

❌ 不好的做法:

return { phase: 'step2' }; 

✅ 推荐做法:

type Phase = 'planning' | 'executing' | 'reviewing' | 'done';

const state: { phase: Phase } = { phase: 'planning' };

// 使用时 TypeScript 会检查
return { phase: 'executing' };  // ✅ 正确
return { phase: 'exeucting' };  // ❌ 编译错误:拼写错误

原因:TypeScript 联合类型提供编译时检查,避免拼写错误导致的运行时 Bug。

💡 实践 3:为所有字段设置 default 值

❌ 不好的做法:

const BadState = Annotation.Root({
  count: Annotation<number>(),  // 没有default,首次访问可能undefined
});

✅ 推荐做法:

const GoodState = Annotation.Root({
  count: Annotation<number>({
    default: () => 0,  // 明确的初始值
  }),
});

原因:未设置default的字段,首次访问时可能是undefined,导致运行时错误。

💡 实践 4:Reducer 必须是纯函数

❌ 不好的做法:

// 错误的Reducer:依赖外部变量
let counter = 0;
const badReducer = (curr: number, update: number) => {
  counter++;  // 副作用!
  return curr + update;
};

✅ 推荐做法:

// 正确的Reducer:纯函数
const goodReducer = (curr: number, update: number) => {
  return curr + update;  // 无副作用,只依赖输入
};

原因:Reducer 可能被多次调用,副作用会导致不可预测的行为。

⚠️ 常见问题

问题现象解决方案
直接修改 State 对象状态更新不生效或产生副作用永远返回新对象,不直接修改 state.xxx = value
Reducer 函数不纯随机行为、难以复现的 BugReducer 必须是纯函数,不能有副作用或随机性
忘记 default 工厂函数首次读取字段时报 TypeError所有自定义 Annotation 都应设置 default
State 字段命名与内置冲突框架行为异常避免使用 __start__、__end__ 等内置名称
状态过于庞大序列化慢、内存占用高只存关键字段,大数据存外部存储
Reducer 逻辑复杂难以调试和维护保持 Reducer 简单,复杂逻辑放节点中

📝 本章小结

核心知识点回顾

知识点关键要点应用场景
Reducer 模式覆盖/追加/累加/合并 四种基础模式根据字段语义选择合适的 Reducer
滑动窗口keepLatestN 工厂函数控制聊天记录、日志大小
消息管理messagesStateReducer 支持追加/更新/删除对话历史管理、记忆修剪
输入/输出分离InputState + OutputState + OverallState生产级 API 设计,保护内部状态
Command 对象同时携带状态更新和路由决策复杂动态路由场景
状态设计原则最小化、不可变、语义清晰、类型安全所有 LangGraph 项目

🎯 动手练习

练习 1:设计电商 Agent 的 State

  • 目标:为一个购物助手设计完整的 State
  • 要求:
    1. 包含用户偏好(preferences)、商品搜索结果(searchResults)
    2. 购物车(cartItems)、订单状态(orderStatus)
    3. 每个字段有合适的 Reducer
    4. 添加 TypeScript 类型定义
  • 验收标准:
    • 至少包含6个字段
    • 每种 Reducer 模式至少使用一次
    • 能通过 TypeScript 编译检查

练习 2:实现去重 Reducer

  • 目标:实现一个"追加但不重复"的 Reducer
  • 要求:
    1. 基于某个字段(如 id)判断是否重复
    2. 创建通用工厂函数 uniqueByIdReducer(idField: string)
    3. 测试多次追加相同 id 的数据
  • 验收标准:
    • State 中只保留一份相同 id 的数据
    • 后追加的数据覆盖先前的数据
    • 支持任意类型的数组

练习 3:使用 Command 实现重试机制

  • 目标:节点执行失败时,最多重试 3 次后才报错
  • 要求:
    1. 在 State 中记录重试次数 retryCount
    2. 节点用 Command 控制重试流程
    3. 超过3次后跳转到错误处理节点
  • 验收标准:
    • 失败时自动重试,最多3次
    • 第4次失败后跳转到errorHandler节点
    • 能正确记录每次重试的原因

练习 4:实现输入输出分离

  • 目标:为一个问答系统设计InputState和OutputState
  • 要求:
    1. OverallState包含至少5个内部字段
    2. InputState只暴露1-2个必要字段
    3. OutputState只返回最终答案
    4. 测试外部无法访问内部字段
  • 验收标准:
    • TypeScript 编译时阻止访问内部字段
    • invoke() 只需提供input字段
    • 返回值只包含output字段

📚 延伸阅读


下一章:第5章 —— 条件边与动态路由

LangGraph学习笔记 — LangGraph中State状态模式 本文深入解析了LangGraph框架中的状态管理机制,重点探讨了State和Reducer函数的核心作用。LangGraph通过节点(Node)和边(Edge)构建工作流,其中状态(State)作为关键载体在节点间传递信息。文章详细介绍了三种状态定义方式:字典类型、TypedDict类型和MessageGraph专用类型,并分析了Reducer函数如何控制状态更新逻辑。特别阐述了add_messages这一高级Reducer函数的实现原理,它能智能处理消息的追加和更新。通过多个代码示例展示了不同场景下的状态 阅读详情

相关推荐

基于LangGraph的多智能体协作系统实战:从环境搭建到状态管理

多智能体系统(Multi-Agent System)是一种由多个具备特定能力的AI智能体组成的协作架构,其核心原理在于通过定义清晰的通信协议与状态管理机制,实现任务的高效分解与协同执行。在工程实践中,这类系统能够显著提升复杂任务的自动化处理能力,尤其适用于数据分析、流程自动化等需要多步骤推理与执行的场景。以LangGraph框架为例,它通过图(Graph)结构来编排智能体工作流,并利用状态(State)管理实现节点间的数据传递与共享。其中,静态循环(Static Cycles)机制允许工作流在特定条件下重复

weixin_30889885的博客 377

【LangGraph】二.State 和 Node 的设计细节

本文详细介绍了LangGraph中State和Node的设计要点。State作为共享数据容器,需要明确定义字段及其更新策略(覆盖或追加)。Node应遵循单一职责原则,只返回必要的更新字段,保持幂等性。文章还提供了调试技巧和常见错误分析,强调清晰的命名和合理的拆分对于构建可维护应用的重要性。通过合理设计State和Node,可以创建更清晰、更可靠的LangGraph工作流。

hrh的博客 379

LangGraph构建可调试AI Agent:图编排、状态管理与生产落地

AI Agent并非简单调用大模型,而是具备目标导向、状态记忆与多步推理能力的自主服务单元。其核心挑战在于流程编排的可验证性、状态一致性与故障恢复能力。LangGraph以有向图(Directed Graph)为执行拓扑,通过显式节点定义、条件边路由与强类型State(基于Pydantic)实现工程级可控性,显著区别于线性链式框架(如RunnableSequence)或对话模拟框架(如AutoGen)。它天然支持checkpoint持久化、人工中断介入、Mermaid可视化调试及嵌套子图,是构建真实业务闭环

weixin_30654583的博客 639

最近,大模型岗位爆了。。。

重磅消息,国资委打响了国内AI第一枪!这意味着传统行业又迎来了一次大洗牌,现在国内头部人工智能公司已经开始用AI数字人助力各行各业,除此之外,知名大厂也都在布局AI市场。懂的程序员年薪已经翻到风口之下,与其焦虑被行业淘汰,不如先人一步掌握 AI 大模型技术。为帮助大家提升竞争力,为了帮助普通程序员享受时代红利,

qq_46094651的博客 1017

文件上传漏洞攻击与防范方法

文件上传漏洞攻击与防范方法 文件上传漏洞简介: 文件上传漏洞是web安全中经常用到的一种漏洞形式。是对数据与代码分离原则的一种攻击。上传漏洞顾名思义,就是攻击者上传了一个可执行文件如木马,病毒,恶意脚本,WebShell等到服务器执行,并最终获得网站控制权限的高危漏洞。 文件上传漏洞危害: 上传漏洞与SQL注入或 XSS相比 , 其风险更大 , 如果 Web应用程序存在上传漏洞 , 攻击者上传...

m0_38103658的博客 4万+

火星遥感数据的获取与处理工具安装详解

有关火星遥感影像数据的那些事...

FengYingLuo的博客 5574

LangGraph 4 - Platform - 部署、Cli、Studio、SDK

一个 LangGraph 应用程序由一个或多个图、一个配置文件 ()、一个指定依赖项的文件以及一个可选的用于指定环境变量的.env文件组成。本指南展示了应用程序的典型结构,并说明了如何指定使用 LangGraph 平台部署应用程序所需的信息。实现你的图结构!图可以在单个文件或多个文件中定义。请注意每个的变量名称,这些变量将被包含在LangGraph应用中。后续创建LangGraph配置文件时会用到这些变量名。示例agent.py文件展示了如何从其他自定义模块导入(此处未显示模块代码,请查看此代码库。

AI工程化、开源分享、文档翻译、代码笔记 4945

AI量化投资开源平台——Qlib(微矿)的学习使用笔记(随缘更新)

Qlib 涵盖了量化投资的全过程,为用户的 AI 算法提供了高性能的底层基础架构,从框架设计上让用户可以更容易地应用 AI 算法来辅助解决量化投资的各个关键问题(例如 Alpha 预测,风险预测,市场动态性建模)。本文旨在记录一些面向初学者的基础内容。

in_void的博客 3133

从“被优化”到“AI训练师”:35岁转行实操手册,把经验变成喂给AI的“黄金饲料”

2025年的职场,“35岁+”仿佛一道无形的分水岭。

m0_59163425的博客 4513

Python-OpenCV及cv2,numpy库最新安装教程[最全步骤]

安装教程目录前言OpenCV-Python安装教程报错解决cv2安装numpy安装opencv安装(附加)总结 前言 首先,我知道一些看到我的Blog的人已经在网上找了很多歪路子,现在已经火冒三丈了(我也是这样过来的hhhh),那么现在,深呼吸,跟着我的教程,不要着急,每一步都要读一遍。完整安装过程需要1个小时左右(仅供参考,本人第一次安装python花了一天(确信)) OpenCV-Python...

qq_45425286的博客 7431

保姆级教程:在LKD3588开发板上为RK3588添加SC2210摄像头驱动(含完整DTS配置)

本文提供了一份详细的教程,指导如何在LKD3588开发板上为RK3588处理器添加SC2210摄像头驱动,包括完整的DTS配置和内核编译步骤。教程涵盖了环境准备、驱动文件添加、DTS配置详解、内核编译与烧录、驱动测试以及常见问题排查,帮助开发者快速实现SC2210传感器在RK3588平台上的集成与优化。

weixin_42641741的博客 480

LangGraph.js 核心概念:State / Node / Edge 一文讲透

LangGraph.js 用Annotation来定义 State 的结构。你可以把它理解成给白板画格子——每个格子是什么类型、怎么更新,都要提前定义好。typescriptimportAnnotationimportconstMyStateAnnotationRoot({// 字段一:消息列表,用追加模式messages:Annotation[]>({default}),// 字段二:当前步骤,直接覆盖Annotation// 字段三:重试次数,取最大值。

LuckyWinty的博客 552

Cursor赋能Qt C++:从环境配置到项目构建的AI开发新范式

本文详细介绍了如何利用Cursor工具链提升Qt C++开发效率,从智能环境配置到CMake项目构建的全流程实践。通过AI辅助编程、Qt生态优化及高级调试技巧,开发者可快速完成从传统开发到AI驱动的新范式转换,显著缩短项目搭建时间并提升代码质量。

weixin_30329623的博客 546

深入 LangGraph State:Reducer 是如何让状态“自动合并”的

本文是 LangGraph 实战第二篇,详解 Reducer 状态合并:默认字段新值直接覆盖,借助Annotated+Reducer可实现数据累加;讲解 Channel 底层原理、源码与三类实战案例,罗列常见踩坑点并给出生产优化方案,区分覆盖 / 累加选型。

曾经“等你生日那天”都遥远得像未来,如今却可欢愉的挥手说“下个十年见” 3万+

河洛理数【陈抟】每月月卦推演每日运卦

Step2:每卦中的日爻遇到二十四节气中的当日为节(月初)或气(月中)的时候,所代表的日期需要变更。正常来说,屯卦分别代表初一到初六,但是由于当月初二时立秋节,所以初爻就不能作为初一、而是要作为立秋节开始时(文中还精算到了立秋是从初二的午时开始),如下。说的代表月运的基础卦上进行当月日卦的推演方式。老样子,我们还是按照书中举得例子卦在这边进行一步步的推演,最后做总结。Step1:从月卦爻下一爻开始,自下而上,进行五个爻的爻变,新推演的每个卦代表六天,如下。假设当月月卦是即济卦,月爻在二爻,如图所示(

Daniel专栏 764

史上最详细的sqlmap使用教程

sqlmapsqlmap是一个自动化的SQL注入工具,其主要功能是扫描,发现并利用给定的URL进行SQL注入。目前支持的数据库有MySql、Oracle、Access、PostageSQL、SQL Server、IBM DB2、SQLite、Firebird、Sybase和SAP MaxDB等Sqlmap采用了以下5种独特的SQL注入技术基于布尔类型的盲注,即可以根据返回页面判断条件真假的注入。

大河之犬的博客 5万+

收藏备用!LangGraph核心之State状态管理全解析,小白也能上手大模型开发

State是什么:在整个流程中共享的数据容器基本用法:节点读取State,处理后返回更新的部分TypedDict:让代码更严谨,避免运行时错误Reducer机制:控制State的更新方式(覆盖、追加等):智能管理消息列表的专用Reducer实战应用:构建带记忆的聊天机器人掌握了这些,你就能灵活构建各种LangGraph应用了。如今技术圈降薪裁员频频爆发,传统岗位大批缩水,相反AI相关技术岗疯狂扩招,薪资逆势上涨150%,大厂老板们甚至开出70-100W年薪,挖掘AI大模型人才!

AI大模型的博客 1838

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

LangGraph核心教程:从零掌握State状态管理,收藏这篇就够了!

本文系统介绍了LangGraph框架的核心状态管理机制,重点解析了State的基本概念、实现方式及实际应用。文章从基础字典实现开始,逐步深入讲解如何通过TypedDict增强代码健壮性,详细说明了Reducer状态更新原理,并演示了如何使用operator.add实现消息列表的累积功能。通过构建带记忆的聊天机器人等实战案例,帮助开发者理解节点间的数据传递方式,掌握LangGraph的核心开发模式。内容涵盖从环境配置到可视化调试的全流程,适合各层次开发者学习状态管理在AI应用开发中的关键作用。

qq_46094651的博客 1344

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

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

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

LangGraph-State 概念

“全局上下文状态对象”,是 StateGraph 用来在节点之间传递和合并数据的统一容器。用 TypedDict 或 dataclass 显式声明所有需要共享的字段。如果 TypedDict 没定义字段,后面更新时 IDE 可能无法提示。注:以下所提的“文档”,是指LangGraph官方指南(Agentic RAG、工作流自动化、上下文共享场景。如果你直接返回一个完整的 QAState 对象,会。,所以通常只返回要更新的那部分。),参考版本是0.6.8。

czhcc的专栏 710

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

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

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

FrontAI的博客 825

LangGraph多Agent系统实战:状态管理、循环路由与生产级容错

多Agent系统本质是具备状态记忆、动态决策和协同反馈的智能体网络,其核心挑战在于状态一致性、流程可溯性与异常韧性。LangGraph通过版本化快照State、条件边驱动的有环图结构、以及基于checkpointer的分布式协调机制,将传统线性编排升级为类神经系统的行为建模。它不仅解决RAG流水线中中间结果丢失、节点耦合过重等问题,更支撑金融合规、智能客服等高可靠场景下的实时协作与人工介入闭环。本文聚焦LangGraph在真实生产环境中的状态协议设计、PostgreSQL持久化选型、LLM动态路由及三层容错

mxdxm8899的专栏 865

LangGraph:从 Graph 到 State 理解 LangGraph 的工作原理

LangGraph 学习笔记摘要 LangGraph 是专为复杂智能体应用设计的低级编排框架,解决了 LangChain 线性流水线在循环、分支、状态管理等方面的局限性。核心思想是将工作流建模为图结构,支持并行执行、条件分支和状态持久化。 关键特点: 七步构建法:定义状态→编写节点→创建图→添加节点→添加边→编译→执行 通过共享状态实现节点通信,节点只处理特定任务 天然支持复杂场景:循环、分支、并行、断点恢复等 典型应用场景:需要多工具协作、循环决策、状态保持的复杂智能体系统。与 LangChain 形成互

2302_80137276的博客 282

Agent实战教程:Langgraph的StateGraph以及State怎么用

input: str"""第一个节点的处理逻辑"""return {"output": f"处理了:def node_1(state : GraphState) - > GraphState : """第一个节点的处理逻辑""" return {"input" : state [ "input" ] , "output" : f"处理了: {

yanqianglifei的专栏 1008

LangGraph-update_state方法

在文档里(如 “Use the graph API”),update_state 是 CompiledStateGraph 的方法之一。在中断或暂停的情形下,如果你希望在恢复之前先修改状态(例如人工干预、补充信息等),这就是 update_state 的主要用途。所以你在使用 update_state 时,要留意该字段是否有特殊 reducer(如 append、累加、合并等)影响。在 LangGraph 中,每一个状态字段(state key)可以有自己的。),参考版本是0.6.8。

czhcc的专栏 1113

从零开始学LangGraph:详解State的定义、更新与管理

本文介绍了LangGraph中State的定义、更新与管理方法。State可以使用TypedDict或Pydantic模型定义,前者轻量简单,后者提供强大的运行时验证功能。State更新分为两个阶段:节点函数处理业务逻辑并返回新值,Reducer决定更新方式(如追加、覆盖等)。文章详细讲解了内置Reducer的使用方法,并展示了如何自定义Reducer实现特定更新逻辑。此外,还介绍了Overwrite机制用于强制覆盖State值的场景。这些功能为构建健壮的AI Agent提供了灵活的状态管理方案。

xiaocheng121212的博客 1038

深入浅出 LangGraph

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

FrontAI的博客 490
上一篇: 深入浅出 LangGraph —— 第3章:图的核心概念:节点、边与状态
下一篇: 深入浅出 LangGraph —— 第5章:条件边与动态路由
FrontAI
博客等级 码龄1年 61粉丝 61原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值