AI领域正以惊人的速度发展,各种概念层出不穷,例如生成式AI、AI Agent和Agentic AI。如果你想构建复杂的AI系统,理解这些概念之间的根本区别至关重要。本文将深入探讨这三大支柱,并指导你如何使用强大的LangGraph框架构建基于Agent的应用程序。

1. 生成式AI:内容创造者

生成式AI的核心在于创造新的内容。无论是使用GPT-4写诗,用DALL-E生成图像,还是用Claude起草电子邮件,你都在与生成式AI系统交互。

核心特征:

  • 被动响应: 它们响应你的提示,但不会主动发起行动。
  • 内容聚焦: 它们的主要任务是生成文本、图像、音频或视频。
  • 无状态交互: 每次对话都是独立的,没有记忆。

技术原理: 这些系统基于大型语言模型(LLM),LLM 接受海量数据集的训练,例如 Llama 3 和 GPT-4 等模型,它们已经消耗了大量的人类知识,成为了内容生成的强大工具。

实际案例: 你向ChatGPT 提出要求:“为我的新产品发布撰写一封营销电子邮件。” 它会根据它的训练数据生成一封完整的电子邮件。但它无法检查你当前的库存,访问你的客户数据库或安排发送这封电子邮件。这说明了生成式AI的局限性。

2. AI Agent:专业工作者

AI Agent更进一步,它不仅仅是生成内容,还能利用外部工具和数据源执行特定任务。可以把它想象成你的生成式AI模型,但现在它有能力在现实世界中采取行动。

核心特征:

  • 工具赋能: 可以调用外部API,搜索网络,查询数据库。
  • 任务特定: 专门设计用于解决特定问题。
  • 主动行动: 可以根据情况主动采取行动。

突破性概念: 工具调用。当LLM 意识到它没有回答你问题所需的信息时,它可以调用外部工具来收集该信息,处理信息,然后为你提供全面的响应。

实际案例: 你询问一个AI Agent:“今天关于AI 发展的最新消息是什么?” 该Agent 意识到它没有最新的信息,于是调用一个新闻API(如Tavily),检索今天的人工智能新闻,然后将其总结成连贯的响应。这展示了AI Agent 的强大之处,它超越了单纯的内容生成,能够主动获取和处理信息。

3. Agentic AI:协同工作流

Agentic AI 代表着一种完整的范式转变。它不是由单个AI 处理一项任务,而是由多个AI Agent协同工作、沟通和协调,以解决复杂的多步骤问题。

核心特征:

  • 多Agent 协作: 多个AI Agent 协同工作。
  • 工作流自动化: 可以处理复杂的多步骤流程。
  • Agent间通信: Agent 可以共享信息并在彼此的工作基础上进行构建。
  • 目标导向: 整个系统朝着实现特定目标而努力。

颠覆性变革: 这不仅仅是拥有多个AI Agent,而是让它们智能地协作。一个Agent 的输出成为另一个Agent 的输入,从而创建复杂的工作流程,处理单个AI 系统无法完成的任务。

实际案例: 你想将你的YouTube 视频转换为一篇博客文章。一个Agentic AI 系统可能会部署:

  • Agent 1: 从你的YouTube 视频中提取转录。
  • Agent 2: 从转录中创建一个引人入胜的标题。
  • Agent 3: 撰写引人入胜的描述。
  • Agent 4: 撰写一个总结所有内容的结论。
  • 协调器: 将所有输出组合成一篇最终的、润色的博客文章。

从生成式AI 到Agentic AI 的演变

生成式AI → AI Agent → Agentic AI

(被动响应) (主动行动) (协同工作)

这种演变不仅仅代表着技术的进步,更代表着我们构建AI 解决方案方式的根本转变。我们正在从简单地响应提示的系统,转向能够推理、计划和自主执行复杂工作流程的系统。

使用LangGraph 构建你的第一个AI Agent

现在让我们用LangGraph 来构建一个简单的AI Agent。

理解LangGraph 的核心概念

在深入研究代码之前,让我们回顾一下LangGraph 的关键概念。每个复杂的LangGraph 多Agent 系统都遵循我们即将探讨的模式:

  • 状态管理: 信息如何在系统中流动。State 类定义了agent之间的共享数据结构,确保了信息的连贯性。
  • 节点: 单独的处理单元(你的AI Agent)。每个节点都执行特定的任务,例如调用LLM 或执行工具。
  • 边: 这些单元如何连接和通信。边定义了节点之间的信息流,以及它们之间的依赖关系。
  • 图编译: 将所有这些组合在一起。编译后的图可以执行,并根据定义的状态和边在节点之间传递信息。

