从零开始掌握AI:LLM、RAG到Agent的完整学习路线图
引言:为什么你需要这份路线图?
2025年被称为"Agent元年",AI正从"聊天工具"进化为"数字员工"。但面对LLM、RAG、Agent等概念,很多初学者感到迷茫:
- ChatGPT和Claude有什么区别?
- RAG听起来很酷,但具体怎么用?
- 网上说的"智能体"到底是什么?
- 我想自己开发AI应用,该从哪里入手?
作为从小白一路走来的学习者,我整理了这份四阶段学习路线图 。这不是罗列概念,而是可执行的实践指南,每个阶段都有具体的工具推荐和操作步骤。建议收藏后按阶段实践,避免信息过载。
第1阶段:理解基础------厘清核心概念
在动手之前,我们必须建立正确的认知框架。很多初学者跳过这一步,导致后续学习碎片化。
1.1 LLM(大语言模型):AI的"大脑"
定义 :LLM是通过海量文本训练的神经网络,能理解和生成人类语言。它是所有AI应用的基础能力层。
核心特点:
| 特性 | 说明 | 影响 |
|---|---|---|
| 预训练知识 | 学习过互联网上的公开文本 | 知识广博但可能过时 |
| 上下文窗口 | 一次能处理的文本长度(4K-200K tokens) | 决定能处理多复杂的任务 |
| 幻觉倾向 | 会自信地编造不存在的信息 | 关键场景必须验证 |
| 指令遵循 | 能理解并执行人类指令 | 质量取决于Prompt设计 |
主流模型对比:
| 模型 | 开发方 | 特点 | 适用场景 |
|---|---|---|---|
| GPT-4o | OpenAI | 多模态强、工具调用成熟 | 通用任务、商业应用 |
| Claude 3.5 Sonnet | Anthropic | 代码能力强、长上下文 | 编程、文档分析 |
| Gemini Pro | 免费额度大、多语言好 | 预算有限、国际化 | |
| DeepSeek V3 | DeepSeek | 开源、性价比高 | 私有化部署、成本控制 |
**关键认知:**LLM本身只有"说话"能力,没有"行动"能力。它就像一位博学但被困在房间里的教授,能回答你的问题,但无法打开电脑查资料、无法帮你订外卖。
1.2 RAG(检索增强生成):给LLM配"参考书"
一句话定义:RAG让AI在回答问题前先查资料 ,基于检索到的证据生成回答,而非仅凭记忆。
为什么必须学RAG?
想象两个场景:
场景A:普通LLM(闭卷考试)
你问:"我公司2024年Q3的销售额是多少?"
LLM回答:"根据一般行业趋势,Q3销售额通常..."(开始胡编)
场景B:RAG增强(开卷考试)
AI先到你的销售数据库检索 → 找到真实数据 → 基于证据回答:"根据销售系统记录,2024年Q3销售额为¥1,200万,环比增长15%..."
RAG工作流程详解:
css
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 1.文档加载 │ → → │ 2.文本分块 │ → → │ 3.向量化存储 │ → → │ 4.检索生成 │
│ (PDF/网页等)│ │ (Chunking) │ │ (Vector DB) │ │ (Query+Context)│
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
↓
┌─────────────┐
│ 5.LLM生成答案 │
│ (带引用溯源) │
└─────────────┘
步骤拆解:
文档加载: 支持PDF、Word、网页、数据库等多种格式
文本分块(Chunking): 长文档切成小片段(通常500-1000字),便于精准检索
向量化(Embedding): 用模型(如OpenAI的text-embedding-3)将文本转成高维向量
向量存储: 存入专用数据库(Pinecone、Milvus、Chroma等)
检索生成: 用户提问时,先找最相似的文本片段,再让LLM基于这些片段回答
RAG vs 微调(Fine-tuning):
| 方案 | 成本 | 时效性 | 数据隐私 | 适合场景 |
|---|---|---|---|---|
| RAG | 低(无需训练) | 实时更新 | 可控(本地部署) | 频繁更新的知识库 |
| 微调 | 高(需GPU训练) | 训练后固定 | 需上传数据 | 固定格式输出、风格模仿 |
结论: 对于大多数企业应用,RAG是首选方案。
1.3 Agent(智能体):给LLM配"手脚"
一句话定义: Agent是能自主感知环境、决策并执行动作 的AI系统。它不只是回答问题,而是完成任务 。
Agent的核心特征(与简单LLM的区别):
| 能力 | 简单LLM | Agent |
|---|---|---|
| 交互方式 | 单轮/多轮对话 | 持续迭代直到目标达成 |
| 工具使用 | 无 | 主动调用搜索、代码执行、API等 |
| 记忆能力 | 会话级 | 长期记忆、可跨会话学习 |
| 规划能力 | 无 | 能分解复杂任务为子步骤 |
| 行动闭环 | 只给建议 | 执行→观察结果→调整→再执行 |
Agent架构解析(ReAct模式):
Thought(思考)→ Action(行动)→ Observation(观察)→ ... → Finish(完成)
实例:让Agent"调研新能源汽车市场并写报告"
css
Thought: 我需要先了解2024年新能源汽车销量数据
Action: 调用搜索工具,查询"2024年中国新能源汽车销量统计"
Observation: 获得销量数据、品牌排名、增长率等信息
Thought: 数据有了,但我需要分析主要品牌的竞争格局
Action: 调用搜索工具,查询"比亚迪vs特斯拉2024年市场份额对比"
Observation: 获得对比分析文章
Thought: 现在我有足够信息,需要生成报告
Action: 调用文档生成工具,整合数据并格式化输出
Observation: 报告已生成,保存为PDF
Finish: 任务完成,报告位于/output/新能源汽车市场分析报告.pdf
关键认知: Agent = LLM(大脑)+ 工具(手脚)+ 记忆(经验)+ 规划(策略)
1.4 阶段1总结:三者关系图
css
┌─────────────────────────────────────────────┐
│ 应用层:AI产品 │
│ (ChatGPT、Perplexity、OpenCode等) │
├─────────────────────────────────────────────┤
│ 架构层:Agent(智能体) │
│ ┌─────────────────────────────────────┐ │
│ │ 核心组件: │ │
│ │ • Planning(规划):分解复杂任务 │ │
│ │ • Memory(记忆):长期与短期记忆 │ │
│ │ • Tools(工具):扩展能力边界 │ │
│ │ • RAG(检索):获取实时准确知识 ← ────┼───┐
│ └─────────────────────────────────────┘ │ │
├─────────────────────────────────────────────┤ │
│ 能力层:LLM(大语言模型) │ │
│ (GPT-4、Claude、Gemini等提供基础理解) │ │
└─────────────────────────────────────────────┘ │
↑ │
└────────────────────────────────────────┘
RAG作为知识增强模块
服务于Agent和直接问答场景
第2阶段:动手体验------建立直观认知
理解概念后,立即动手体验。这一阶段的目标是:用真实产品感受技术差异,建立直觉。
2.1 体验基础对话:ChatGPT vs Claude
为什么要对比 ? 不同模型的"性格"和能力侧重不同,了解差异才能选对工具。
实践任务清单:
任务1:开放式创意写作
Prompt: "写一个关于AI觉醒的科幻短篇开头,300字,要有悬念"
观察维度:
ChatGPT-4o:结构完整,但可能偏"标准答案"
Claude 3.5 Sonnet:文笔更细腻,角色心理描写更生动
任务2:逻辑推理挑战
Prompt: "一个农场有鸡和兔,头共35个,脚共94只。鸡兔各几只?请用两种方法解答,并解释思路"
观察维度:
- 是否准确理解题意
- 解题步骤是否清晰
- 是否能提供多种解法(方程法、假设法)
任务3:长文本处理(测试上下文窗口)
操作步骤:
- 找一篇2万字的技术文档(如某论文PDF)
- 分别上传到ChatGPT和Claude(Claude支持更长上下文)
- 提问:"总结第三部分的核心观点,并列出作者使用的三个实验方法"
关键发现 :Claude在长文本中的"记忆力"明显更强,不容易"遗忘"前文内容。
阶段2.1小结: - ChatGPT:工具调用能力强,适合需要插件/自动化的场景
- Claude:代码和长文本处理更优,适合技术文档分析
- 建议:两个都用,根据任务选择
2.2 体验RAG:Perplexity的深度使用
Perplexity 是RAG技术的最佳展示产品,它会实时搜索网络 并标注信息来源。
实践任务清单:
任务1:观察引用机制
**操作:**搜索"2025年最新的大模型发展趋势"
观察要点:
- 回答中的每个事实后都有[1] [2]等上标
- 点击上标可查看原始网页来源
- 底部有完整的参考链接列表
**思考:**这就是RAG的"溯源性"------答案不是瞎编的,有明确出处。
任务2:对比时效性
**操作:**问"昨天美股收盘情况"(假设今天是2026年2月5日)
观察:
- ChatGPT(知识截止2024年4月):"我无法获取实时股市数据..."
- Perplexity:实时搜索后给出昨日道指、纳指具体涨跌
关键认知 :RAG解决的是知识时效性 问题。
任务3:聚焦模式(Pro功能)
**操作:**点击"Academic"学术模式,搜索"transformer架构的注意力机制原理"
观察:
- 优先检索arXiv论文、学术网站
- 引用格式更规范(作者、年份、期刊)
进阶思考:这就是RAG的数据源可配置性 ------你可以指定它查什么(网页、论文、内部文档)。
任务4:本地RAG体验(选做)
如果你想体验私有RAG,可以尝试:
- 开源方案:AnythingLLM、Ollama + LangChain
- 操作:上传你自己的PDF,然后提问文档内容
阶段2.2小结:
- RAG = LLM + 实时检索 + 来源标注
- 核心价值:准确、时效、可信、可溯源
- 企业应用:将Perplexity的"搜索互联网"换成"搜索企业内部知识库"
2.3 搭建简单"智能体":Coze/扣子实操
**扣子(Coze)**是字节跳动推出的AI Bot开发平台,零代码即可搭建"智能体"。
实践任务:搭建一个"旅游规划助手"
步骤1:创建Bot
- 访问 www.coze.cn
- 点击"创建Bot" → 输入名称"旅行小助手" → 选择图标
- 进入编排页面
步骤2:编写Prompt(人设与回复逻辑)
在"Persona & Prompt"区域输入:
css
# 角色
你是一个专业的旅行规划师,擅长根据用户需求制定详细行程。
## 技能
### 技能1:目的地推荐
- 根据用户偏好(自然风光/历史文化/美食购物)推荐目的地
- 提供3个选项,并说明理由
### 技能2:行程规划
- 制定每日详细行程(上午/下午/晚上)
- 包含交通方式、餐厅推荐、注意事项
- 预算分解(交通/住宿/餐饮/门票)
### 技能3:实用信息
- 提供当地天气、货币、签证、紧急联系方式
## 限制
- 只回答旅游相关问题
- 不确定的信息要说明"建议核实"
- 语气友好、热情、专业
步骤3:添加插件(工具能力)
点击"插件" → 添加以下工具:
- 必应搜索:获取实时旅游信息
- 天气查询:提供目的地天气
- 地图服务:推荐路线
关键认知 :这就是给Agent配置"工具"。当用户问"北京明天天气",Bot会自动调用天气插件。
步骤4:添加知识库(RAG能力)
- 点击"知识" → 创建知识库
- 上传你收集的《2025年全球旅游攻略.pdf》
- 设置回复模式:"优先从知识库回答,不足时补充网络搜索"
**关键认知:**这就是RAG的落地------Bot会先查你的私有文档,再补充公开信息。
步骤5:测试与优化
在右侧预览窗口测试:
- "我想去日本看樱花,什么时候去最好?"
- "帮我规划一个3天2晚的成都美食之旅,预算3000元"
观察Bot如何:
- 调用搜索工具查樱花花期
- 分解任务(目的地→行程→预算)
- 引用知识库中的具体餐厅推荐
步骤6:发布
点击"发布" → 选择平台(豆包、飞书、微信等)→ 你的"智能体"就可以被使用了!
阶段2.3小结:
- 扣子的"Bot" = 简化版Agent(有Prompt人设+工具+知识库)
- 通过图形界面理解了Agent的核心组件
局限: 扣子的Bot自主决策能力有限,大多是"预设流程"
阶段2总体收获:
| 体验项目 | 学到的核心概念 | 技术对应 |
|---|---|---|
| ChatGPT/Claude | LLM基础能力、上下文窗口 | 大模型原理 |
| Perplexity | 实时检索、来源标注 | RAG流程 |
| Coze扣子 | 人设Prompt、工具调用、知识库 | Agent雏形 |
第3阶段:深入Agent------理解自主决策
经过阶段2,你已经体验了"玩具级"智能体。阶段3的目标是:接触真正的Agent,观察它如何自主解决复杂问题。
3.1 体验OpenCode:观察代码Agent的自主工作
OpenCode 是目前最流行的开源AI编程Agent(见前文介绍)。我们通过实际观察,理解Agent的"思考-行动-观察"循环。
安装与配置
css
# macOS/Linux安装
brew install sst/tap/opencode
# 或npm安装
npm install -g opencode-ai@latest
# 配置API Key(以Claude为例)
export ANTHROPIC_API_KEY="sk-ant-..."
# 或配置OpenAI
export OPENAI_API_KEY="sk-..."
实践任务:让Agent修复真实Bug
准备环境:
- 找一个你有权限测试的GitHub仓库(或本地项目)
- 故意引入一个Bug,例如:
css
# calculator.py
def divide(a, b):
return a / b # 没有处理b=0的情况
启动OpenCode观察:
css
cd your-project-folder
opencode
进入Agent模式后,输入:
检查calculator.py文件,找到潜在的bug并修复,然后运行测试验证修复是否成功
关键观察:Agent的思考过程
你会在终端看到类似这样的输出(颜色区分):
css
[思考] 用户让我检查calculator.py的bug。我需要:
1. 先读取文件内容
2. 分析代码问题
3. 提出修复方案
4. 执行修复
5. 验证修复结果
[行动] 读取文件 calculator.py
[工具] file_read: calculator.py
[观察] 文件内容:
def divide(a, b):
return a / b
[思考] 发现问题:没有处理b=0的情况,会导致ZeroDivisionError。需要添加异常处理。
[行动] 修改文件,添加参数检查
[工具] file_edit: calculator.py
[编辑] 在函数开头添加:
if b == 0:
raise ValueError("除数不能为零")
[思考] 修改完成,需要验证。我先写一个测试用例,然后运行。
[行动] 创建测试文件 test_calculator.py
[工具] file_write: test_calculator.py
[内容] import pytest
from calculator import divide
def test_divide_normal():
assert divide(10, 2) == 5
def test_divide_by_zero():
with pytest.raises(ValueError, match="除数不能为零"):
divide(10, 0)
[行动] 运行测试
[工具] command: pytest test_calculator.py -v
[观察] 测试通过:2 passed in 0.03s
[完成] Bug已修复并验证成功。修改内容:
- 在divide函数中添加了对b=0的检查
- 添加了相应的单元测试
深度分析:Agent的决策流程
通过观察,你可以看到真正的Agent具备以下特征:
- 自主规划:不需要你告诉它"先读文件、再修改、再测试",它自己分解步骤
- 工具调用:根据需要使用file_read、file_edit、command等工具
- 错误处理:如果测试失败,它会观察错误信息,调整方案重新尝试
- 记忆上下文:始终记得最终目标是"修复bug并验证"
对比阶段2的扣子Bot:
- 扣子:你预设了流程(问A→答B→调用工具C)
- OpenCode:你给目标,它自己决定每一步做什么
进阶实验:复杂任务观察
尝试让OpenCode完成更复杂的任务:
css
为这个Python项目添加完整的CI/CD配置:
- 创建GitHub Actions工作流,运行pytest和flake8
- 添加Dockerfile支持容器化部署
- 更新README,说明如何本地运行和Docker运行
- 确保所有配置都经过验证
观察要点:
- 它如何分解这个大任务?
- 遇到不确定的地方(如你的Dockerhub用户名),它会怎么问?
- 如果某一步失败了(如Docker构建失败),它会如何重试?
阶段3.1小结:
- 真正的Agent核心:自主规划 + 工具使用 + 反馈循环
- OpenCode展示了"代码场景"的Agent形态
- 其他场景(如浏览器操作、数据分析)的Agent原理相同,只是工具不同
3.2 阅读LangChain/LangGraph文档:理解Agent架构
要深入理解Agent,必须学习LangChain(AI应用开发框架)和LangGraph(Agent工作流引擎)。
LangChain基础概念
LangChain是构建LLM应用的Python/JS框架,核心组件:
css
┌────────────────────────────────────────────┐
│ LangChain 架构 │
├────────────────────────────────────────────┤
│ Model I/O │ 模型接口(LLM/ChatModel) │
├───────────────┼────────────────────────────┤
│ Retrieval │ 数据检索(RAG组件) │
├───────────────┼────────────────────────────┤
│ Chains │ 流程链(固定步骤组合) │
├───────────────┼────────────────────────────┤
│ Agents │ 智能体(动态决策) │
├───────────────┼────────────────────────────┤
│ Memory │ 记忆管理 │
├───────────────┼────────────────────────────┤
│ Callbacks │ 回调系统(日志、监控) │
└───────────────┴────────────────────────────┘
必读文档章节:
- Agent概念:LangChain Agents
- 理解AgentAction(行动)和AgentFinish(完成)
- 学习ReAct(Reasoning + Acting)模式
- Tools:Tools指南
- 如何给Agent配备工具
- 工具描述(Description)的重要性(Agent靠它决定用什么工具)
- Memory:Memory类型
- ConversationBufferMemory:记住完整对话
- ConversationSummaryMemory:总结长对话
LangGraph:Agent的"大脑升级"
为什么需要LangGraph?
传统Agent(如LangChain的ZeroShotAgent)是线性的:思考→行动→观察→思考...
但复杂任务需要分支、循环、并行:
- 如果工具A返回错误,走分支B
- 同时调用多个工具,综合结果
- 人工审核节点,必要时人工介入
LangGraph核心概念:
css
State(状态)→ Nodes(节点)→ Edges(边)→ Graph(图)
节点:每个步骤(LLM调用、工具执行、人工审核)
边:状态流转(普通边、条件边)
状态:跨节点共享的数据(消息历史、中间结果)
必读示例:
- ReAct Agent:LangGraph ReAct
- 用LangGraph实现标准ReAct流程
- 对比与LangChain原生Agent的区别
人机协作:Human-in-the-loop - 关键节点暂停,等待人类输入
- 适用于需要审核的场景(如自动下单前确认)
多Agent系统:Multi-Agent
多个Agent协作(如研究员Agent写报告→审核员Agent检查→编辑Agent润色)
学习建议:
css
# 安装
pip install langchain langgraph langchain-openai
# 从官方示例开始,逐行阅读代码
# 重点关注:
# 1. State如何定义和传递
# 2. Node函数如何修改State
# 3. Conditional Edge(条件边)如何实现分支逻辑
阶段3.2小结:
- LangChain提供组件,LangGraph提供编排
- 学Agent必须理解:状态管理、工具描述、ReAct循环、条件分支
**建议:**先跑通官方示例,再修改实验(如添加新工具、改变分支逻辑)
第4阶段:系统学习------从使用到开发
阶段4的目标是:掌握底层原理,能独立开发AI应用。
4.1 学习Prompt Engineering:与AI高效沟通
Prompt Engineering(提示工程)不是"写几句话",而是与LLM的编程接口。
核心原则
原则1:清晰具体
css
# 差
"写个Python函数"
# 好
"写一个Python函数,接收两个参数(列表list和目标值target),返回列表中两数之和等于target的索引。要求时间复杂度O(n),包含docstring和类型提示。"
原则2:结构化格式
使用Markdown、XML或JSON结构化Prompt:
css
## 角色
你是一位资深Python工程师。
## 任务
优化以下代码的性能。
## 输入代码
```python
def find_duplicates(data):
result = []
for i in range(len(data)):
for j in range(i+1, len(data)):
if data[i] == data[j] and data[i] not in result:
result.append(data[i])
return result
要求
- 优化时间复杂度至O(n)
- 解释优化思路
- 提供复杂度分析
css
**原则3:Few-Shot示例(少样本学习)**
给AI示例,让它模仿:
```markdown
将自然语言转为SQL查询。
示例1:
输入:查询2023年销售额超过100万的客户
输出:SELECT customer_id, SUM(amount) FROM sales
WHERE year=2023 GROUP BY customer_id HAVING SUM(amount)>1000000;
示例2:
输入:{用户输入}
输出:
高级技巧
Chain-of-Thought(思维链):让AI"一步步想"
css
问题:一个果园有苹果树和梨树共100棵,苹果树是梨树的3倍。各有多少棵?
请按以下步骤解答:
1. 设梨树为x棵,列出方程
2. 解方程
3. 验证答案
4. 给出最终答案
Self-Consistency(自洽性):多次采样选多数答案
css
# 同一个问题问3次,选出现最多的答案
answers = [query_llm(prompt) for _ in range(3)]
final_answer = most_common(answers)
ReAct模式(推理+行动):Agent的基础
css
思考:用户问北京天气,我需要查询实时数据。
行动:调用天气API,参数{"city": "北京"}
观察:API返回{"temp": 25, "weather": "晴"}
思考:已获得信息,可以回答。
最终答案:北京今天晴天,25°C。
学习资源:
《Prompt Engineering Guide》promptingguide.ai
OpenAI官方文档:Best Practices
**实践:**在PromptLayer等平台上测试不同Prompt的效果
4.2 了解向量数据库和Embedding:RAG的基石
Embedding(嵌入) :文本的数学表示
**概念:**用高维向量(通常512-4096维)表示文本的语义。
关键特性:
- 语义相似 ↔ 向量相近:"国王"和"皇帝"的向量距离很近
- 可计算:向量间可算余弦相似度,实现语义搜索
实践:可视化Embedding
css
from openai import OpenAI
import numpy as np
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
client = OpenAI()
# 准备句子
sentences = [
"苹果是一种水果",
"香蕉很好吃",
"iPhone是智能手机",
"华为发布了新手机",
"今天天气很好",
"明天可能下雨"
]
# 获取Embedding
embeddings = []
for s in sentences:
response = client.embeddings.create(
model="text-embedding-3-small",
input=s
)
embeddings.append(response.data[0].embedding)
# 降维到2D可视化
embeddings = np.array(embeddings)
pca = PCA(n_components=2)
reduced = pca.fit_transform(embeddings)
# 绘图
plt.figure(figsize=(10, 6))
colors = ['red', 'red', 'blue', 'blue', 'green', 'green']
for i, (x, y) in enumerate(reduced):
plt.scatter(x, y, c=colors[i], s=100)
plt.annotate(sentences[i], (x, y), fontsize=9)
plt.title("句子Embedding可视化(PCA降维)")
plt.show()
# 你会看到:水果聚一类,手机聚一类,天气聚一类
向量数据库: 高效检索相似向量
主流产品对比:
| 数据库 | 特点 | 适用场景 |
|---|---|---|
| Chroma | 开源、轻量、易用 | 本地开发、小项目 |
| Pinecone | 全托管、无需运维 | 生产环境、快速启动 |
| Milvus/Zilliz | 开源、高性能、可扩展 | 大规模企业应用 |
| pgvector | PostgreSQL扩展 | 已有PG基础架构 |
| Redis | 内存存储、极速 | 实时推荐、缓存 |
核心操作(以Chroma为例):
css
import chromadb
# 创建客户端
client = chromadb.Client()
collection = client.create_collection("my_docs")
# 添加文档(自动Embedding)
collection.add(
documents=["文档1内容...", "文档2内容..."],
metadatas=[{"source": "file1.pdf"}, {"source": "file2.doc"}],
ids=["doc1", "doc2"]
)
# 检索(自动将查询转为向量,找最相似的)
results = collection.query(
query_texts=["用户问题"],
n_results=3
)
# results包含最相似的3个文档片段
关键参数:
css
# 分块策略(Chunking)
from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500, # 每个块多少字符
chunk_overlap=50, # 块之间重叠多少(保持上下文)
separators=["\n\n", "\n", "。", "!", "?"] # 优先按这些分割
)
# 相似度阈值
results = collection.query(
query_texts=["问题"],
n_results=5,
where={"category": "技术"} # 元数据过滤
)
4.3 动手写一个简单Agent:Python + OpenAI API
最后,我们将所有知识整合,实现一个极简但完整的ReAct Agent
css
import json
import os
from openai import OpenAI
from datetime import datetime
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
# ========== 1. 定义工具 ==========
def calculator(expression: str) -> str:
"""计算数学表达式,如'2 + 2'或'sqrt(16)'"""
try:
# 安全评估:只允许数学运算
allowed_names = {
"sqrt": __import__('math').sqrt,
"sin": __import__('math').sin,
"cos": __import__('math').cos,
"pi": __import__('math').pi
}
result = eval(expression, {"__builtins__": {}}, allowed_names)
return str(result)
except Exception as e:
return f"错误: {str(e)}"
def search_weather(city: str) -> str:
"""模拟天气查询(实际应调用真实API)"""
# 模拟数据
weather_db = {
"北京": "晴天,25°C",
"上海": "多云,22°C",
"深圳": "小雨,28°C"
}
return weather_db.get(city, f"未找到{city}的天气信息")
def get_current_time() -> str:
"""获取当前时间"""
return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# 工具注册表
TOOLS = {
"calculator": calculator,
"search_weather": search_weather,
"get_current_time": get_current_time
}
# 工具描述(告诉LLM每个工具的功能和参数)
TOOLS_DESCRIPTION = [
{
"name": "calculator",
"description": "计算数学表达式,支持加减乘除、开方sqrt等",
"parameters": {
"type": "object",
"properties": {
"expression": {"type": "string", "description": "数学表达式,如'2 + 2'"}
},
"required": ["expression"]
}
},
{
"name": "search_weather",
"description": "查询指定城市的天气",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "城市名称,如'北京'"}
},
"required": ["city"]
}
},
{
"name": "get_current_time",
"description": "获取当前时间",
"parameters": {
"type": "object",
"properties": {}
}
}
]
# ========== 2. ReAct Agent核心 ==========
class SimpleAgent:
def __init__(self):
self.messages = [] # 对话历史
self.max_iterations = 10 # 防止无限循环
def think(self, user_input: str) -> str:
"""主循环:思考-行动-观察"""
self.messages.append({"role": "user", "content": user_input})
for i in range(self.max_iterations):
print(f"\n=== 迭代 {i+1} ===")
# 调用LLM,让它决定下一步
response = client.chat.completions.create(
model="gpt-4o",
messages=self._build_messages(),
tools=[{"type": "function", "function": desc} for desc in TOOLS_DESCRIPTION],
tool_choice="auto"
)
message = response.choices[0].message
# 情况1:LLM决定调用工具
if message.tool_calls:
self.messages.append(message) # 记录 assistant 的 tool_calls
for tool_call in message.tool_calls:
function_name = tool_call.function.name
function_args = json.loads(tool_call.function.arguments)
print(f"🤔 思考: 需要调用 {function_name},参数: {function_args}")
# 执行工具
if function_name in TOOLS:
result = TOOLS[function_name](**function_args)
print(f"🔧 行动: {function_name}({function_args})")
print(f"👁️ 观察: {result}")
# 将结果加入对话
self.messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": str(result)
})
else:
error_msg = f"错误: 未知工具 {function_name}"
self.messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": error_msg
})
# 情况2:LLM直接给出最终答案
else:
final_answer = message.content
self.messages.append({"role": "assistant", "content": final_answer})
print(f"✅ 完成: {final_answer}")
return final_answer
return "达到最大迭代次数,未能完成"
def _build_messages(self):
"""构建完整的对话历史,包含系统提示"""
system_prompt = """你是一个智能助手,可以使用以下工具完成任务:
- calculator: 计算数学表达式
- search_weather: 查询天气
- get_current_time: 获取当前时间
规则:
1. 分析用户问题,决定是否需要工具
2. 如果需要,调用相应工具并等待结果
3. 根据观察结果,决定下一步或给出最终答案
4. 回答要简洁、准确"""
return [{"role": "system", "content": system_prompt}] + self.messages
# ========== 3. 运行测试 ==========
if __name__ == "__main__":
agent = SimpleAgent()
# 测试1:数学计算 + 时间查询
print("=" * 50)
print("测试1: 计算 (158 * 27) + 当前时间")
result = agent.think("计算158乘以27,并告诉我现在几点")
print(f"\n最终答案: {result}")
# 测试2:天气查询
print("\n" + "=" * 50)
print("测试2: 查询北京天气")
agent2 = SimpleAgent() # 新会话
result = agent2.think("北京今天天气怎么样?适合出门吗?")
print(f"\n最终答案: {result}")
代码解析:
| 组件 | 作用 |
|---|---|
TOOLS |
工具函数 registry |
TOOLS_DESCRIPTION |
工具元数据(名称、描述、参数schema),LLM靠这个决定调什么 |
SimpleAgent |
Agent主类,管理状态和循环 |
think() |
ReAct循环:LLM决策→执行工具→观察结果→继续或结束 |
messages |
维护完整对话历史,包括 tool_calls 和 tool 响应 |
运行结果示例:
css
==================================================
测试1: 计算 (158 * 27) + 当前时间
=== 迭代 1 ===
🤔 思考: 需要调用 calculator,参数: {'expression': '158 * 27'}
🔧 行动: calculator({'expression': '158 * 27'})
👁️ 观察: 4266
=== 迭代 2 ===
🤔 思考: 需要调用 get_current_time,参数: {}
🔧 行动: get_current_time({})
👁️ 观察: 2026-02-04 15:32:18
=== 迭代 3 ===
✅ 完成: 158乘以27等于4266,当前时间是2026-02-04 15:32:18。
最终答案: 158乘以27等于4266,当前时间是2026-02-04 15:32:18。
进阶方向:
添加记忆: 把messages持久化到数据库,实现跨会话记忆
添加RAG: 在工具中加入search_documents,接入向量数据库
复杂规划: 用LangGraph实现多步骤规划、条件分支、人工审核