这是我学习 AI Agent 开发第一周的实战记录:实现一个能自动判断问题类型、调用不同工具(RAG、SQL、计算器)的智能体。全文代码开源,思路清晰,适合想动手做 Agent 的同学参考。
一、为什么要做这个?
AI Agent 是当下大模型落地的热门方向。但 Agent 不只是“能聊天的模型”,而是能自己动脑子、用工具、完成复杂任务的程序。
这周我给自己定了一个小目标:实现一个最小化的多工具智能体。它能:
- 判断用户是想查知识、查数据,还是做计算
- 根据判断结果,自动调用对应的工具
- 用自然语言给出答案
最终效果是这样的:
| 用户问题 | 智能体行为 | 回答 |
|---|---|---|
| 什么是 AI Agent? | 知识类 → RAG 检索 | AI Agent 是智能体程序 |
| 笔记本卖了多少? | 数据类 → 生成 SQL | 笔记本共销售 95 台 |
| 25 * 4 等于多少? | 计算类 → 数学计算 | 25 * 4 = 100 |
二、技术栈
| 工具 | 用途 |
|---|---|
| Python 3.13 | 开发语言 |
| DeepSeek API | 大模型(便宜,中文友好) |
| Chroma | 向量数据库(RAG 检索) |
| SQLite | 业务数据存储 |
| LangGraph | Agent 框架(状态图 + 条件路由) |
三、整体架构
智能体的核心流程如下:
用户输入
↓
【判断意图】→ 知识类 → RAG 检索 → 回答
↓
数据类 → 生成 SQL → 执行 → 解释结果
↓
计算类 → 提取表达式 → 计算 → 返回
关键点:用一个 LLM 判断意图,然后根据意图走不同的处理分支。
四、核心代码解析
1. 定义状态(传递的数据包)
class AgentState(TypedDict):
question: str # 用户问题
intent: str # 意图:knowledge / data / calculator
answer: str # 最终答案
2. 意图判断节点
def classify_node(state: AgentState):
prompt = f"""判断问题类型,只回答"knowledge"、"data"或"calculator"。
知识类:问概念、定义、解释
数据类:问统计、数量、金额
计算类:数学计算
问题:{state["question"]}
类型:"""
result = call_deepseek(prompt).strip().lower()
intent = "knowledge" if "knowledge" in result else "data" if "data" in result else "calculator"
return {"intent": intent}
3. 条件路由(根据意图选节点)
def route_by_intent(state: AgentState):
if state["intent"] == "knowledge":
return "knowledge"
elif state["intent"] == "data":
return "sql"
else:
return "calculator"
builder.add_conditional_edges("classify", route_by_intent, {
"knowledge": "knowledge",
"sql": "sql",
"calculator": "calculator"
})
4. 各工具节点
RAG 节点(从 Chroma 检索):
def knowledge_node(state):
context = search_rag(state["question"])
prompt = f"基于资料回答问题。资料:{context}\n问题:{state['question']}"
return {"answer": call_deepseek(prompt)}
SQL 节点(让模型写 SQL 并执行):
def sql_node(state):
sql = call_deepseek(f"数据库结构:{schema}\n问题:{state['question']}\nSQL:")
result = execute_sql(sql)
answer = call_deepseek(f"查询结果:{result}\n用自然语言回答")
return {"answer": answer}
计算器节点(安全执行数学表达式):
def calculator_node(state):
expr = call_deepseek(f"提取表达式:{state['question']}")
result = eval(expr, {"__builtins__": {}}, {"sqrt": math.sqrt, "pi": math.pi})
return {"answer": f"{expr} = {result}"}
五、运行效果
直接看终端输出:
智能体成功区分知识类、数据类、计算类问题
六、踩坑记录
- API Key 空格:复制时容易带上空格 → 用
.strip()清理 - Chroma 模型下载:默认源在国外 → 用国内镜像
HF_ENDPOINT - SQL 带 Markdown:模型返回
```sql ... ```→ 用字符串清理 - eval 安全:限制
__builtins__和只允许少数函数,防止恶意代码
七、总结与下一步
第一周完成了:
- RAG 检索(Chroma)
- SQL 生成与执行
- 计算器工具
- LangGraph 图结构 + 条件路由
下一步:
- 增加联网搜索工具
- 支持多步推理(例如:先查笔记本销量,再和鼠标对比)
- 用 FastAPI 封装成服务
八、代码仓库
所有代码已开源在 GitHub:
github.com/qiu121122/a…
欢迎 star、fork、交流!
本文首发于掘金,如有转载需求请私信联系。