首页 / 文章 / 实用指南:如何利用LangGraph构建更出色的AI智能体

实用指南:如何利用LangGraph构建更出色的AI智能体

《实用指南》操作流程详解:如何利用 LangGraph 构建更出色的 AI 智能体——为采用该模式的团队提供合约、校验机制以及可直接插入的代码模块。

1873 词

以下笔记围绕“如何使用LangGraph构建更优秀的AI智能体”梳理出一条实用路径。重点在于契约、校验机制以及可直接插入的代码占位符,而非激励性表述。 在完成概览阶段时,首先明确契约内容:所需输入、成功信号以及部分失败时的处理方式。这样的清单能确保后续的代码修改保持一致性。 同时记录正常流程与异常恢复路径。重试机制、人工审核环节以及错误处理都属于产品功能的一部分,而非后续的优化工作。

1. 研究大纲:掌握智能体工作流

在“掌握阶段”的1项研究框架中,将其视为可度量的对象最为有效。在扩大范围之前,先记录一份优秀的成果案例、一个失败案例以及回滚说明。 相较于庞大的脚本,应优先选择小型且可测试的单元。当某一步骤失败时,故障应能指向单一责任主体,而非复杂的流程链。 保持图表状态简洁且具有类型定义。嵌套的数据块会掩盖哪个节点修改了哪个字段的信息,还会在流程中断后导致无法继续执行。

2. 解决方案:自我修正的搜索代理

将“解决方案A”阶段视为可度量的界面来处理效果最佳。在扩大范围之前,先记录一份优秀的案例、一个失败案例以及回滚说明。 把这一阶段视为输入与已验证输出之间的契约。为相关成果命名,明确成功标准,绝不允许默默地部分完成任务。 保持图结构的状态简洁且类型明确。嵌套的数据块会掩盖哪个节点修改了哪个字段,还会在任务中断后导致无法继续执行。

导入

将“导入”阶段视为可度量的对象来处理,效果最佳。在扩大范围之前,先记录一个成功的案例、一个失败案例以及回滚说明。在功能结果旁同时记录执行时间以及令牌或查询成本。提前了解成本情况,就能避免在从演示环境过渡到共享环境时出现意外费用。要保持图表状态简洁且类型明确,嵌套的数据块会掩盖是哪个节点修改了哪个字段,还会在出现中断后导致流程无法继续。

import operator
from typing import Annotated, TypedDict, Union
from langgraph.graph import StateGraph, START, END

共享大脑

将“共享大脑”阶段视为可测量的界面来使用效果最佳。在扩大范围之前,先记录一个成功的案例、一个失败案例以及回滚说明。 将配置置于应用程序代码之外。环境文件、密钥存储和功能标志应集中存放于一个位置,这样操作人员无需查看整个结构即可进行审计。 保持图结构的层次简单且具有类型约束。嵌套的数据块会掩盖哪个节点修改了哪个字段的信息,还会在出现中断后导致无法继续处理。

# 1. State: The agent's shared memory
class AgentState(TypedDict):
  # 'operator.add' lets us append messages instead of overwriting
    messages: Annotated[list[str], operator.add]
    attempts: int
    found_info: bool

工作节点

将“工作节点”阶段视为可度量的对象来处理时,其效果最佳。在扩大范围之前,先记录一个成功的案例、一个失败案例以及回滚说明。 同时记录正常流程和恢复流程。重试机制、人工审核环节以及死信处理都是产品本身的一部分,而非后续需要补充的内容。 保持图结构的层次简单且类型明确。嵌套的数据块会掩盖哪个节点编写了哪个字段的信息,还会在中断后导致流程无法继续。

# 2. Nodes: Individual 'steps' in the process
def search_node(state: AgentState):
    print(f\n"--- Attempt {state['attempts'] + 1}: Searching ---")
    # Simulating a logic check
    success = state['attempts'] >= 1
    msg = "Success: Found LangGraph info!" if success else "No results found."
    return {"messages": [msg], "attempts": state['attempts'] + 1, "found_info": success}

def refine_query_node(state: AgentState):
    print("\n--- Refining query for better results ---")
    return {"messages": ["System: Query refined."]}

路由逻辑

将“路由逻辑”阶段视为可度量的对象来处理,其效果最佳。在扩大范围之前,先记录一份理想的运行示例、一个故障案例以及回滚说明。 优先选择小型且可测试的单元,而非庞大的脚本。当某个步骤出现故障时,故障应能指向单一责任主体,而非复杂的流程链。 保持图结构的层次简单且类型明确。嵌套的数据块会掩盖哪个节点修改了哪个字段的信息,还会在中断后导致流程无法继续。

def should_continue(state: AgentState):
    if state["found_info"] or state["attempts"] >= 3:
        return "end"
    return "refine"

构建图结构

将“构建图结构”阶段视为可度量的对象来处理效果最佳。在扩大范围之前,先记录一个成功的案例、一个失败案例以及回滚说明。 把这个阶段看作输入与经过验证的输出之间的契约。为相关成果命名,明确成功标准,绝不允许出现无声的、不完整的处理结果。 保持图结构的层次简单且类型明确。嵌套的数据块会掩盖是哪个节点修改了哪个字段,还会在处理中断后导致无法继续。

# 4. Build the Graph
workflow = StateGraph(AgentState)
workflow.add_node("search", search_node)
workflow.add_node("refine", refine_query_node)

workflow.add_edge(START, "search")
workflow.add_conditional_edges("search", should_continue, {"refine": "refine", "end": END})
workflow.add_edge("refine", "search")

运行代理程序

