读完这篇博客,你将能自己动手搭建一个会计算、会查天气、会统计文本的 AI 智能助手。不需要任何 Agent 开发经验,只需要会 Python 基础。


开篇:ChatGPT 能聊天,但"Agent"能干活

你可能用过 ChatGPT——问它问题,它回答。但你有没有发现一个问题:ChatGPT 不会算数(经常算错)、不知道实时天气不能操作文件

为什么?因为大语言模型(LLM)本质上只是一个"文字接龙机"——它只会一个字一个字地生成文本,没有手脚去执行实际操作

Agent(智能体) 解决了这个问题:

┌──────────────────────────────────────────────────────┐
│                     Agent (智能体)                    │
│                                                      │
│   ┌───────────┐       决策循环        ┌───────────┐  │
│   │    LLM    │ ◄─────────────────► │   Tools   │  │
│   │   (大脑)   │   思考→行动→观察    │   (手脚)   │  │
│   └───────────┘                     └───────────┘  │
│        │                                  │         │
│        ▼                                  ▼         │
│   理解语言、推理                   算数、查天气、调API │
└──────────────────────────────────────────────────────┘

Agent = LLM(大脑)+ Tools(手脚)+ 决策循环

当用户问"北京今天多少度?",Agent 的 LLM 推理出"我需要查天气",然后调用天气工具获取数据,再告诉用户结果。它不是凭空编造——是真的去查了。


一、先认识两个主角:LangChain 和 LangGraph

很多新手会被这两个名字搞晕。其实关系很简单:

🔗 LangChain —— 搭积木

LangChain 让你像串糖葫芦一样把 LLM 操作串起来:

用户输入 → 写提示词 → 调 LLM → 解析结果 → 输出

一条线走到底,顺序执行。适合简单任务,比如"翻译一段文字"。

🕸️ LangGraph —— 画流程图

LangGraph 更进一步——不再是一条直线,而是有循环、有分支的图

          ┌── 需要工具?──是──→ 调工具 ──┐
          │                              │
用户输入 → LLM 思考 ←───── 工具结果 ──────┘
          │
          └── 不需要?───→ 直接回答 → 输出

Agent 的核心就是反复循环:"思考→需要工具→调用→拿到结果→再思考→..."。这种循环正是 LangGraph 擅长的。

🎯 一句话区分

LangChain 是链——从头跑到尾。LangGraph 是图——可以循环、分叉、暂停。LangGraph 更高级。


二、项目实战:搭建你的第一个 Agent

项目结构

python/
├── .env.example       # API Key 配置模板
├── requirements.txt   # 依赖
├── tools.py           # 自定义工具(Agent 的手)
├── agent_demo.py      # 主程序
└── README.md          # 说明文档

Step 1:安装依赖

cd python
pip install -r requirements.txt

requirements.txt 内容:

langchain>=0.3.0
langchain-openai>=0.2.0
langchain-community>=0.3.0
langgraph>=0.2.0
python-dotenv>=1.0.0

Step 2:配置 API Key

复制 .env.example.env,填入你的 Key:

cp .env.example .env

推荐用 DeepSeek(性价比高,国内即用):

DEEPSEEK_API_KEY=sk-你的key
DEEPSEEK_BASE_URL=https://api.deepseek.com/v1
LLM_PROVIDER=deepseek

🔗 获取 Key:DeepSeek

Step 3:定义工具(Agent 的手)

# tools.py
from langchain_core.tools import tool
import math
from datetime import datetime

@tool
def calculator(expression: str) -> str:
    """执行数学表达式计算。支持 + - * / sqrt 等。"""
    try:
        allowed = {k: v for k, v in math.__dict__.items()
                   if not k.startswith("__")}
        result = eval(expression, {"__builtins__": {}}, allowed)
        return f"计算结果: {result}"
    except Exception as e:
        return f"计算出错: {e}"

@tool
def get_current_datetime(format_str: str = "%Y-%m-%d %H:%M:%S") -> str:
    """获取当前日期和时间。"""
    return f"当前时间: {datetime.now().strftime(format_str)}"

