## 前言

在上一篇文章中,我们使用 `create_react_agent` 快速搭建了第一个 LangGraph Agent。但在实际开发中,我们常常需要更灵活的控制流程。本文将带你深入理解 LangGraph 的核心概念——**StateGraph(状态图)**,通过从零构建一个聊天机器人,掌握状态管理、节点编排和流式输出等关键技术。

---

## 一、核心概念

### 1.1 什么是 StateGraph

StateGraph 是 LangGraph 的核心抽象,它将应用建模为**状态机**:

- **状态(State)**:应用在某个时刻的数据快照

- **节点(Node)**:执行特定任务的函数

- **边(Edge)**:定义节点之间的流转关系

类比理解:

- StateGraph 就像一张**流程图**

- 节点是流程图中的**处理步骤**

- 边是连接步骤的**箭头**

### 1.2 为什么需要 StateGraph

| 场景 | `create_react_agent` | `StateGraph` |

|------|---------------------|--------------|

| 快速原型 | ✅ 适合 | ⚠️ 需要更多代码 |

| 自定义流程 | ❌ 固定 ReAct 模式 | ✅ 完全可控 |

| 多节点协作 | ❌ 单节点 | ✅ 支持多节点 |

| 条件分支 | ❌ 不支持 | ✅ 支持条件边 |

StateGraph 提供了**细粒度的控制能力**,适合构建复杂的 AI 工作流。

---

## 二、环境准备

### 2.1 安装依赖

```bash

pip install langgraph langchain langchain-openai pydantic python-dotenv typing-extensions

```

### 2.2 配置 API 密钥

创建 `.env` 文件:

```env

SILICONFLOW_API_KEY=your_api_key_here

```

---

## 三、代码实现

### 3.1 完整代码

```python

"""

LangGraph 教程 - 构建一个基本聊天机器人

本示例演示如何使用 StateGraph 构建一个基础聊天机器人。

这是 LangGraph 系列教程的基础,后续将逐步添加更复杂的功能。

官方教程地址:https://langchain-ai.github.io/langgraph/tutorials/introduction/

"""

# 过滤警告信息

import warnings

warnings.filterwarnings("ignore", category=DeprecationWarning)

warnings.filterwarnings("ignore", category=UserWarning)

from typing import Annotated

from typing_extensions import TypedDict

from langgraph.graph import StateGraph, START

from langgraph.graph.message import add_messages

from langchain_openai import ChatOpenAI

from dotenv import load_dotenv

import os

# 加载环境变量

load_dotenv()


 

# ==================== 1. 定义状态 ====================

class State(TypedDict):

    """

    定义图的状态结构。

   

    messages: 消息列表,使用 add_messages reducer 函数

              确保新消息追加到列表,而不是覆盖

    """

    messages: Annotated[list, add_messages]


 

# ==================== 2. 创建图构建器 ====================

graph_builder = StateGraph(State)


 

# ==================== 3. 初始化模型 ====================

# 使用硅基流动平台的 Qwen 模型

llm = ChatOpenAI(

    model="Qwen/Qwen3-Next-80B-A3B-Instruct",

    openai_api_key=os.getenv("SILICONFLOW_API_KEY"),

    openai_api_base="https://api.siliconflow.cn/v1",

    temperature=0.7

)


 

# ==================== 4. 定义聊天机器人节点 ====================

def chatbot(state: State):

    """

    聊天机器人节点函数。

   

    Args:

        state: 当前状态,包含消息历史

       

    Returns:

        包含 LLM 响应消息的字典

    """

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


 

# 添加节点到图

# 第一个参数是节点名称,第二个参数是节点函数

graph_builder.add_node("chatbot", chatbot)


 

# ==================== 5. 添加入口点 ====================

# 告诉图每次运行时从哪里开始

graph_builder.add_edge(START, "chatbot")


 

# ==================== 6. 编译图 ====================

# 编译图,创建可执行的 CompiledGraph

graph = graph_builder.compile()


 

# ==================== 7. 可视化图(可选)====================

def visualize_graph():

    """可视化图结构(需要安装额外依赖)。"""

    try:

        from IPython.display import Image, display

        display(Image(graph.get_graph().draw_mermaid_png()))

    except Exception as e:

        print(f"可视化失败(可选功能): {e}")

        print("提示:可以通过安装依赖来使用可视化功能")


 

# ==================== 8. 运行聊天机器人 ====================

def stream_graph_updates(user_input: str):

    """

    流式处理图更新。

   

    Args:

        user_input: 用户输入的消息

    """

    for event in graph.stream({"messages": [{"role": "user", "content": user_input}]}):

        for value in event.values():

            print("助手:", value["messages"][-1].content)


 

def main():

    """主函数 - 运行交互式聊天机器人。"""

    print("🤖 LangGraph 聊天机器人已启动!")

    print("=" * 50)

    print("提示:输入 'quit'、'exit' 或 'q' 退出对话\n")

   

    while True:

        try:

            # 获取用户输入

            user_input = input("用户: ")

           

            # 检查退出命令

            if user_input.lower() in ["quit", "exit", "q"]:

                print("\n👋 再见!")

                break

           

            # 处理用户输入并获取响应

            stream_graph_updates(user_input)

            print()  # 空行分隔对话

           

        except KeyboardInterrupt:

            print("\n\n👋 再见!")

            break

        except Exception as e:

            print(f"发生错误: {e}")

            # 备用方案:使用默认输入

            user_input = "What do you know about LangGraph?"

            print(f"\n用户: {user_input}")

            stream_graph_updates(user_input)

            break


 

if __name__ == "__main__":

    main()

```

