1. 从零构建AI Agent:基于LangChain的智能任务执行系统实战
最近在开发一个需要处理复杂业务逻辑的AI系统时,我发现单纯的聊天机器人(ChatGPT式交互)已经无法满足需求。经过调研,我选择了LangChain框架来构建一个真正的AI Agent——一个能够自主决策、调用工具、具备记忆能力的智能系统。本文将分享我在这个过程中的完整实现方案和踩坑经验。
AI Agent与传统聊天机器人的本质区别在于:它不只是被动回答问题,而是能主动感知环境、进行多步推理、调用工具完成任务。比如在我们的案例中,Agent可以同时处理公司内部文档查询和精确数学计算两类任务,并能根据上下文自主决定何时使用哪种工具。下面我就从核心架构开始,逐步拆解实现细节。
2. 核心架构设计
2.1 Agent的四大核心组件
一个完整的AI Agent需要包含以下四个关键部分:
-
LLM核心:负责基础推理和决策。我们选用通义千问(qwen-plus)作为基础模型,因其在中文场景下的优秀表现。
-
记忆系统:
- 短期记忆:自动维护的对话历史
- 长期记忆:基于RAG(检索增强生成)的公司知识库
-
规划能力:通过多轮对话机制实现任务分解和分步执行
-
工具调用:可以执行Python函数调用,扩展模型能力边界
python复制# 典型Agent架构代码示意
class MyAgent:
def __init__(self):
self.llm = ChatTongyi(model_name="qwen-plus") # 核心模型
self.memory = ConversationBufferMemory() # 记忆系统
self.tools = [calculator, rag_search] # 工具集
2.2 工具系统的设计要点
工具(Tool)是Agent能力的扩展关键。每个工具本质上是一个Python函数,但需要遵循特定规范:
- 必须使用
@tool装饰器标记 - 函数文档字符串需要详细描述功能、参数和返回
- 返回值必须是字符串格式
- 需要处理可能的异常情况
python复制@tool
def calculator(expression: str) -> str:
"""
计算数学表达式。需要精确计算时使用。
参数:
expression: 数学算式,如 "2 + 2" 或 "500 * 0.8"。
返回:
str: 计算结果,如 "4.0" 或 "400.0"。
"""
try:
return str(eval(expression))
except Exception as e:
return f"计算错误: {e}"
重要提示:工具函数的文档字符串质量直接影响模型调用工具的准确性。建议包含清晰的参数示例和返回示例。
3. 完整实现步骤
3.1 环境准备与初始化
首先需要安装必要的Python包:
bash复制pip install langchain langchain-community dashscope faiss-cpu
然后设置API密钥:
python复制import os
os.environ["DASHSCOPE_API_KEY"] = "your_api_key_here" # 替换为真实的API密钥
3.2 构建RAG知识库
长期记忆系统我们采用FAISS向量数据库实现:
python复制from langchain_community.vectorstores import FAISS
from langchain_community.embeddings import DashScopeEmbeddings
from langchain_text_splitters import RecursiveCharacterTextSplitter
def build_rag_index(documents):
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=200, # 根据文档特点调整
chunk_overlap=50
)
splits = text_splitter.split_documents(documents)
embeddings = DashScopeEmbeddings(model="text-embedding-v1")
vectorstore = FAISS.from_documents(splits, embeddings)
vectorstore.save_local("faiss_index")
return vectorstore
3.3 工具绑定与Agent运行
核心执行流程的关键代码:
python复制def run_agent(query: str, max_turns=5):
tool_maps = {
"rag_search": rag_search,
"calculator": calculator
}
llm = ChatTongyi(model_name="qwen-plus")
tool_llm = llm.bind_tools(tools=list(tool_maps.values()))
messages = [HumanMessage(content=query)]
for turn in range(max_turns):
response = tool_llm.invoke(messages)
messages.append(response)
if not response.tool_calls:
return response.content
for tool_call in response.tool_calls:
tool_name = tool_call["name"]
if tool_name in tool_maps:
tool_output = tool_maps[tool_name].invoke(tool_call["args"])
messages.append(
ToolMessage(
content=tool_output,
tool_call_id=tool_call["id"],
name=tool_name
)
)
return "达到最大对话轮次仍未完成请求"
4. 关键问题与解决方案
4.1 工具调用死循环问题
在实际测试中,我发现当LLM无法正确理解用户意图时,可能会在"思考-调用工具-再思考"的循环中无法跳出。解决方案:
- 设置最大对话轮次(如5轮)
- 添加明确的终止条件判断
- 在工具描述中强调适用场景
python复制# 改进后的循环结构
for turn in range(MAX_TURNS):
response = tool_llm.invoke(messages)
if should_terminate(response): # 自定义终止条件判断
break
...
4.2 安全风险防范
原始代码中使用eval()存在严重安全隐患。我采用了以下加固措施:
- 使用
ast.literal_eval替代eval - 添加数学表达式白名单校验
- 在工具描述中明确禁止危险操作
改进后的安全计算器实现:
python复制import ast
import re
@tool
def safe_calculator(expression: str) -> str:
"""
安全计算数学表达式。仅支持基本算术运算。
示例:
"2 + 3 * 4" -> "14.0"
禁止:
函数调用、属性访问等危险操作
"""
if not re.match(r'^[\d\s+\-*/().]+$', expression):
return "错误: 包含非法字符"
try:
node = ast.parse(expression, mode='eval')
if not all(isinstance(n, (ast.Num, ast.BinOp, ast.UnaryOp))
for n in ast.walk(node)):
raise ValueError("危险操作")
return str(eval(expression, {'__builtins__': None}, {}))
except Exception as e:
return f"计算错误: {e}"
4.3 性能优化技巧
-
向量检索优化:
- 调整chunk_size(通常200-500)
- 使用更好的embedding模型
- 添加元数据过滤
-
对话历史管理:
- 设置合理的对话窗口大小
- 重要信息摘要存储
- 适时清理无关历史
-
工具调用加速:
- 并行执行独立工具调用
- 缓存常用工具结果
- 预加载必要资源
5. 典型应用场景示例
5.1 公司信息查询与计算
python复制run_agent("公司计划是什么")
# 输出:深蓝计划,目标是开发猫语翻译器...
run_agent("经费预算提高46%后是多少")
# 输出:当前预算50元,提高46%后是73元
5.2 多工具协同工作
Agent可以自动判断何时使用哪种工具:
python复制run_agent("查询项目截止日期,并计算距离今天还有多少天")
# 自动先后调用rag_search和calculator工具
5.3 异常处理展示
python复制run_agent("计算system('rm -rf /')")
# 输出:错误: 包含非法字符 (安全拦截)
6. 扩展与进阶方向
-
多Agent协作系统:
- 不同Agent专精不同领域
- 设置协调员Agent管理任务分配
- 实现Agent间的通信机制
-
动态工具加载:
- 运行时发现和注册新工具
- 工具的热插拔机制
- 工具版本管理
-
强化学习优化:
- 根据历史交互优化工具选择策略
- 自动调整对话策略
- 个性化用户偏好学习
在实际项目中,我发现这套系统特别适合处理需要结合多种能力的中等复杂度任务。比如我们用它来处理客户支持场景,既能查询知识库,又能进行简单的计算和推理,大大提高了自动化程度。