图工程是将 AI 系统设计为图的一种实践,其中工作的每一步都是一个节点,从一个步骤到另一个步骤的每条路径都是一条边。我们将工作拆分成小步骤,并明确决定哪个步骤在哪个步骤之后运行。

在这篇博客中,我们将学习图工程,即将 AI 系统构建为由清晰路径连接的小步骤组成的图,而不是一个巨大的提示词或一个无休止的循环。我们还将了解为什么需要它,节点和边究竟意味着什么,状态如何在图中传递,条件边如何做出决策,循环如何让系统重复执行工作,并行分支如何节省时间,检查点如何让我们暂停和恢复,以及它在哪些场景下效果好、哪些场景下会失效。

我们将涵盖以下内容:

  • 什么是图工程?
  • 图 = 节点 + 边
  • 为什么我们需要图工程?
  • 三个基本构建块:节点、边和状态
  • 让我们构建第一个图
  • 条件边:在图内部做出决策
  • 循环:在需要时重复执行工作
  • 一次完整运行,逐步进行
  • 并行分支:同时做多件事
  • 检查点:暂停和恢复图
  • 人在回路中
  • 在图内部处理错误
  • 图工程 vs 循环工程
  • 图工程适用良好的场景
  • 图工程失效的场景
  • 图工程的最佳实践
  • 结论

我是 Amit Shekhar,Outcome School 的创始人,我曾教导和指导过许多开发者,他们的努力帮助他们获得了高薪的技术工作,帮助许多科技公司解决了他们的独特问题,并创建了许多被顶级公司使用的开源库。我热衷于通过开源、博客和视频分享知识。

我在 Outcome School 教授 AI 和机器学习。

让我们开始吧。

什么是图工程?

图工程是将 AI 系统设计为图的一种实践,其中工作的每一步都是一个节点,从一个步骤到另一个步骤的每条路径都是一条边。

图工程 = 图 + 工程。

简单来说,与其编写一条巨大的指令并期望模型一次性正确完成所有事情,不如将工作拆分成小步骤,然后明确决定哪个步骤在哪个步骤之后运行。

这里,每当我们说到模型时,指的是读取文本并生成文本的 AI 模型;每当我们说到工具时,指的是模型之外我们的系统可以调用的任何东西,比如搜索、数据库或电子邮件服务。

如今,我们主要在 AI Agent 的语境下听到这个词,这是有充分理由的。真实的工作从来不是一步完成的。真实的工作包含许多步骤,中间穿插着回退、等待、检查和审批。图工程(Graph Engineering)就是我们赋予系统这种形态的方式。

图 = 节点 + 边

在深入图工程之前,我们必须先了解什么是图。

图就是两样东西。

  • 节点:事情发生的地方。
  • 边:连接一个地方与另一个地方的路径。

学习这个概念最好的方式是通过一个例子。

假设我们在看一座城市的地铁图。图上的每个车站都是一个节点。两个车站之间的每条轨道都是一条边。列车从某个车站出发,沿轨道行驶,到达下一个车站,如此继续,直到到达终点站。

现在,把车站替换成我们工作的步骤,把轨道替换成我们工作的顺序。这正是我们在图工程中构建的图。

地铁图我们的 AI 系统
车站节点,即一小步工作
两个车站之间的轨道边,即通往下一步的路径
乘客携带的包状态(State),即沿途传递的信息
起点站我们系统开始的那一步
终点站我们系统停止的那一步

由此可以看出,边其实就是对一个小问题的回答:这一步结束后,下一步运行哪一步?

现在,我们已经理解了图。接下来,让我们理解为什么我们需要图工程。

为什么我们需要图工程?

假设我们要构建一个回答有关公司内部文档问题的系统。用户提出一个问题,我们的系统必须给出带有可靠来源的正确答案。

我们将一步一步地构建这个系统。在每一步中,我们都会看到问题所在,然后转向更好的方法。

方法一:一个大提示词

我们写一条长指令,发送给模型。

You are a helpful assistant. Read the user question. Search the company
documents. Read the results. Write an answer. Check that the answer is
correct. Add the sources. If something is missing, search again.

模型读完所有内容,试图一次性完成所有事情。

问题: 模型完成了一部分,却悄悄忽略了其他部分。有时它不搜索就直接写出答案。有时它搜索了却从不检查答案。而当输出出错时,我们完全不知道是哪个环节出了问题,因为一切都发生在单次调用之中。我们无法修复看不见的东西。