### 3.2 代码解析

#### 3.2.1 定义状态

```python

from typing import Annotated

from typing_extensions import TypedDict

from langgraph.graph.message import add_messages

class State(TypedDict):

    messages: Annotated[list, add_messages]

```

**关键点**:

- `TypedDict`:定义状态的结构类型

- `Annotated`:为类型添加元数据

- `add_messages`:**reducer 函数**,确保消息追加而非覆盖

#### 3.2.2 创建图构建器

```python

from langgraph.graph import StateGraph, START

graph_builder = StateGraph(State)

```

`StateGraph` 是图的构建器,接收状态类型作为参数。

#### 3.2.3 定义节点

```python

def chatbot(state: State):

    """聊天机器人节点函数。"""

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

graph_builder.add_node("chatbot", chatbot)

```

节点函数的特点:

- **输入**:当前 `state`

- **输出**:状态更新字典

- **命名**:通过 `add_node` 注册到图中

#### 3.2.4 定义边

```python

graph_builder.add_edge(START, "chatbot")

```

- `START`:图的入口点

- `"chatbot"`:目标节点名称

#### 3.2.5 编译图

```python

graph = graph_builder.compile()

```

编译后的 `graph` 可以被执行,支持 `stream()` 和 `invoke()` 方法。

#### 3.2.6 流式执行

```python

def stream_graph_updates(user_input: str):

    for event in graph.stream({"messages": [{"role": "user", "content": user_input}]}):

        for value in event.values():

            print("助手:", value["messages"][-1].content)

```

`graph.stream()` 的特点:

- **流式输出**:实时返回每个节点的执行结果

- **事件结构**:`{节点名: {状态更新}}`

- **适用场景**:长任务、需要实时反馈的场景

---

## 四、运行效果

### 4.1 执行步骤

```bash

python 02构建一个基本聊天机器人.py

```

### 4.2 输出结果

---

## 五、核心概念图解

### 5.1 状态流转图

```

┌─────────┐     ┌─────────────┐     ┌─────────┐

│  START  │────▶│  chatbot    │────▶│   END   │

│ (入口)  │     │ (LLM 节点)  │     │ (结束)  │

└─────────┘     └─────────────┘     └─────────┘

                      │

                      ▼

              ┌─────────────┐

              │   State     │

              │  messages   │

              └─────────────┘

```

### 5.2 执行流程

```

用户输入 ──▶ 构建初始 State ──▶ graph.stream() ──▶ 节点执行

                                              │

                                              ▼

用户 ◀── 提取响应 ◀── 更新 State ◀── LLM 调用 ◀── chatbot 节点

```

---

## 六、踩坑记录

| 问题 | 原因 | 解决方案 |

|------|------|----------|

| `TypedDict` 导入错误 | Python 版本问题 | 使用 `typing_extensions` 替代 |

| 消息被覆盖而非追加 | 缺少 reducer | 使用 `Annotated[list, add_messages]` |

| 节点函数返回值格式错误 | 不了解规范 | 必须返回 `{状态键: 更新值}` 字典 |

| 图无法执行 | 忘记编译 | 调用 `graph_builder.compile()` |

---

## 七、总结

通过本文,你学会了:

1. ✅ **StateGraph 核心概念**:状态、节点、边

2. ✅ **状态定义**:使用 `TypedDict` 和 `Annotated`

3. ✅ **节点编写**:输入状态、返回更新

4. ✅ **图构建**:添加节点、定义边、编译执行

5. ✅ **流式输出**:使用 `graph.stream()` 实时获取结果

### 进阶方向

- **条件边**:使用 `add_conditional_edges` 实现分支逻辑

- **多节点协作**:构建复杂的多步骤工作流

- **持久化存储**:集成检查点器实现对话记忆

- **人机协作**:添加 Human-in-the-loop 节点



 

---

## 参考资料

- [LangGraph 官方教程](https://langchain-ai.github.io/langgraph/tutorials/introduction/)

- [StateGraph API 文档](https://langchain-ai.github.io/langgraph/reference/graphs/)

- [Python TypedDict 文档](https://docs.python.org/3/library/typing.html#typing.TypedDict)

---

> 📌 本文首发于 CSDN,作者:码上AI_123

> 🔗 转载请注明出处

>

> 💡 如果觉得有帮助,欢迎点赞、收藏、关注!

> 🎯 你的支持是我持续创作的动力!

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