将“运行代理”阶段视为可度量的对象来处理,效果最佳。在扩大范围之前,先记录一份理想的执行日志、一个故障案例以及回滚说明。 在功能结果旁同时记录执行时间以及令牌或查询成本。提前了解成本情况,可避免在从演示环境过渡到共享环境时出现意外费用。 保持图结构简洁且类型明确。嵌套的数据块会掩盖哪个节点修改了哪个字段的信息,且在中断后会导致流程无法继续。

# 5. Execute
app = workflow.compile()
for output in app.stream({"messages": [], "attempts": 0, "found_info": False}):
    print(output)
--- Attempt 1: Searching ---
{'search': {'messages': ['No results found.'], 'attempts': 1, 'found_info': False}}

--- Refining query for better results ---
{'refine': {'messages': ['System: Query refined.']}}

--- Attempt 2: Searching ---
{'search': {'messages': ['Success: Found LangGraph info!'], 'attempts': 2, 'found_info': True}}

将“运行代理”阶段视为可度量的对象来处理,效果最佳。在扩大范围之前,先记录一份理想的执行日志、一个故障案例以及回滚说明。 需同时记录正常流程与恢复流程的文档。重试机制、人工审核环节以及死信处理都是产品本身的组成部分,而非后续需要补充的功能。

3. 提升 LangGraph 使用水平的五个技巧

关于实施这3个关键建议:在修改代码之前,需明确输入参数、该步骤的负责人以及结束标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。相比冗长的脚本,更应选择小型且易于测试的单元。当某个步骤失败时,故障原因应能指向单一责任主体,而非复杂的流程链。对于涉及资金支出或修改生产数据的操作,必须经过人工审批——仅靠编译时的配置并不能保证业务的完整性。

建议1:明确状态架构

对于第一个建议“掌控你的阶段”,在修改代码之前需明确输入内容、该步骤的负责人以及结束标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。 将这一阶段视为输入与经过验证的输出之间的契约。为相关成果命名,定义成功检测标准,并拒绝默许的半完成状态。 对于涉及资金支出或更改生产数据的环节,必须经过人工审批。编译时的连接并不等同于业务上的完整性。

建议2:掌握条件性路径

在“提示2:主条件控制”阶段,修改代码之前需明确输入参数、该步骤的负责人以及终止标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。 在功能结果旁记录执行时间以及令牌或查询成本。提前显示成本可避免在流程从演示环境转向共享环境时出现意外费用。 对于会产生费用或修改生产数据的操作,必须经过人工审批。编译时的连接方式并不等同于业务功能的完整性。 在“提示2:主条件控制”阶段,修改代码之前需明确输入参数、该步骤的负责人以及终止标准。操作人员应能够从已知的检查点重新运行该步骤,而无需猜测隐藏状态。 需同时记录正常流程和异常恢复流程。重试机制、人工审核环节以及错误处理措施都是产品的一部分,而非后续需要补充的内容。

建议3:切勿忽视持久性(检查点机制)

在实施建议3“不要分阶段处理”时,首先需明确合同条款:所需的输入参数、成功信号以及部分失败时的处理方式。这样的检查清单能确保后续的代码修改保持一致性。 优先选择小型、可测试的单元,而非庞大的脚本。当某个步骤失败时,故障应指向单一责任模块,而非复杂的流程链。 在耗时的步骤之后设置检查点。当操作员重新尝试后续节点时,恢复流程不应再次调用相同的LLM接口。

建议4:采用人工干预机制

在实践“提示4:拥抱阶段”时,首先写下相关契约:所需的输入、成功标志以及部分失败时的处理方式。这样的清单能确保后续的代码修改保持透明可溯。 将这一阶段视为输入与经过验证的输出之间的契约。为相关成果命名,明确成功判定标准,杜绝默许的部分完成情况。 在成本较高的步骤之后设置检查点。当操作员重新尝试后续节点时,恢复流程不应再次调用相同的LLM接口。

提示5:保持节点规模小巧

在遵循“保持阶段一致性”这一建议时,首先需明确合同条款:所需的输入参数、成功标志以及部分失败时的处理方式。这样的清单能确保后续的代码修改始终符合预期。 在功能结果旁记录执行时间以及令牌或查询成本。提前了解成本情况,可避免在从演示环境过渡到共享环境时出现意外费用。 在耗时的步骤之后设置检查点。当操作员重新尝试后续节点时,恢复流程不应再次收取相同的LLM调用费用。 在遵循“保持阶段一致性”这一建议时,首先需明确合同条款:所需的输入参数、成功标志以及部分失败时的处理方式。这样的清单能确保后续的代码修改始终符合预期。 需同时记录正常流程和故障恢复流程。重试机制、人工审核环节以及死信处理都是产品功能的一部分,而非后续需要补充的内容。

实际应用场景

在“实际应用”阶段,若能将其视为可度量的对象,效果会更好。在扩大范围之前,先记录一份理想的运行日志、一个故障案例以及回滚说明。 相较于庞大的脚本,应优先选择小型且可测试的单元。当某一步骤出现故障时,故障原因应能指向某个具体的责任模块,而非复杂的流程链。 保持图表状态简洁且具有类型定义。嵌套的数据结构会掩盖哪个节点修改了哪个字段的信息,还会在流程中断后导致无法继续执行。

参考资料

在“参考资料”阶段,若能将其视为可度量的对象,效果会更好。在扩大范围之前,先记录一份理想的运行日志、一个故障案例以及回滚说明。 应将此阶段视为输入与经过验证的输出之间的契约。为相关成果命名,明确成功标准,拒绝默许部分完成的情况。

操作检查清单