这种方法的问题在于完全没有结构。让我们看看下一种方法如何解决这个问题。

方法二:步骤链

现在,我们把工作拆分成多个独立的调用,并依次运行它们。

Step 1: understand the question
Step 2: search the documents
Step 3: write the answer
Step 4: send the answer

这就是提示词链,它要好得多。每一步只做一件事。当出现问题时,我们能准确知道是哪一步失败了。

问题: 链总是沿直线向前推进,从不回头。但真实的工作需要回头。如果搜索没有返回有用的结果怎么办?如果答案是错的、需要重写怎么办?直线链做不到这些,它只会一路向前,交付一个糟糕的答案。

这种方法的问题在于它无法回头。让我们看看下一种方法如何解决这个问题。

方法三:一个循环

现在,我们把整个流程放进一个 agent loop 中。模型思考、调用工具、查看结果,然后再次思考,如此反复,直到它判断工作完成为止。

这解决了“回头”的问题。模型可以重新搜索、重新撰写并自我纠正。

问题: 现在我们走向了另一个极端。每个决策都由模型在一个循环内做出,因此我们的控制力非常有限。模型会把同一个失败的搜索重复十次;它会因为感觉有把握而跳过检查步骤;它会在我们绝不想让它调用的时刻调用一个危险工具。每次运行的路径都不同,因此测试变得非常困难。

这种方法的问题在于流程完全掌握在模型手中。让我们看看下一种方法如何解决这个问题。

方法四:图

于是,图工程(Graph Engineering)前来救场。

我们保留方法二的小步骤,保留方法三的回头能力,并亲自写下路径。

understand  ->  search  ->  write  ->  check
check       ->  send        (when the answer is good)
check       ->  search      (when the sources are missing)
check       ->  write       (when the answer is weak)

在这里,我们可以看到每一步都很小且可见,系统可以在需要时回头,而模型只在我们允许它做决策的地方做决策。

问题解决了。这就是图工程。

我们这里举的例子——系统搜索、撰写、检查、再搜索——就是我们所说的 Agentic RAG,我们有一篇详细的博客对它进行了深入讲解。

三个基本构建块:节点、边和状态

我们构建的每个图都只有三个部分。

节点: 节点是工作中的一个步骤。它只是一个函数。它接收当前信息,完成一个小任务,然后返回更新后的信息。节点可以调用模型、调用工具、访问数据库,或者运行完全不用模型的普通代码。

边: 边是从一个节点到另一个节点的路径。它只回答一个问题:下一个运行哪个节点?

状态: 状态是图的共享笔记本。每个节点都从这个笔记本中读取信息,并向其中写入信息。第二个节点就是通过这种方式知道第一个节点做了什么。

让我们看看我们的文档问答系统的状态,如下所示:

state = {
    "question": "What is our refund policy?",
    "intent": None,
    "documents": [],
    "answer": None,
    "score": None,
    "attempts": 0,
}

在这里,我们创建了一个值为空的简单笔记本。随着图的运行,节点会不断填充这些值。

understand

节点填充

intent

。该

search

节点填充

documents

。该

write

节点填充

answer

。该

check

节点填充

score

和

attempts

.

这个状态是图工程中最重要的设计决策。如果状态保持干净,图就会保持简单。如果状态变成随意堆放各种键的垃圾场,图就会变得无法理解。节点呈现给模型的内容也来自这个状态,因此保持状态干净同时也是良好的上下文工程。

现在我们已经了解了构建模块,是时候构建一个真正的图了。

让我们构建第一个图

首先,我们将编写节点。每个节点都是一个普通函数。

def understand(state):
    state["intent"] = model.find_intent(state["question"])
    return state

def search(state):
    state["documents"] = db.search(state["intent"])
    return state

def write(state):
    state["answer"] = model.write_answer(state["question"], state["documents"])
    return state

在这里,我们可以注意到每个函数只做一件事,并返回更新后的状态。任何地方都没有庞大的指令。

understand

节点只负责识别意图。

search

节点只负责搜索。

write

节点只负责根据

search

节点找到的文档撰写答案。

然后,我们将用边连接这些节点。

graph = Graph(state)

graph.add_node("understand", understand)
graph.add_node("search", search)
graph.add_node("write", write)

graph.add_edge("understand", "search")
graph.add_edge("search", "write")

graph.set_entry("understand")
graph.set_finish("write")

在这里,我们首先将三个节点添加到图中。然后,我们添加了两条边。第一条边表示在

understand

。该

search

节点运行。第二条边表示在