@tool
def text_stats(text: str) -> str:
    """统计文本的字数、字符数、行数。"""
    lines = text.split("\n")
    words = text.split()
    return f"字符数: {len(text)}, 字数: {len(words)}, 行数: {len(lines)}"

@tool
def get_weather(city: str) -> str:
    """查询指定城市的天气(模拟数据,仅供学习)。"""
    mock_db = {
        "北京": "☀️ 晴天, 32°C",
        "上海": "🌧️ 小雨, 28°C",
        "深圳": "⛅ 多云, 30°C",
    }
    return mock_db.get(city, f"暂无 {city} 的天气数据")

# ⭐ 汇总所有工具——Agent 只会用这个列表里的工具
ALL_TOOLS = [calculator, get_current_datetime, text_stats, get_weather]

关键点:函数的 docstring(三引号里的描述)就是告诉 LLM "这个工具能干什么"。LLM 靠读这段文字来决定什么时候用哪个工具。

Step 4:创建 Agent(两种方式)

方式一:LangChain 经典模式(推荐新手)
from langchain.agents import AgentExecutor, create_tool_calling_agent
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder

# ① 写提示词
prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个乐于助人的 AI 助手。回答请用中文。"),
    MessagesPlaceholder(variable_name="chat_history"),      # 对话历史
    ("human", "{input}"),                                    # 用户输入
    MessagesPlaceholder(variable_name="agent_scratchpad"),   # 思考过程
])

# ② 创建 agent
agent = create_tool_calling_agent(llm=llm, tools=ALL_TOOLS, prompt=prompt)

# ③ 包装成执行器(负责"思考→行动→观察"的循环)
agent_executor = AgentExecutor(
    agent=agent,
    tools=ALL_TOOLS,
    verbose=True,              # 打印内部思考过程(建议新手开启)
    max_iterations=10,         # 最多调 10 轮工具,防止死循环
)
方式二:LangGraph 现代模式(高级)
from langgraph.prebuilt import create_react_agent

agent = create_react_agent(
    model=llm,
    tools=ALL_TOOLS,
    state_modifier=SystemMessage(content="你是一个乐于助人的 AI 助手。"),
)

一行就搞定!循环、容错、历史管理全自动。

Step 5:运行

python agent_demo.py

看到的菜单:

╔══════════════════════════════════════════════════════════════╗
║          🚀 LangChain Agent 入门 Demo                       ║
║                                                              ║
║  请选择运行模式:                                              ║
║    1. 交互模式 - 经典 Tool Calling Agent (推荐初学者)         ║
║    2. 交互模式 - 现代 LangGraph ReAct Agent                  ║
║    3. 一次性示例 - 经典模式                                  ║
║    4. 一次性示例 - ReAct 模式                                ║
║    5. 调试模式 - 查看 Agent 内部思考过程                     ║
║    0. 退出                                                   ║
╚══════════════════════════════════════════════════════════════╝

1 就能在终端跟 Agent 聊天了:

👤 你: 北京天气怎么样?

🔍 Agent 思考中...
----------------------------------------
> 进入新的 AgentExecutor 链...
> 思考:用户问北京天气,我需要调用 get_weather 工具
> 调用工具: get_weather
  参数: {"city": "北京"}
> 工具返回: 北京 天气: ☀️ 晴天, 32°C
> 思考:我已经拿到天气数据,可以回答用户了

🤖 Agent: 北京今天是晴天,气温 32°C,适合出门但注意防晒哦!

三、两种方式的代码对比

