How to Build Your First Multi-Agent AI System in Python and LangGraph

TL;DR · AI 摘要
本文详解使用Python和LangGraph构建多智能体AI系统,对比框架与无框架实现的差异,强调本地运行的低成本优势。
核心要点
- LangGraph通过节点边实现工作流管理,降低多智能体系统开发复杂度
- Ollama+Qwen组合可实现零API成本的本地智能体部署
- 多智能体系统适合任务可拆解为独立步骤的场景,如规划/写作/审核流程
结构提纲
按章节快速跳转。
思维导图
用一张图看清主题之间的关系。
查看大纲文本(无障碍 / 无 JS 友好)
- 多智能体系统构建
- 实现方式
- Python原生实现
- LangGraph框架
- 核心工具
- Ollama
- Qwen
- 优势
- 零API成本
- 任务拆解能力
金句 / Highlights
值得收藏与分享的关键句。
多智能体系统通过责任划分使每个代理的提示更简单易执行
LangGraph框架通过节点边定义实现工作流管理,降低开发复杂度
Ollama+Qwen组合实现本地运行,避免API成本且支持32GB内存以下设备
如何使用 Python 和 LangGraph 构建你的第一个多智能体 AI 系统
2026年7月14日
/
#AI
Darsh Shah
在本教程中,我将向你展示如何在不使用任何编排框架的情况下,用 Python 构建多智能体 AI 系统。我们还将使用 LangGraph 的节点、边和共享状态来实现该系统。
构建两个版本的目的是向你展示使用框架与不使用框架之间的差异。
简单的 Python 版本展示了构建多智能体系统实际上需要多么少的代码。LangGraph 版本则展示了工作流框架在构建此类系统时能带来的能力。
智能体通过 Ollama 和 Qwen 本地运行,因此你将不会产生任何 API 成本。
目录
- 背景
- 什么是多智能体系统?
- 单智能体与多智能体系统
- 动机与架构
- 步骤 1:安装 Ollama 和依赖项
- 步骤 2:简单 Python 版本
- 步骤 3:使用节点和边的 LangGraph 版本
- 示例输出
- 常见多智能体模式
- 结论
背景
大型语言模型能够通过单一提示解决令人惊讶的复杂任务。对于许多应用来说,这正是正确的做法。
但随着工作流的增长,单一提示通常需要同时处理太多事情。将所有这些责任合并到一个提示中会使维护、扩展和推理问题变得更加困难,尤其是对于小型本地模型而言。
常见的解决方案是将工作分解为更小的步骤,创建多智能体系统,而不是依赖一个智能体完成所有任务。
要跟随本教程,你需要在机器上安装 Ollama 并拥有一个免费的 Ollama 账户。本教程适用于 macOS、Windows 和 Linux。我使用的是配备 32 GB 内存的 MacBook Pro,但你可以通过从 Ollama 选择更小的 Qwen 模型,在内存更小的机器上运行此教程。
什么是多智能体系统?
在本教程中,多智能体系统简单来说就是一组协作完成更大任务的人工智能智能体。
每个智能体具有:
- 特定的责任
- 自己的提示和指令
- 在工作流中定义的位置
与其要求一个模型解决整个问题,不如将工作负载分解为更小、更集中的任务。由于每个智能体的目标更狭窄,其提示通常更简单,也更容易让模型保持一致性。
本教程有意保持系统简单。没有记忆、工具调用或复杂模式。相反,重点放在一个简单的用例上,以展示多智能体 AI 系统的构建模块。
何时使用多智能体系统
当任务自然地分解为不同的步骤或角色(如规划、写作、审查或使用不同的专用提示处理工作流的不同部分)时,多智能体系统是有意义的。如果单个智能体可以通过清晰的提示可靠地处理任务并生成输出,那么添加更多智能体只会引入额外的复杂性、延迟和开销。
一般来说,当职责分离能明显改善结果时使用多个智能体,而当任务仍可作为一次连贯的交互处理时使用单个智能体。
动机与架构
在本教程中,我们将使用小型 Qwen 本地 LLM 和 Ollama 构建一个简单的 AI 驱动学习指南生成器。给定提示中的主题,系统会生成包含大纲、笔记和复习问题的结构化学习指南。单个智能体提示如下:
为该主题创建一个适合初学者的学习指南:{topic}
输出必须包含以下部分:
1. 大纲
- 将主题分为3个简短的学习部分
2. 笔记
- 为每个部分编写简短清晰的学习笔记
- 保持解释简洁易懂
3. 复习问题
- 根据笔记编写3个简短的复习问题
以整洁的Markdown格式返回结果。单个代理需要同时执行多项任务来根据上述提示生成学习指南。这对小型本地模型来说一次处理太多任务,输出质量可能不会最佳。
多代理系统通过将单个提示拆分为三个专用代理来提供帮助。这使小型模型更容易处理任务。工作流中的代理包括:
- 规划者:将主题拆分为逻辑部分。
- 教师:为每个部分编写简洁的学习笔记。
- 测验编写者:生成复习问题以巩固材料。
此工作流可以通过两种方式实现。在简单的Python版本中,Python代码协调步骤以调用代理。
在LangGraph版本中,相同的流程通过节点、边和共享状态来表达。代理仍然相同,LangGraph将工作流建模为图。每个节点执行一个任务,更新共享状态,并将该状态传递给下一个节点以获得最终输出。
第1步:安装Ollama和依赖项
安装Ollama并拉取模型:
ollama pull qwen3.5:4b设置Python环境:
python3 -m venv venv
source venv/bin/activate
pip install langchain-ollama langgraph第2步:简单Python版本
纯Python版本使用三个专注的LLM调用或代理(规划者、教师和测验编写者),由常规Python代码协调。
ask()函数将系统提示和用户输入发送到模型并返回响应文本。run_agent()函数包装该调用并打印每个步骤所需的时间。
然后代码定义了三个具有特定提示的小代理:
- planner_agent()为该主题创建一个三部分大纲。
- teacher_agent()将该大纲转换为简短的初学者友好笔记。
- quiz_agent()从笔记中创建3个复习问题。
build_study_guide()函数按顺序运行这三个代理,将每个输出传递给下一步。
将此保存为study_guide_v1.py。
import time
from langchain_ollama import ChatOllama
# 三个代理使用的本地Ollama模型。
MODEL = ChatOllama(model="qwen3.5:4b", temperature=0)
def ask(system: str, user: str) -> str:
"""使用系统提示和用户输入运行一次LLM调用。"""
response = MODEL.invoke([
{"role": "system", "content": system},
{"role": "user", "content": user},
])
return response.content
def run_agent(name: str, system: str, user: str) -> str:
"""记录每个代理耗时的辅助函数。"""
print(f"调用代理 {name}...")
start = time.time()
result = ask(system, user)
print(f"完成 {name} 耗时 {time.time() - start:.1f}s")
return result
# 代理1:创建简要大纲
def planner_agent(topic: str) -> str:
return run_agent(
"planner_agent",
"将此主题拆分为3个简短的学习部分。",
topic,
)
Agent 2:根据大纲生成笔记
def teacher_agent(topic: str, outline: str) -> str: return run_agent( "teacher_agent", "使用大纲编写简明易懂的入门笔记。保持简洁。", f"Topic: {topic}\n\nOutline:\n{outline}", )
Agent 3:根据笔记生成复习题
def quiz_agent(topic: str, notes: str) -> str: return run_agent( "quiz_agent", "根据笔记编写3个简短的复习问题。", f"Topic: {topic}\n\nNotes:\n{notes}", )
def build_study_guide(topic: str) -> str: """按顺序运行所有三个代理并合并输出结果。""" outline = planner_agent(topic) notes = teacher_agent(topic, outline) quiz = quiz_agent(topic, notes)
return ( f"# 学习指南:{topic}\n\n" f"## 大纲\n{outline}\n\n" f"## 笔记\n{notes}\n\n" f"## 复习问题\n{quiz}\n" )
if __name__ == "__main__": print("预热模型...") MODEL.invoke("Say ready.") print("模型已就绪。\n")
topic = input("输入学习主题: ").strip() print("\n" + build_study_guide(topic))
运行方式:
python study_guide_v1.py
这已经是一个功能完整的多代理系统。每个代理只是一个聚焦的LLM调用。Python负责协调流程且不需要任何框架。对于这种固定顺序的工作流,纯Python通常是最佳起点。
## 第三步:使用节点和边的LangGraph版本
现在让我们用LangGraph构建相同的学习笔记生成器。角色保持不变,但LangGraph提供了编排功能:
- 每个专家变为一个节点
- 共享字典变为图状态
- 执行顺序变为边
不再需要手动控制函数依次调用代理,而是将流程定义为图:START -> planner -> teacher -> quiz -> END
每个节点从状态中读取数据,只返回它更新的字段。
保存为study_guide_v2.py:
from typing import TypedDict import time
from langchain_ollama import ChatOllama from langgraph.graph import StateGraph, START, END
所有节点使用的本地Ollama模型。
MODEL = ChatOllama(model="qwen3.5:4b", temperature=0)
节点间传递的共享状态。
class StudyState(TypedDict): topic: str outline: str notes: str quiz: str
def ask(system: str, user: str) -> str: response = MODEL.invoke([ {"role": "system", "content": system}, {"role": "user", "content": user}, ]) return response.content
def run_node(name: str, system: str, user: str) -> str: print(f"调用节点 {name}. ..") start = time.time() result = ask(system, user) print(f"{name} 调用耗时 {time.time() - start:.1f}s") return result
节点1:创建大纲
def planner(state: StudyState) -> dict: return { "outline": run_node( "planner", "将该主题拆分为3个简短的学习部分。", state["topic"], ) }
节点2:根据大纲生成笔记
def teacher(state: StudyState) -> dict: return { "notes": run_node( "teacher", "使用大纲编写简明易懂的入门笔记。保持简洁。", f"Topic: {state['topic']}\n\nOutline:\n{state['outline']}", ) }
节点 3:根据笔记编写复习问题
def quiz_writer(state: StudyState) -> dict: return { "quiz": run_node( "quiz_writer", "根据笔记编写3个简短的复习问题。", f"主题: {state['topic']}\n\n笔记:\n{state['notes']}", ) }
def build_graph(): graph = StateGraph(StudyState)
添加节点
graph.add_node("planner", planner) graph.add_node("teacher", teacher) graph.add_node("quiz_writer", quiz_writer)
定义执行顺序
graph.add_edge(START, "planner") graph.add_edge("planner", "teacher") graph.add_edge("teacher", "quiz_writer") graph.add_edge("quiz_writer", END)
return graph.compile()
if __name__ == "__main__": print("预热模型...") MODEL.invoke("Say ready.") print("模型已就绪.\n")
app = build_graph() topic = input("输入学习主题: ").strip()
result = app.invoke({ "topic": topic, "outline": "", "notes": "", "quiz": "", })
print( f"\n# 学习指南: {topic}\n\n" f"## 大纲\n{result['outline']}\n\n" f"## 笔记\n{result['notes']}\n\n" f"## 复习问题\n{result['quiz']}\n" )
python study_guide_v2.py
简单Python版本和LangGraph版本的代码本质上都在做同一件事:协调多个由LLM驱动的步骤来解决更复杂的任务。
简单Python版本适合轻量级的流程编排。如果工作流简单且线性,普通Python通常是更实际的选择。
当工作流需要共享状态、分支、循环或更复杂的代理协调时,LangGraph会是更好的选择。
## 示例输出
对于以下输入:
输入学习主题: 牛顿运动定律
两个版本都会生成相同类型输出:包含大纲、笔记和复习问题的简短学习指南。
典型结果可能如下:
$python study_guide_v2.py
预热模型... 模型已就绪.
输入学习主题: 牛顿运动定律 调用planner节点... planner节点执行耗时30.2秒 调用teacher节点... teacher节点执行耗时33.0秒 调用quiz_writer节点... quiz_writer节点执行耗时40.0秒
学习指南: 牛顿运动定律
大纲
第一部分:惯性定律
- 定义:静止的物体保持静止状态,运动的物体以相同速度和方向持续运动,除非受到不平衡力的作用。
- 关键概念:惯性是物体抵抗运动状态改变的性质。
第二部分:加速度定律
- 定义:物体的加速度与作用力成正比,与质量成反比。
- 公式:$F = ma$(力=质量×加速度)。
第三部分:作用与反作用定律
- 定义:每个作用力都有一个大小相等、方向相反的反作用力。
- 关键概念:力总是成对出现;如果物体A对物体B施加力,物体B会对物体A施加等量反方向的力。
笔记
第一部分:惯性定律
- 定义:物体保持原有状态。静止则保持静止,运动则保持匀速直线运动。
- 关键概念:惯性是物体抵抗运动状态改变的性质。
/think
第2节:加速度定律
- 定义: 力会导致加速度。推得越用力,物体加速越快。物体质量越大,越难推动。
- 公式: $F = ma$(力 = 质量 × 加速度)。
第3节:作用与反作用定律
- 定义: 力总是成对出现。当一个物体推动另一个物体时,第二个物体会产生反向的推力。
- 关键概念: 作用力与反作用力总是大小相等、方向相反。
复习问题
- 物体抵抗运动状态改变的性质称为什么?
- 加速度定律的公式是什么?
- 根据作用与反作用定律,作用力与反作用力如何比较?
这两种架构解决相同的问题,但一个由简单的 Python 代码协调,另一个通过显式图结构实现。
## 常见多智能体模式
本教程的示例是一个顺序流水线。一个专家按固定顺序将任务交给下一个专家。这是最简单的多智能体模式,但并非唯一的模式。
以下几种模式值得关注:
- **并行专家:** 多个智能体独立处理相同输入,输出结果合并。
- **协调器-子代理:** 顶层智能体拆分任务、分配工作并整合结果。
- **监督者/路由器:** 路由智能体决定哪个专家负责处理请求。
- **人机协作:** 智能体起草工作内容,但需人工审核或批准后才能继续。
- **评审/优化循环:** 一个智能体生成输出,另一个检查或改进输出。
以下信息图展示了这些模式的视觉化表示:
## 结论
在本教程中,我们使用 Python 分别通过和不通过 LangGraph 框架构建了一个简单的多智能体 AI 系统。
接下来可以尝试扩展示例。添加一个第四节点,用更简单的语言重写笔记。添加一个评审步骤,检查测验是否与笔记匹配。或者分支图结构,使初级主题获得更简明的解释,而高级主题则更深入。尽情探索吧!
如果你喜欢本教程,可以在我的博客(近期文章包括系统设计论文系列)、我的个人网站 和 LinkedIn 上查看我的更多作品。
https://darshshah.org/
如果本文对你有帮助,请分享它。
免费学习编程。freeCodeCamp 的开源课程已帮助超过 40,000 人成为开发者。立即开始
ADVERTISEMENT