search

。该

write

节点运行。最后,我们告诉了图从哪里开始、在哪里结束。

之后,我们就可以运行这个图了。

final_state = graph.run(state)
print(final_state["answer"])

在这里,我们将起始笔记本交给图。图从一个节点走到另一个节点,每个节点更新笔记本,最后我们从同一个笔记本中读取答案。

它运行得非常完美。但这个图仍然是一条直线,与方法二完全一样。现在,让我们赋予它做决策的能力。

注意: 为了便于理解,本博客中的代码保持简单。为这项工作构建的真实库提供了相同的三要素——节点、边和状态,只是名称略有不同。LangGraph 是其中最流行的一个,我们有一篇关于它的详细博客,逐步解释了它的工作原理。

计划转型进入 AI 领域?

无论你今天在哪个技术领域工作,只要付出努力,你都可以转型到以下这些角色:

  • AI 工程师
  • 前沿部署工程师
  • AI Agent 工程师
  • Harness 工程师
  • 语音 AI 工程师
  • AI 架构师
  • LLM 工程师
  • LLM 推理工程师
  • 生成式 AI 工程师
  • MLOps 工程师
  • 机器学习工程师
  • 深度学习工程师

Outcome School 的 AI 与机器学习课程将带你实现这一目标。

条件边:在图内部做出决策

普通边总是通向同一个下一个节点。条件边会先查看状态,然后决定接下来运行哪个节点。

让我们添加一个

check

节点,为我们的答案打分。

def check(state):
    state["score"] = model.rate_answer(state["answer"], state["documents"])
    state["attempts"] = state["attempts"] + 1
    return state

在这里,我们将模型用作评审者,这就是 LLM 作为评审模式。它会连同文档一起阅读答案,并给出十分制的评分。我们还在统计尝试次数,很快你就会明白为什么这个计数如此重要。

现在,我们将编写路由函数。

def route_after_check(state):
    if state["score"] >= 8:
        return "send"
    if not state["documents"]:
        return "search"
    return "write"

在这里,我们可以看到决策是纯代码,完全掌握在我们手中。如果分数好,我们就前往

send

。如果完全没有文档,我们就回到

search

。在其他所有情况下,我们都回到

write

再试一次。

然后,我们将这个函数作为条件边附加。

graph.add_node("check", check)
graph.add_node("send", send)

graph.add_edge("write", "check")
graph.add_conditional_edge("check", route_after_check)

graph.set_finish("send")

我们遵循了以下步骤:

  • 我们添加了 check 节点和 send 节点。send 节点是一个小节点,只是将最终答案交付给用户。
  • 我们添加了从 write 到 check 的普通边,因此每个答案都会送去审查。
  • 我们添加了从 check 出发的条件边。这条边有三个可能的目的地,我们的路由函数通过读取状态来选择其中一个。
  • 我们将终点从 write 移到了 send,因为 send 现在是我们图的最后一站。

注意: 模型给出了分数,但模型并没有选择路径。路径是由我们自己的代码选择的。这就是图工程的核心。我们让模型负责思考,而把流程的控制权留给自己。

要学习图工程、编排与路由,以及 LLM 作为评判者,我们在 Outcome School 的 AI 与机器学习项目 中对它们进行了深入讲解。

循环:在需要时重复执行工作

在上面的图中,

check

可以把我们送回

write

和

write

又把我们送到

check

。这种在两个节点之间来回往返称为一个

cycle

.

循环是非常强大的东西,因为这就是系统自我纠正的方式。写作、审查、写得更好、再审查。这正是人类的工作方式,也是 Reflection Agent 背后的理念。

但是,这里有个陷阱。循环可能会永远运行下去。如果审查者从不给出八分,我们的图就会一直写作和检查,直到我们的钱花完为止。

所以,每个循环都必须有停止条件。这就是为什么我们要在

check

节点内统计尝试次数。

def route_after_check(state):
    if state["score"] >= 8:
        return "send"
    if state["attempts"] >= 3:
        return "ask_human"
    if not state["documents"]:
        return "search"
    return "write"

在这里,我们添加了两行高亮的代码。三次尝试之后,图会自行停止尝试,并通过一个新的

ask_human

节点把工作交给人类。我们还必须把这个节点添加到图中,否则图将不知道这条路径通向哪里。

graph.add_node("ask_human", ask_human)
graph.add_edge("ask_human", "send")

在这里,我们添加了

ask_human

节点并将其连接到

send