方式一:LangChain 经典 方式二:LangGraph 现代
创建 agent 3 步(提示词→agent→executor) 1 步(create_react_agent
提示词 手动写 3 个占位槽 直接传 SystemMessage
对话历史 自己维护 list,每轮手动 append thread_id,自动管理
调用方式 invoke({"input": ..., "chat_history": ...}) invoke({"messages": [...]}, config=...)
取结果 result["output"] result["messages"][-1].content
灵活性 低——黑盒循环 高——可插节点、加分叉
代码量
适合 学习原理 实际干活

四、记忆(Memory)—— Agent 怎么记住聊过什么

想象你跟一个人聊天,每一句话他都会忘记你上一句说了什么——这聊不下去。Agent 也一样,需要记忆来支持多轮对话。

LangChain 经典模式:自己手动管,存内存

在方式一中,"记忆"就是一个普通的 Python 列表,存在进程内存里:

# 就是一个 list,你手动维护
chat_history = []

# 每轮对话结束后,自己往里塞
chat_history.append(HumanMessage(content=user_input))
chat_history.append(AIMessage(content=result["output"]))

# 下一轮调用时,手动传进去
result = agent_executor.invoke({
    "input": user_input,
    "chat_history": chat_history,  # ← 不传就失忆
})

特点

  • 存在进程内存里,程序一关就没了

  • 你得手动 append、手动传,忘了传就"失忆"

  • 只有一个全局列表,没法同时服务多个用户

LangGraph 默认:自动管,但也存在内存

方式二(LangGraph)默认也是存内存,但管理是全自动的——你不需要手动维护列表:

config = {"configurable": {"thread_id": "demo-session"}}
#                          ↑ 靠这个 ID 自动追踪上下文

result = agent.invoke(
    {"messages": [HumanMessage(content=user_input)]},
    config=config,  # ← 自动读写历史,不用你管
)

但注意:默认情况下,重启程序记忆还是丢了——因为它也是纯内存。

LangGraph + Checkpointer:一行代码,记忆永久保存

LangGraph 真正强的地方在于可以挂载持久化存储,改一行代码就行:

from langgraph.checkpoint.memory import MemorySaver       # 内存(重启就丢)
from langgraph.checkpoint.sqlite import SqliteSaver       # SQLite(存硬盘,重启还在)

# 创建 agent 时挂上 checkpointer
agent = create_react_agent(
    model=llm,
    tools=tools,
    checkpointer=SqliteSaver.from_conn_string("memory.db"),  # ← 持久化!
)
# 重启后,同一个 thread_id 的历史还在!

不同 thread_id 的记忆互相隔离,天然支持多用户:

# 用户 A 的记忆
agent.invoke({"messages": [HumanMessage("我叫小明")]},
             config={"configurable": {"thread_id": "user-a"}})

# 用户 B 的记忆(完全独立)
agent.invoke({"messages": [HumanMessage("我叫小红")]},
             config={"configurable": {"thread_id": "user-b"}})

一张表看清三种记忆方案

LangChain 经典 LangGraph 默认 LangGraph + Checkpointer
存储位置 内存 list 内存 内存 / SQLite / Postgres
谁管理 你手动 append 自动 自动
重启后还在? ❌ 丢 ❌ 丢 ✅ 在(用 SQLite 等)
多用户隔离 ❌ 做不到 ✅ 靠 thread_id ✅ 靠 thread_id
适合场景 学习、单次对话 学习、单次会话 生产环境

一句话:LangChain 经典是你拿个 list 自己记,程序关了就忘;LangGraph 自带记忆框架,默认也是内存,但改一行代码就能把记忆写到硬盘上,永久保存。


五、Agent 决策过程详解

当你问"3 的平方根加 5 等于多少?",Agent 内部发生了什么:

Step 1 — LLM 分析
  "用户问的是数学题,我需要用 calculator 工具来计算"

Step 2 — 工具调用
  → calculator("sqrt(3) + 5")

Step 3 — 工具返回
  ← "计算结果: 6.732050807568877"

Step 4 — LLM 综合
  "结果是 6.732...,我告诉用户"

Step 5 — 输出 ✅
  "3 的平方根加 5 的结果约等于 6.732"

整个过程并不神秘——就是一个反复的"思考→行动"循环,直到 LLM 觉得能回答了为止。


六、进阶:如何扩展你的 Agent

添加新工具,只需 3 步

# ① 在 tools.py 里定义
@tool
def translate(text: str, target_lang: str = "中文") -> str:
    """将文本翻译成目标语言"""
    # 你的翻译逻辑
    return translated_text

# ② 注册到工具列表
ALL_TOOLS.append(translate)

Agent 自动就能用新工具了,不用改 Agent 本身的任何代码

还有现成的社区工具

from langchain_community.tools import DuckDuckGoSearchRun  # 网络搜索
from langchain_community.tools import WikipediaQueryRun    # 维基百科

七、常见问题

Q:API Key 要钱吗? DeepSeek 新用户有免费额度,国内可以直接用,不用担心。

Q:能在 PyCharm 里跑吗? 完全可以。PyCharm 直接打开项目文件夹,装好依赖后右键 agent_demo.py → Run,在 Run 窗口就能交互。

Q:verbose=True 输出太多怎么办? 改成 verbose=False 就行。但建议新手先开着,能看到 Agent 的"思考过程"非常有助于理解原理。

Q:Agent 调工具总出错怎么办? 每个工具函数里用 try/except 包住,返回友好的错误信息。Agent 会读错误信息然后自己调整重试。


八、学习路线图

✅ 第一步:理解 Agent = LLM + Tools + 循环 (你现在在这里)
✅ 第二步:跑通 Demo,跟 Agent 聊几句
📖 第三步:自己写一个新工具加进去
📖 第四步:改系统提示词,换 Agent 的"人设"
📖 第五步:用 LangGraph 构建更复杂的工作流
📖 第六步:学 RAG(检索增强生成)——让 Agent 能读文件
📖 第七步:多 Agent 协作

九、常见面试题

如果你去面试 AI Agent 开发相关的岗位,下面这些题大概率会碰到。

Q1:什么是 Agent?它和直接调用 LLM 有什么区别?

回答

Agent = LLM + Tools + 决策循环。直接调用 LLM 只能做文本生成——你问它"今天天气怎么样",它只能编一个答案。Agent 则会在 LLM 推理出"我需要查天气"之后,真的去调用天气 API 获取实时数据,再综合返回。

核心区别:LLM 只有脑子,Agent 有脑子 + 手脚


Q2:LangChain 和 LangGraph 是什么关系?什么时候用哪个?

回答

都来自同一家公司(LangChain Inc),定位不同:

  • LangChain:链式调用框架。适合"一次性"任务(翻译→摘要→分类),流程是线性的。

  • LangGraph:图式状态机框架。适合需要循环、分支、条件判断的任务(如 Agent 的"思考→行动→观察"循环)。

简单项目用 LangChain 就够了;需要复杂工作流、多步推理、人机交互时用 LangGraph。


Q3:Agent 怎么知道该调用哪个工具?

回答

靠工具的描述(description)。当你用 @tool 装饰器定义工具时,函数的 docstring 会被当作工具的"说明书"注入到 LLM 的提示词里。LLM 读取所有工具的说明书,根据用户的问题判断该用哪个、参数填什么。

例如用户问"北京天气?",LLM 看到 get_weather 的描述是"查询指定城市的天气",就决定调用它,并填入参数 city="北京"


Q4:Tool Calling Agent 和 ReAct Agent 有什么区别?

回答

Tool Calling ReAct
决策方式 LLM 原生 function calling 强制 LLM 按"思考→行动→观察"模板输出
提示词 不需要特殊格式 需要 ReAct 格式的提示词
灵活性 依赖模型能力 格式固定,兼容性更好
底层实现 create_tool_calling_agent (LangChain) create_react_agent (LangGraph)

Tool Calling 依赖模型自身支持 function calling(如 GPT-4、DeepSeek),更简洁。ReAct 模式通过提示词工程强制推理链,对模型要求更低,且过程可读性更强。


Q5:Agent 的记忆是怎么实现的?如何持久化?

回答

分三层:

  1. 没有记忆:每次调用都是独立的,Agent 不知道上一轮聊了什么

  2. 内存记忆:用 Python list 或 LangGraph 默认的 MemorySaver,存进程内存里。程序重启就丢

  3. 持久化记忆:LangGraph 挂载 SqliteSaver / PostgresSaver 等 Checkpointer,历史存硬盘,重启不丢。通过 thread_id 隔离不同用户

# 持久化记忆示例
from langgraph.checkpoint.sqlite import SqliteSaver

agent = create_react_agent(
    model=llm, tools=tools,
    checkpointer=SqliteSaver.from_conn_string("memory.db"),
)

Q6:Agent 陷入死循环怎么办?有哪些防护手段?

回答

三种防护:

  1. max_iterations:LangChain 的 AgentExecutor 可以设最大迭代次数,超过就强制停止

  2. 超时控制:给整个 invoke 加超时,避免无限等待

  3. 工具设计兜底:工具函数内部做好异常捕获,确保每次都返回有效结果(哪怕是报错信息),让 Agent 能继续往下走而不是卡住

AgentExecutor(
    agent=agent, tools=tools,
    max_iterations=10,  # ← 最多调 10 轮工具
)

LangGraph 内置了递归次数限制,默认 25 步。


Q7:什么是 RAG?它和 Agent 怎么结合?

回答

RAG(检索增强生成) = 先从知识库检索相关内容,再把检索结果和用户问题一起给 LLM,让 LLM 基于真实资料回答。

和 Agent 结合后,Agent 不再是"凭空回答"或"只能调计算/天气工具",而是多了一个能查资料的工具。流程变成:

用户提问 → Agent 分析 → 需要查资料?→ 调用检索工具查知识库
                      → 需要计算?  → 调用计算器
                      → 不需要工具?→ 直接回答

这被称为 RAG Agent,能处理私域知识 + 实时操作。


Q8:@tool 装饰器背后做了什么?

回答

@tool 装饰器做了三件事:

  1. 读取函数的 docstring,作为工具的描述信息

  2. 读取函数的参数签名,自动生成 JSON Schema,告诉 LLM 工具需要哪些参数、什么类型

  3. 包装成 BaseTool 子类,赋予 invoke() / ainvoke() 等 Agent 能调用的接口

本质上就是把一个普通 Python 函数,变成 LLM 能理解和调用的标准化工具。

@tool
def calculator(expression: str) -> str:
    """执行数学表达式计算。"""
    ...

# 等价于手动写:
class CalculatorTool(BaseTool):
    name = "calculator"
    description = "执行数学表达式计算。"
    args_schema = {"expression": {"type": "string"}}

    def _run(self, expression: str) -> str:
        ...

Q9:temperature 参数对 Agent 有什么影响?应该设多少?

回答

  • temperature = 0:LLM 输出完全确定性。同一输入永远同一输出。Agent 场景推荐设为 0,因为 Agent 需要稳定地判断"用哪个工具、传什么参数",不能发挥创意

  • temperature = 0.7~1.0:输出变随机。适合写作、头脑风暴等创意任务,但 Agent 可能"想歪"——该调计算器时却自己瞎编一个数

面试标准答案:Agent / 工具调用场景设 0 或接近 0;创意生成类场景设 0.7 以上。


Q10:如果要做一个能操作数据库的 Agent,你会怎么设计?

回答

  1. 定义数据库工具:用 @tool 包装 SQL 查询函数,描述清楚工具能查什么表、返回什么字段

  2. 安全第一:工具内部做 SQL 注入防护(参数化查询)、限制只读操作(SELECT 不放行 DROP/DELETE)

  3. 结果截断:查询结果太多时截断,避免撑爆 LLM 上下文窗口

  4. 用 LangGraph:复杂多步查询(先查A表 → 根据结果查B表)用 LangGraph 的图和 checkpointer 管理状态

  5. 记忆持久化:挂 SqliteSaver/PostgresSaver,保证多轮分析不丢上下文

@tool
def query_database(sql: str) -> str:
    """执行 SELECT 查询。可用表: users(id, name), orders(id, user_id, amount)"""
    # 安全检查:只允许 SELECT
    if not sql.strip().upper().startswith("SELECT"):
        return "错误:只允许 SELECT 查询"
    # 参数化查询、结果截断...
    cursor.execute(sql)
    return str(cursor.fetchmany(100))  # 最多返回 100 行

写在最后

Agent 开发听起来高大上,但核心思想非常简单:

  1. LLM 负责理解和推理

  2. Tools 负责干活

  3. 一个循环把它们串起来

LangChain 帮你快速上手,LangGraph 帮你走得更远。希望这篇博客帮你迈出了第一步。

📂 完整代码在文中的 python/ 目录下,复制就能跑。

🔗 资源链接:


写于 2026 年 7 月,一个还不错的开始。

Logo

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

更多推荐