🔥 LangChain 实战:构建全能工具调用 Agent
📋 文章信息
- 分类: 后端开发 / AI 工程
- 标签: Python、LangChain、Agent、LLM、RAG
- 难度: 中级
🔍 引言
在 AI Agent 时代,如何让大语言模型拥有"十八般武艺"?本文将带你从零开始构建一个具备文档检索、网络搜索、数学计算、天气查询、邮件发送、数据库操作等多种能力的全能工具调用 Agent。
🎯 项目亮点
| 能力 | 实现方式 | 技术亮点 |
|---|---|---|
| 📚 文档检索 | Chroma + Ollama Embeddings | 本地部署,隐私安全 |
| 🔍 网络搜索 | TavilySearch | 实时信息获取 |
| 🧮 数学计算 | 安全 eval 沙箱 | 防代码注入 |
| 🌤️ 天气查询 | Open-Meteo API | 免费开源 |
| 📧 邮件发送 | SMTP | 自动邮件通知 |
| 📊 数据库查询 | SQLite + Pandas | 结构化数据处理 |
| ✏️ 文件写入 | 本地文件操作 | 结果持久化 |
🏗️ 整体架构
flowchart TD
User((用户))
subgraph Agent_Layer [Agent 核心层]
Agent[Agent LangGraph
create_agent] Checkpointer[InMemorySaver
会话记忆] LLM[ChatDeepSeek
DeepSeek-V4-Pro] end subgraph Tools [工具层] Calculator[calculator
数学计算] KnowledgeBase[knowledge_base_tool
文档检索] Search[TavilySearch
网络搜索] Weather[weather
天气查询] SendEmail[send_email
发送邮件] DatabaseQuery[database_query
查询销售表] FileWriter[file_writer
写文件] end subgraph RAG [知识库] Docs[(./docs/*.txt
本地文档)] Chroma[(Chroma 向量库
persist_directory)] Embeddings[OllamaEmbeddings
nomic-embed-text] end subgraph DataSources [数据源与外部服务] SQLiteDB[(sales.db
SQLite)] TavilyAPI[Tavily Search API] WeatherAPI[Open-Meteo API] SMTP[QQ邮箱 SMTP] end %% 用户与Agent交互 User --> Agent Agent --> Checkpointer Agent --> LLM LLM --> Agent %% Agent调用工具 Agent_Layer --> Tools %% 知识库工具的构建依赖 Chroma --> |创建 retriever| KnowledgeBase Embeddings --> |生成向量| Chroma Docs --> |加载并分割| Embeddings %% 各工具的外部依赖 Search --> TavilyAPI Weather --> WeatherAPI SendEmail --> SMTP DatabaseQuery --> SQLiteDB %% 样式 classDef tool fill:#e1f5fe,stroke:#01579b,stroke-width:2px; classDef datasource fill:#fff9c4,stroke:#fbc02d,stroke-width:2px; classDef agent fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px; class Calculator,Search,KnowledgeBase,Weather,SendEmail,DatabaseQuery,FileWriter tool; class Docs,Chroma,Embeddings,SQLiteDB,TavilyAPI,WeatherAPI,SMTP datasource; class Agent,Checkpointer,LLM agent;
create_agent] Checkpointer[InMemorySaver
会话记忆] LLM[ChatDeepSeek
DeepSeek-V4-Pro] end subgraph Tools [工具层] Calculator[calculator
数学计算] KnowledgeBase[knowledge_base_tool
文档检索] Search[TavilySearch
网络搜索] Weather[weather
天气查询] SendEmail[send_email
发送邮件] DatabaseQuery[database_query
查询销售表] FileWriter[file_writer
写文件] end subgraph RAG [知识库] Docs[(./docs/*.txt
本地文档)] Chroma[(Chroma 向量库
persist_directory)] Embeddings[OllamaEmbeddings
nomic-embed-text] end subgraph DataSources [数据源与外部服务] SQLiteDB[(sales.db
SQLite)] TavilyAPI[Tavily Search API] WeatherAPI[Open-Meteo API] SMTP[QQ邮箱 SMTP] end %% 用户与Agent交互 User --> Agent Agent --> Checkpointer Agent --> LLM LLM --> Agent %% Agent调用工具 Agent_Layer --> Tools %% 知识库工具的构建依赖 Chroma --> |创建 retriever| KnowledgeBase Embeddings --> |生成向量| Chroma Docs --> |加载并分割| Embeddings %% 各工具的外部依赖 Search --> TavilyAPI Weather --> WeatherAPI SendEmail --> SMTP DatabaseQuery --> SQLiteDB %% 样式 classDef tool fill:#e1f5fe,stroke:#01579b,stroke-width:2px; classDef datasource fill:#fff9c4,stroke:#fbc02d,stroke-width:2px; classDef agent fill:#e8f5e9,stroke:#2e7d32,stroke-width:2px; class Calculator,Search,KnowledgeBase,Weather,SendEmail,DatabaseQuery,FileWriter tool; class Docs,Chroma,Embeddings,SQLiteDB,TavilyAPI,WeatherAPI,SMTP datasource; class Agent,Checkpointer,LLM agent;
🚀 核心功能实现
1. 文档检索系统(RAG)
python
# 加载文档
loader = DirectoryLoader("./docs", glob="**/*.txt", loader_cls=TextLoader)
documents = loader.load()
# 文本分割
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500,
chunk_overlap=50,
separators=["\n\n", "\n", "。", "!", "?", ","]
)
docs = text_splitter.split_documents(documents)
# 构建向量数据库
embeddings = OllamaEmbeddings(model="nomic-embed-text")
vectorstore = Chroma.from_documents(
documents=docs,
embedding=embeddings,
persist_directory="./chroma_db"
)
# 创建检索工具
retriever = vectorstore.as_retriever(search_kwargs={"k": 3})
knowledge_base_tool = create_retriever_tool(
retriever,
name="knowledge_base",
description="查询公司内部文档,如考勤、请假、福利等。"
)
技术要点:
- 使用 Ollama 本地嵌入模型,无需 API 调用
- 中文文本分割策略优化
- 向量数据库持久化,避免重复构建
2. 工具定义与注册
python
@tool
def calculator(expression: str) -> str:
"""执行数学计算。输入是一个数学表达式,例如 "2+3*4" """
try:
result = eval(expression, {"__builtins__": {}}, math.__dict__)
return str(result)
except Exception as e:
return f"计算错误: {e}"
@tool
def weather(city: str) -> str:
"""查询城市天气"""
geo_url = f"https://geocoding-api.open-meteo.com/v1/search?name={city}&count=1"
geo = requests.get(geo_url).json()
if not geo.get("results"):
return "城市未找到"
lat, lon = geo["results"][0]["latitude"], geo["results"][0]["longitude"]
w = requests.get(f"https://api.open-meteo.com/v1/forecast?latitude={lat}&longitude={lon}¤t_weather=true").json()
cur = w["current_weather"]
return f"{city}温度{cur['temperature']}°C, 风速{cur['windspeed']}km/h"
......省略部分代码
tools = [calculator, search, knowledge_base_tool, weather, send_email, file_writer, database_query]
设计亮点:
@tool装饰器自动生成工具描述- 函数签名和 docstring 即为 LLM 的工具调用指南
- 统一的错误处理机制
3. 多模型支持与配置
python
# 使用 DeepSeek API
llm = ChatDeepSeek(
model="deepseek-v4-pro",
temperature=0,
thinking={"type": "enabled"},
reasoning_effort="high",
)
# 或使用 Ollama 本地模型
# llm = ChatOpenAI(
# model='llama3.2:1b',
# base_url="http://localhost:11434/v1",
# temperature=0,
# )
4. Agent 创建与记忆系统
python
memory = InMemorySaver()
agent = create_agent(
model=llm,
tools=tools,
checkpointer=memory,
system_prompt="你是一个能用工具的得力助手。回答问题时请先思考,如需获取实时信息或进行计算,务必调用工具。"
)
📦 依赖与环境配置
安装依赖
bash
pip install langchain langchain-core langchain-community langchain-deepseek langchain-ollama langchain-openai langchain-tavily langgraph pandas python-dotenv
环境变量配置(.env)
tex
EMAIL=your_email@qq.com
MAIL_PASSWORD=your_qq_email_token
💡 使用示例
示例 1:多步骤任务
python
agent.invoke(
{"messages": [{"role": "user", "content": "搜索最新的GPT-4o评测文章,读一遍总结成三句话,再翻译成法语存为文件"}]},
config
)
执行流程:
- 调用
search工具搜索 GPT-4o 评测 - 总结文章内容
- 翻译为法语
- 调用
file_writer工具保存文件
示例 2:内部知识查询
python
agent.invoke(
{"messages": [{"role": "user", "content": "公司规定多少天年假,和国家法定标准比哪个多?"}]},
config
)
执行流程:
- 调用
knowledge_base工具查询员工手册 - 对比国家法定标准
- 给出结论并引用来源
🔧 核心技术解析
1. RAG 检索流程
flowchart LR
A[文档加载
Document Loaders] --> B[文本分割
Text Splitters] B --> C[嵌入生成
Embedding Models] C --> D[向量存储
Vector Store] D --> E[相似度检索
Similarity Search] E --> F[上下文注入
Context Injection]
Document Loaders] --> B[文本分割
Text Splitters] B --> C[嵌入生成
Embedding Models] C --> D[向量存储
Vector Store] D --> E[相似度检索
Similarity Search] E --> F[上下文注入
Context Injection]
2. 工具调用机制
LangChain 的 @tool 装饰器会自动将函数转换为 LLM 可理解的格式:
python
{
"name": "calculator",
"description": "执行数学计算。输入是一个数学表达式,例如 \"2+3*4\"",
"parameters": {
"type": "object",
"properties": {
"expression": {"type": "string"}
},
"required": ["expression"]
}
}
3. 记忆系统原理
LangGraph 的 InMemorySaver 实现了对话状态的持久化:
- 存储每个对话线程的完整历史
- 支持多线程并发
- 可扩展为持久化存储(如 Redis)
🚀 技术洞察
1. 安全计算的实现
python
result = eval(expression, {"__builtins__": {}}, math.__dict__)
安全措施:
- 清空
__builtins__防止危险函数调用 - 仅允许数学运算相关函数
- 异常捕获确保程序稳定
2. 文档分割策略
中文文本分割需要考虑:
- 语义完整性
- 上下文重叠(chunk_overlap)
- 中文标点符号处理
3. 多模型切换策略
| 模型类型 | 优点 | 缺点 |
|---|---|---|
| API 模型 | 性能强、更新快 | 成本高、有调用限制 |
| 本地模型 | 隐私安全、无成本 | 性能有限、需要硬件 |
📊 性能优化建议
| 优化方向 | 具体措施 |
|---|---|
| 向量数据库优化 | 使用 FAISS 替代 Chroma,提升检索速度 |
| 缓存机制 | 缓存搜索结果,避免重复查询 |
| 异步调用 | 并行执行多个工具调用 |
| 提示词优化 | 精简系统提示词,减少 token 消耗 |
| 文档预处理 | 提前构建向量数据库,避免运行时开销 |
🎯 总结与展望
本文要点
- ✅ 使用 LangChain 构建工具调用 Agent
- ✅ 实现文档检索(RAG)系统
- ✅ 注册多种实用工具(计算、搜索、天气、邮件等)
- ✅ 配置记忆系统支持多轮对话
- ✅ 支持多模型切换
未来方向
- 🔄 工具市场:支持动态加载第三方工具
- 🧠 反思机制:让 Agent 能够评估自己的决策
- 📊 性能监控:追踪工具调用效率
- 🔒 权限控制:细粒度的工具访问控制
- 📱 API 服务化:封装为 RESTful API
📮 互动交流
如果你有任何问题或想法,欢迎在评论区留言!如果觉得本文对你有帮助,请点赞、收藏、关注三连支持一下~