,这样即使是这条糟糕的路径也能正确到达最后一站。

我们完整的图现在如下所示:

understand  ->  search  ->  write  ->  check
check       ->  send        (the score is good)
check       ->  ask_human   (three attempts are over)
check       ->  search      (there are no documents)
check       ->  write       (the answer is weak)
ask_human   ->  send

在这里,我们可以在一个屏幕上看到系统的完整形态。每一步都是一个节点,每一条线都是一条边,任何地方都没有隐藏的行为。

我们的系统现在以安全且可预测的方式失败,而不是永远运行下去。

非常重要: 我们图中的每个循环都必须有硬性上限。

给你的快速提示

无论你在哪个技术领域工作,都要熟悉这些主题:

  • LLM
  • RAG
  • MCP
  • Agent
  • 微调
  • 量化

我们把它们全部整合在一个视频中:

AI 工程详解:LLM、RAG、MCP、Agent、微调与量化

不必现在就读完——先收藏起来,等有空的时候再看。未来的你会感谢现在的你。

现在,让我们回到正题。

一次完整运行,逐步进行

现在,让我们完整地走一遍运行流程,看看每个节点执行后笔记本的状态。这是感受图如何真正运作的最佳方式。

第 1 步: 用户提出一个问题,所以初始状态是:

question: "What is our refund policy?"
intent: None, documents: [], answer: None, score: None, attempts: 0

第 2 步:

understand

节点运行并填充意图(intent):

intent: "refund policy duration and conditions"

第 3 步:

search

节点运行并填充文档(documents):

documents: ["policy-v3.pdf", "faq-refunds.md"]

第 4 步:

write

节点运行并填充答案(answer):

answer: "Refunds are allowed within 30 days."

第 5 步:

check

节点运行。答案中没有来源,所以审查者给出了低分:

score: 5, attempts: 1

第 6 步: 条件边读取状态。分数低于八,文档存在,且尝试次数低于三次,所以路径回到

write

.

第 7 步:

write

节点再次运行,这次它写出了一个带来源的更好答案:

answer: "Refunds are allowed within 30 days of purchase, as per policy-v3.pdf."

第 8 步:

check

节点再次运行:

score: 9, attempts: 2

第 9 步: 条件边再次读取状态。分数达到八或以上,所以路径走向

send

,图到此停止。

在这里,我们可以注意到一个美妙之处:系统发现了自己的错误并加以纠正,而且始终没有脱离我们的控制,因为每一条路径都是我们自己编写的。

以上就是我们图的一次完整运行。现在,让我们看看如何让图运行得更快。

并行分支:同时做多件事

有时两个步骤之间毫无关联。搜索我们的内部文档和搜索公共网络是完全独立的。按顺序逐个运行只会浪费时间。

在图中,我们可以把一个节点同时发送到两个节点。

graph.add_edge("understand", "search_docs")
graph.add_edge("understand", "search_web")

graph.add_edge("search_docs", "merge")
graph.add_edge("search_web", "merge")

在这里,我们可以看到两点。第一,

understand

有两条出边,所以两个搜索同时开始。这称为扇出(fan-out)。第二,两个搜索都指向同一个

merge

节点,所以图会等待两者都完成后再继续。这称为扇入(fan-in)。

。该

merge

节点将两个结果合并在一起。

def merge(state):
    state["documents"] = state["doc_results"] + state["web_results"]
    return state

在这里,我们只是把两个列表合并到

documents

键中,图的其余部分甚至不需要知道发生过两次搜索。

扇出和扇入是我们用来协调多个步骤的常见模式中的两种。我们有一篇关于 AI 编排 的详细博客,端到端地介绍了这些模式。

注意: 当两个节点同时运行时,它们必须写入状态的不同键。如果两者写入同一个键,其中一个会悄悄覆盖另一个,而我们可能会花上好几个小时去找这个 bug。

检查点:暂停和恢复图

一个长图需要时间。它会调用模型、调用工具,并等待缓慢的服务。那么,如果我们的服务器在运行中途重启会发生什么?在简单的循环中,一切都会丢失,用户必须从零开始。

这时检查点(checkpointing)就派上用场了。

每个节点完成后,图会保存状态。这个保存下来的状态称为检查点。如果出现故障,我们加载最后一个检查点,并从那个确切的节点继续。

graph = Graph(state, checkpointer=Database())

final_state = graph.run(state, thread_id="user-123")

在这里,我们为图提供了一个存储,并为这次特定的运行分配了一个 id。每个节点之后,状态都会针对这个 id 进行保存。如果这次运行在