掌握这四个概念,你将理解LangGraph 的大部分强大之处。

搭建基本聊天机器人

步骤 1:设置你的环境

首先,确保你已安装了所有必要的库:

pip install langgraph langchain langchain-groq python-dotenv langchain-tavily

然后,创建一个 .env 文件,并在其中添加你的Groq API 密钥:

GROQ_API_KEY=YOUR_GROQ_API_KEY
TAVILY_API_KEY=YOUR_TAVILY_API_KEY
from typing import Annotated
from typing_extensions import TypedDict
from langgraph.graph import StateGraph, START, END
from langgraph.graph.message import add_messages
import os
from dotenv import load_dotenv

# 加载环境变量,创建 .env 文件并从 https://console.x.ai/team/YOUR_TEAM_ID/api-keys/create 获取你的 grok api 密钥
load_dotenv()

步骤 2:定义你的状态

LangGraph 与传统的聊天机器人不同,它以状态的概念来思考:

class State(TypedDict):
    # 消息类型为 "list"。`add_messages` 函数
    # 在注释中定义了如何更新此状态键
    # (在这种情况下,它将消息附加到列表中,而不是覆盖它们)
    messages: Annotated[list, add_messages]

此状态定义非常强大,因为它会自动维护对话历史记录。add_messages 函数确保每次交互都建立在前一次交互的基础上,从而创建真正的对话上下文。

步骤 3:连接你的LLM

from langchain_groq import ChatGroq
from langchain.chat_models import init_chat_model

# 两种初始化方式 - 都完美工作
llm = ChatGroq(model="llama3-8b-8192")
# 或者使用 init_chat_model 帮助器
#llm = init_chat_model("groq:llama3-8b-8192")

这里使用Groq,因为它对于学习来说速度快且具有成本效益。你可以轻松地将其替换为OpenAI、Anthropic 或任何其他与LangChain 兼容的模型。

步骤 4:创建你的节点函数

def chatbot(state: State):
    return {"messages": [llm.invoke(state["messages"])]}

这个简单的函数:

  • 接收当前状态(对话历史记录)。
  • 将其传递给LLM。
  • 返回以预期格式包装的LLM 的响应。

接收状态 -> 处理 -> 返回新状态 这种模式是每个LangGraph 节点的基础,无论它是一个简单的聊天机器人还是一个复杂的数据分析Agent。

步骤 5:构建和编译你的图

# 初始化图构建器
graph_builder = StateGraph(State)

# 将你的聊天机器人添加为节点
graph_builder.add_node("llmchatbot", chatbot)

# 定义流程:START -> chatbot -> END
graph_builder.add_edge(START, "llmchatbot")
graph_builder.add_edge("llmchatbot", END)

# 编译图
graph = graph_builder.compile()

步骤 6:可视化你的创建

from IPython.display import Image, display
try:
    display(Image(graph.get_graph().draw_mermaid_png()))
except Exception:
    pass

这会创建你的图的可视化表示,这在构建复杂的多Agent 系统时非常宝贵。

步骤 7:测试你的聊天机器人

# 单次交互
response = graph.invoke({"messages": "你好"})
print(response["messages"][-1].content)

# 输出:"你好!很高兴认识你。有什么我可以帮你的或者你想聊天的吗?"

# 流式响应(更具交互性)
for event in graph.stream({"messages": "你好吗?"}):
    for value in event.values():
        print(value["messages"][-1].content)

# 响应:你好!我只是一个语言模型,所以我没有像人类那样的情感或感觉,但我工作正常,可以帮助你解决任何问题或任务!今天我能帮你做什么?

从简单的聊天机器人到ReAct Agent:添加超能力

现在,让我们更进一步,将我们基本聊天机器人转变为ReAct Agent,它可以搜索网络、执行计算和推理复杂任务。

步骤 1:添加工具

我们将添加两种类型的工具:

  • 网络搜索: 用于访问实时信息。
  • 自定义函数: 用于执行计算。
from langchain_tavily import TavilySearch

# 网络搜索工具
tool = TavilySearch(max_results=2)

# 测试一下
tool.invoke("什么是langgraph")

