1. AI Agent 开发实战:从零构建具备工具调用能力的智能系统
在当今AI技术快速发展的背景下,能够自主调用工具完成复杂任务的AI Agent正成为行业热点。与普通聊天机器人不同,一个真正的AI Agent应该具备环境感知、自主决策和工具调用的能力。本文将基于LangChain框架,手把手教你构建一个能够调用RAG知识库和精确计算器的实用Agent系统。
1.1 什么是真正的AI Agent?
AI Agent的核心在于"智能代理"四个字。它不仅仅是一个问答系统,而是一个具备以下关键能力的智能体:
- 环境感知:能够理解用户输入和上下文
- 自主决策:根据任务需求选择合适的工具
- 工具调用:实际执行外部函数完成任务
- 记忆能力:保留短期对话历史和长期知识
这种架构使得Agent能够处理远比普通聊天机器人更复杂的业务场景,比如数据分析、知识检索、自动化流程等。
提示:在开发Agent时,最关键的是设计好工具接口和决策逻辑,这直接决定了Agent的实用性和可靠性。
2. Agent核心架构解析
2.1 Agent四大核心组件
一个完整的AI Agent通常由以下四个核心组件构成:
- LLM(大语言模型):负责理解、推理和决策
- 记忆系统:
- 短期记忆:保存对话历史
- 长期记忆:RAG知识库
- 规划模块:任务分解和执行流程控制
- 工具集:Agent可调用的外部函数
在我们的案例中,LLM选用的是通义千问(qwen-plus),记忆系统通过RAG实现,工具集则包含计算器和知识检索两个功能。
2.2 工具调用机制详解
工具调用是Agent最核心的能力之一。在LangChain框架中,工具调用的基本流程如下:
- 用户输入问题
- LLM分析问题并决定是否需要调用工具
- 如果需要,LLM返回工具名称和参数
- 系统执行对应工具函数
- 将工具执行结果返回给LLM
- LLM整合信息生成最终回复
这个流程可能循环多次,直到LLM认为已经获得足够信息来回答用户问题。
3. 实战:构建双工具Agent系统
3.1 环境准备与依赖安装
首先需要安装必要的Python包:
bash复制pip install langchain langchain-community faiss-cpu dashscope
然后设置API密钥:
python复制import os
os.environ["DASHSCOPE_API_KEY"] = "your_api_key_here"
3.2 工具函数实现
3.2.1 精确计算器工具
python复制@tool
def calculator(expression: str) -> str:
"""
计算数学表达式。需要精确计算时使用。
参数:
expression: 数学算式,如 "2 + 2" 或 "500 * 0.8"。
返回:
str: 计算结果,如 "4.0" 或 "400.0"。
"""
print(f" [工具调用] 计算器正在计算: {expression}")
try:
return str(eval(expression))
except Exception as e:
return f"计算错误: {e}"
注意:直接使用eval存在安全风险,生产环境应该替换为更安全的计算方式,比如使用ast.literal_eval或专门的数学表达式解析库。
3.2.2 RAG知识库工具
python复制@tool
def rag_search(query: str) -> str:
"""
从数据库中搜索与查询公司内部相关的文档,包括公司计划名,代号,截止日期等详细信息。
参数:
query (str): 要搜索的查询字符串。
返回:
str: 与查询相关的文档内容。
"""
raw_text = """
【公司内部机密:代号"深蓝计划"】
1. 项目目标:开发一款能听懂猫语的翻译器。
2. 核心技术:基于Transformer的"喵声波"分析算法。
3. 团队暗号:如果有人问"今天天气怎么样?",必须回答"我想吃鱼"。
4. 截止日期:2026年12月31日。
5. 经费预算:仅剩50元人民币,主要用于购买猫条。
"""
RAG_PATH = "faiss_index"
docs = [Document(page_content=raw_text)]
text_splitter = RecursiveCharacterTextSplitter(chunk_size=25, chunk_overlap=5)
split_docs = text_splitter.split_documents(docs)
embeddings = DashScopeEmbeddings(model="text-embedding-v1")
if os.path.exists(RAG_PATH):
ragdb = FAISS.load_local(RAG_PATH, embeddings, allow_dangerous_deserialization=True)
else:
ragdb = FAISS.from_documents(split_docs, embeddings)
ragdb.save_local(RAG_PATH)
return "\n\n".join(doc.page_content for doc in ragdb.similarity_search(query, k=2))
3.3 Agent核心逻辑实现
python复制def run_agent(query:str):
# 初始化模型和工具
tool_maps={
"rag_search": rag_search,
"calculator": calculator
}
llm = ChatTongyi(model_name="qwen-plus")
tool_llm = llm.bind_tools(tools=list(tool_maps.values()))
message = [HumanMessage(content=query)]
# 限制最多5轮对话避免死循环
for i in range(5):
print("="*20+"\n第"+str(i+1)+"轮\n"+query+"\n"+"="*20)
# 调用LLM获取响应
response = tool_llm.invoke(message)
message.append(response)
print(f"需要调用{len(response.tool_calls)}个方法")
# 如果没有工具调用,直接返回结果
if not response.tool_calls:
print("最终结果:" + response.content)
return
# 处理每个工具调用
for tool_call in response.tool_calls:
call_id = tool_call["id"]
func_name = tool_call["name"]
func_args = tool_call["args"]
# 安全检查:确保工具存在
if func_name in tool_maps:
tool_func = tool_maps[func_name]
tool_output = tool_func.invoke(func_args)
print("工具调用:" + func_name + ",参数:" + str(func_args) + ",结果:" + tool_output)
else:
tool_output = f"错误: 工具 {func_name} 不存在。"
message.append(
ToolMessage(
content=tool_output,
tool_call_id=call_id,
name=func_name,
)
)
if __name__ == "__main__":
run_agent("公司计划是什么")
run_agent("公司的经费预算是多少,如果预算提高46%后多少")
run_agent("今天天气真好")
4. 关键技术与实现细节
4.1 工具绑定机制
在LangChain中,通过bind_tools方法将工具与LLM绑定:
python复制tool_llm = llm.bind_tools(tools=list(tool_maps.values()))
这个方法会修改LLM的prompt,使其了解可用的工具及其使用方法。绑定的工具必须使用@tool装饰器,并且有清晰的文档字符串说明。
4.2 多轮对话控制
Agent通过循环实现多轮对话,每轮可能包含以下步骤:
- LLM分析当前对话状态
- 决定是否需要调用工具
- 如果调用工具,执行并收集结果
- 将结果反馈给LLM
- LLM生成最终回复或决定继续调用工具
为了防止无限循环,必须设置最大轮次限制(如5轮)。
4.3 工具调用安全
工具调用存在潜在安全风险,特别是当工具涉及系统操作或使用eval等危险函数时。应采取以下防护措施:
- 工具函数内部进行输入验证
- 限制工具的执行权限
- 使用沙箱环境运行工具
- 监控和记录所有工具调用
5. 常见问题与解决方案
5.1 工具调用失败排查
问题现象:Agent没有按预期调用工具
排查步骤:
- 检查工具是否正确定义并绑定
- 验证工具的描述文档是否清晰完整
- 检查LLM的响应是否包含正确的工具调用信息
- 查看日志确认工具调用流程
5.2 性能优化建议
- 缓存工具结果:对相同输入的工具调用结果进行缓存
- 并行工具调用:当多个工具可以并行调用时,使用异步方式
- 精简工具描述:保持工具文档简洁但信息完整
- 限制工具集大小:避免绑定过多不常用的工具
5.3 安全性增强方案
- 输入验证:所有工具函数都应验证输入参数
- 权限控制:不同工具设置不同执行权限
- 沙箱环境:高风险工具在隔离环境中运行
- 审计日志:记录所有工具调用的详细信息
6. 进阶开发方向
6.1 扩展工具集
可以根据业务需求添加更多工具,比如:
- 数据库查询工具
- API调用工具
- 文件操作工具
- 外部系统集成工具
6.2 增强记忆能力
当前的记忆系统比较简单,可以增强为:
- 分层记忆结构(短期/中期/长期)
- 记忆压缩和摘要
- 基于时间线的记忆组织
6.3 改进规划能力
通过以下方式提升Agent的任务规划能力:
- 引入任务分解算法
- 增加规划验证步骤
- 支持动态调整规划
在实际开发中,我发现工具的描述质量直接影响Agent的调用准确性。每个工具都应该有清晰、具体的文档说明,包括参数格式、返回值和典型用例。另外,限制工具调用的轮次非常重要,避免陷入无限循环。对于生产环境,还需要考虑添加完善的监控和日志系统,以便追踪Agent的决策过程。