search

节点之后中断,我们用相同的

run

再次调用

thread_id

,图就会从

write

开始,而不是从

understand

.

之所以能做到这一点,是因为我们系统的全部进展都保存在一个简单的状态对象中。这也是保持状态整洁如此重要的又一个原因。

保持更新: 订阅我们的新闻通讯,将我们最新的 AI 和机器学习博客直接发送到您的收件箱。

到目前为止,我们已经学习了图如何独立运行。现在,是时候了解人类加入图的地方了。

人在回路中

有些步骤必须有人类说“是”才能进行。给客户发送邮件。发放退款。删除记录。将代码推送到线上应用。

因为我们的工作被划分为节点,我们可以简单地在这样的节点之前停止图。

graph.add_node("send_email", send_email, interrupt_before=True)

在这里,我们将一个节点标记为停止点。当图到达

send_email

时,它会保存状态并暂停。此时还没有发送任何内容。

现在,人类打开待处理的工作,阅读草稿,并做出决定。

if human_says_yes:
    graph.resume(thread_id="user-123")
else:
    graph.update_state(thread_id="user-123", changes={"answer": edited_answer})
    graph.resume(thread_id="user-123")

在这里,我们可以看到,人类既可以允许图继续运行,也可以先修正状态中的答案,然后再允许它继续。图甚至不知道有人类触碰过它。它只是读取状态并继续前进。

这样,我们就获得了自动化的速度,同时拥有人工审查的安全性。

如果想深入了解 Agent 架构、Agent 中的记忆以及 Agent 中的工具使用,我们在 Outcome School 的 AI 和机器学习课程中会从零开始全面讲解这些内容。

在图内部处理错误

工具会失败。网络会失败。模型会返回错误的输出。在一个大提示词中,一次失败会毁掉一切。而在图中,失败只是某个节点表现不佳,我们可以像处理其他信息一样,把它保存在状态中。

def search(state):
    try:
        state["documents"] = db.search(state["intent"])
        state["error"] = None
    except Exception:
        state["error"] = "search service is down"
    return state

在这里,我们捕获了失败并将其写入状态,而不是让整个图崩溃。

然后,我们编写一个路由函数,读取该错误并决定如何处理。

def route_after_search(state):
    if state["error"]:
        return "search_web"
    if not state["documents"]:
        return "ask_human"
    return "write"

接着,我们将从

search

出来的普通边替换为如下所示的条件边:

graph.add_conditional_edge("search", route_after_search)

在这里,我们可以注意到,失败现在只是图中的一个普通路径。当我们自己的搜索服务宕机时,我们会回退到网络搜索。当完全没有任何可依据的内容时,我们会求助人工。没有任何东西会崩溃,用户总能得到某种响应。

这就是我们构建一个即使在糟糕的日子里也能持续运行的系统的方式。

既然我们已经了解了完整的图,现在是时候将它与构建 AI 系统的另一种流行方式进行比较了。

图工程 vs 循环工程

循环工程是指一个 Agent 在循环中思考,自行决定下一步动作,并在它觉得工作完成时停止。图工程则是许多小的步骤,而它们之间的路径由我们写下来。

让我用表格列出循环工程和图工程之间的区别,以便你更好地理解。

对比点循环工程图工程
谁决定下一步由模型决定由我们的代码根据模型的输出决定
结构一个“思考与行动”的循环由边连接的许多节点
每次运行的路径每次都不同相同情况走相同路径
测试困难,因为路径不断变化容易,我们可以一次测试一个节点
查找 Bug我们要阅读模型所做一切操作的长长历史记录我们只需查看失败的那一个节点
模型的自由度非常高仅限于我们允许的范围
最适合开放式和未知的任务有明确阶段的已知工作

为了掌握循环工程、图工程和多 Agent 系统,我们在 Outcome School 的 AI 与机器学习课程中从零开始构建一个 AI 编程 Agent。

图工程适用良好的场景

  • 有明确阶段的工作。 工单支持、退款处理、文档审查和报告撰写都有自然的阶段形态。
  • 需要审批的工作。 因为我们可以在任意节点暂停,人工审查可以非常自然地融入其中。
  • 必须可重复的工作。 相同的输入走相同的路径,因此我们可以测试并信任它。
  • 长时间运行的工作。 检查点让图能够在重启后存活,并持续运行数小时甚至数天。
  • 包含独立部分的工作。 并行分支可以同时完成多个搜索或多项检查。
  • 必须可解释的工作。 我们可以逐个节点展示所采取的确切路径。在银行、医疗和法律工作中,这一点非常重要。