# 自定义函数工具
def multiply(a: int, b: int) -> int:
    """Multiply a and b

    Args:
        a (int): first int
        b (int): second int

    Returns:
        int: output int
    """
    return a * b

# 合并工具
tools = [tool, multiply]

# 将工具绑定到我们的LLM
llm_with_tool = llm.bind_tools(tools)

步骤 2:构建启用工具的图

我们需要创建一个可以执行以下操作的图:

  • 处理用户输入。
  • 确定是否使用工具。
  • 执行工具(如果需要)。
  • 返回结果。
from langgraph.graph import StateGraph, START, END
from langgraph.prebuilt import ToolNode
from langgraph.prebuilt import tools_condition

# 节点定义
def tool_calling_llm(state: State):
    return {"messages": [llm_with_tool.invoke(state["messages"])]}

# 构建图
builder = StateGraph(State)
builder.add_node("tool_calling_llm", tool_calling_llm)
builder.add_node("tools", ToolNode(tools))

# 添加边
builder.add_edge(START, "tool_calling_llm")
builder.add_conditional_edges(
    "tool_calling_llm",
    # 如果来自助理的最新消息是工具调用 -> 路由到工具
    # 如果不是工具调用 -> 路由到 END
    tools_condition
)
builder.add_edge("tools", END)

# 编译图
graph = builder.compile()

步骤 3:测试工具集成

# 测试网络搜索
response = graph.invoke({"messages": "最近的人工智能新闻是什么?"})
print(response['messages'][-1].content)

# 测试自定义函数
response = graph.invoke({"messages": "5 乘以 2 等于多少?"})
for m in response['messages']:
    m.pretty_print()

# 测试需要多个工具的复杂查询
response = graph.invoke({"messages": "给我最近的人工智能新闻,然后将 5 乘以 10"})
for m in response['messages']:
    m.pretty_print()

ReAct 架构

ReAct 代表推理和行动。这是一种Agent:

  • 推理它需要做什么。
  • 通过使用工具来行动。
  • 观察结果。
  • 再次推理下一步骤。
  • 重复直到任务完成。

步骤 4:实现ReAct 架构

# 相同的节点定义
def tool_calling_llm(state: State):
    return {"messages": [llm_with_tool.invoke(state["messages"])]}

# 相同的图设置
builder = StateGraph(State)
builder.add_node("tool_calling_llm", tool_calling_llm)
builder.add_node("tools", ToolNode(tools))

# 关键区别:创建一个循环
builder.add_edge(START, "tool_calling_llm")
builder.add_conditional_edges(
    "tool_calling_llm",
    tools_condition
)

# 这是神奇的一行 - 工具流回LLM
builder.add_edge("tools", "tool_calling_llm")

# 编译
graph = builder.compile()

关键区别在于,我们使用builder.add_edge("tools", "tool_calling_llm") 而不是builder.add_edge("tools", END)。这会创建一个循环,其中:

  1. LLM 可以使用工具。
  2. 工具结果流回LLM。
  3. LLM 可以推理结果并使用更多工具。
  4. 该过程会继续,直到LLM 确定它已完成。

步骤 5:ReAct Agent 实战

response = graph.invoke({"messages": "给我最近的人工智能新闻,然后将 5 乘以 10"})
for m in response['messages']:
    m.pretty_print()

内部发生了什么:

  1. 用户: “给我最近的人工智能新闻,然后将 5 乘以 10”
  2. LLM 推理: “我首先需要搜索人工智能新闻”
  3. 行动: 调用 TavilySearch 工具
  4. 观察: 获取搜索结果
  5. LLM 推理: “现在我有了新闻,我需要将 5 乘以 10”
  6. 行动: 调用 multiply 函数
  7. 观察: 获取计算结果
  8. LLM 推理: “我已经有了这两条信息,我可以回复”
  9. 最终响应: 结合两个结果

结论

本文介绍了生成式AI、AI Agent 和 Agentic AI 的核心概念,并引导你使用LangGraph 构建了一个基本的聊天机器人和一个ReAct Agent。通过学习本文,你应该对如何使用LangGraph 构建更强大的AI 系统有了更深入的了解。在未来的博客中,我们将讨论关于存储、复杂工作流程、MCP 集成的内容,我们将使用上面所有的概念通过 langgraph 构建至少 20 个现实世界的复杂Agent。