图工程失效的场景

  • 真正开放式的工作。 如果我们连阶段都无法命名,那么画图就只是猜测。循环在那里更合适。
  • 非常简单的工作。 如果一次模型调用就能回答问题,图只会增加工作量而没有好处。
  • 不加节制增长的图。 一个有六十个节点且边四通八达的图,比一个大的提示词还要糟糕,因为现在混乱分散在许多文件中。
  • 混乱的状态。 当每个节点都添加一些键,而没有人删除任何东西时,状态就会变成垃圾场,任何节点都无法被独立理解。
  • 隐藏的依赖。 如果一个节点悄悄依赖某个只有部分先前节点才会写入的键,那么移动节点就会以极难发现的方式破坏整个图。
  • 没有限制的循环。 只要缺少一个停止条件,我们的图就会整夜原地打转,而每一圈都要花钱。

图工程的最佳实践

保持每个节点都很小。 一个节点,一个任务。如果我们无法用一句简短的话描述一个节点,那么它就必须拆分成两个节点。

先设计状态。 写下每一个键、它保存什么内容、以及由哪个节点来填充它。在编写任何节点之前先完成这一步。

把决策保留在代码中,而不是文字里。 让模型给出分数、标签或选择。让我们自己的代码读取该值并选择路径。这一个习惯就能给我们带来大部分控制权。

给每个循环设置上限。 在状态中记录尝试次数,并始终为次数超限的情况准备一条退出路径。

始终要有出口。 图中的每条路径都必须到达终点,即使是失败路径。一条无处可去的路径就是一个挂起的系统。

把失败转化为路径。 把错误写入状态,并据此进行路由。不要让一次糟糕的工具调用毁掉整个运行。

在纸上画出图。 如果我们画不出来,那么我们的队友和用户就永远不会理解它。画不出来的图就是过于复杂的图。

记录每个节点的日志。 保存哪个节点运行了、输入了什么、输出了什么。当出现问题时,这份日志能直接带我们找到出问题的节点。这正是让我们对系统获得真正可观测性的关键。

逐个节点进行测试。 每个节点都只是一个从状态到状态的函数,因此我们可以用固定的状态、完全不用模型来单独测试它。相比一整个大提示词,这是一个巨大的优势。

从一条直线开始。 先构建最简单的可用路径。只有当真实的问题需要时,才添加分支、循环和并行工作。

结论

图工程是一个简单的理念。把工作拆分成小步骤,写下这些步骤之间的路径,并把所有进展保存在一个共享状态中。

当我们这样做时,我们的 AI 系统就不再是一个偶尔能用的黑盒。它变成了一个我们可以查看、测试、暂停、恢复、纠正并向任何人解释的系统。

模型仍然负责思考。图决定思考的去向。

现在我们应该已经理解了图工程,可以开始为正在构建的工作绘制我们自己的图了。

常见问题

图工程和提示词链是一回事吗?

不是。提示链将工作拆分为多个依次运行的独立调用,但链条总是沿直线向前推进,从不回头。图工程保留了这些小步骤,并增加了回退、分支和决策的能力,步骤之间的路径由我们自己编写。

在图工程中,是由模型选择下一步吗?

不是。模型可以给出分数、标签或选择,但由我们自己的代码从状态中读取该值并决定路径。我们让模型负责思考,而把流程的控制权留给自己。这正是图工程的核心。

图中的每个节点都需要调用 AI 模型吗?

不需要。节点只是一个函数,它接收当前状态,完成一个小任务,然后返回更新后的状态。节点可以调用模型、调用工具、访问数据库,或者运行完全不涉及模型的普通代码。这也是我们可以单独测试每个节点的原因。

LangGraph 和图工程是同一回事吗?

不是。图工程是一种将 AI 系统设计为节点、边和状态的实践。LangGraph 是为此工作构建的最流行的库。这类库为我们提供了节点、边和状态这三个相同的概念,只是名称略有不同。

如果两个并行节点写入同一个状态键会怎样?

其中一个会悄悄覆盖另一个。当两个节点在并行分支中同时运行时,它们必须写入状态的不同键。然后可以由一个合并节点将结果连接起来,这样图的其余部分就不需要知道有两个分支同时运行过。

目前就到这里。

谢谢

Amit Shekhar Outcome School 创始人

你可以通过以下方式与我联系:

关注 Outcome School: