67-Agent工具定义与调用-搜索引擎-数据库-代码执行器集成
文章目录
- 【67.Python+AI】Agent工具定义与调用:搜索引擎、数据库、代码执行器集成实战
- 导入语
- 1 ~> 工具的定义规范
- 1.1 一个标准 Tool 的结构
- 1.2 工具描述的黄金法则
- 2 ~> 工具一:搜索引擎集成
- 2.1 使用 Tavily Search API
- 2.2 免费替代方案
- 3 ~> 工具二:数据库查询
- 3.1 让 Agent 安全地查数据库
- 3.2 带着表结构描述的 Tool
- 4 ~> 工具三:Python 代码执行器
- 4.1 为什么要让 Agent 执行代码
- 4.2 沙箱式代码执行
- 5 ~> 三合一 Agent 实战
- 5.1 架构
- 5.2 完整代码
- 5.3 执行过程
- 思考 && 总结
- 结尾
【67.Python+AI】Agent工具定义与调用:搜索引擎、数据库、代码执行器集成实战
📖文章简介:本文聚焦Agent开发中最关键的环节——工具(Tool)的定义与集成。文章从"一个好的工具描述长什么样"开始,拆解Tool的四大要素(名称、描述、参数schema、执行函数),然后逐一讲解三种最常用工具的集成方式:搜索引擎(Tavily API)、数据库查询(SQLite + 安全检查)、Python代码执行器(沙箱模式)。最后给出一个"三合一"Agent的完整代码——能上网搜索、能查数据库、能写代码计算,配上Mermaid架构图展示工具调度流程。适合正在写ReAct Agent、需要给Agent扩充能力的开发者。
🎬 个人主页:源码骑士
❄专栏传送门:《Android开发基础》《python基础课程》
⭐️热衷从源码视角拆解技术底层原理,将复杂架构讲得通俗易懂
🎬 源码骑士的简介:
5年Android Framework系统开发经验,曾主导多项系统级性能优化专项
技术栈覆盖Android系统全链路(Binder/Handler/AMS/WMS/启动流程)及Java后端全家桶(Spring + MyBatis + Redis + Oracle)
累计产出原创技术文章100+篇,文章以流程图为特色,被读者评价为"看一篇胜过啃一周源码"
导入语
Agent 的"智能"从哪里来?一半来自 LLM 的推理能力,另一半来自它能调用的工具的广度——能搜到多少信息、能操作多少系统、能执行多少命令。
一个只有"搜索"工具的Agent,就是个加了联网功能的ChatGPT。但如果你的Agent能搜网页、能查数据库、能执行Python代码——它突然就有了"手和脚",能干真正的活了。
这篇文章就聚焦这个关键环节:怎么定义工具才能被LLM准确调用、三种最常用工具怎么集成、以及它们组合起来能解决什么问题。看完全文你会得到一个可复用的"三合一工具集",直接嵌入你的ReAct Agent。
1 ~> 工具的定义规范
1.1 一个标准 Tool 的结构
frompydanticimportBaseModel,FieldclassTool:"""标准工具定义"""def__init__(self,name:str,description:str,func,args_schema=None):self.name=name self.description=description self.func=func self.args_schema=args_schemadefexecute(self,**kwargs):returnself.func(**kwargs)1.2 工具描述的黄金法则
| 法则 | 好的描述 | 坏的描述 |
|---|---|---|
| 说清楚做什么 | “输入公司名称,返回该公司最新股价” | “查股票” |
| 说清楚输入格式 | “参数 keyword: 搜索关键词,多个词用空格分隔” | “搜索” |
| 说清楚输出格式 | “返回JSON:{price, change, volume}” | 无描述 |
| 写典型使用场景 | “当你需要获取实时信息时使用此工具” | 无 |
# ✅ 好:LLM能准确理解什么时候该用、怎么用search_tool=Tool(name="web_search",description="在互联网上搜索实时信息。当你需要最新资讯、事实核查时使用。""参数 query: 搜索关键词,尽量精简。返回前5条结果的标题和摘要。",func=web_search,)# ❌ 差:LLM不知道什么时候该调用bad_tool=Tool(name="s",description="search",func=web_search,)2 ~> 工具一:搜索引擎集成
2.1 使用 Tavily Search API
Tavily 是为 AI Agent 设计的搜索引擎 API,返回结构化的搜索结果:
importrequestsdefweb_search(query:str)->str:"""调用Tavily搜索API"""api_key="your-tavily-api-key"response=requests.post("https://api.tavily.com/search",json={"api_key":api_key,"query":query,"search_depth":"basic","max_results":5,})data=response.json()# 格式化搜索结果results=[]forrindata.get("results",[]):results.append(f"标题:{r['title']}\n内容:{r['content']}\n链接:{r['url']}")return"\n\n---\n\n".join(results)search_tool=Tool(name="web_search",description="搜索互联网获取实时信息。参数 query: 搜索关键词。",func=web_search,)2.2 免费替代方案
如果不想用付费API,可以考虑 DuckDuckGo 的免费搜索:
# 使用 duckduckgo_search 库fromduckduckgo_searchimportDDGSdeffree_search(query:str)->str:withDDGS()asddgs:results=list(ddgs.text(query,max_results=5))return"\n".join(f"{r['title']}:{r['body']}"forrinresults)3 ~> 工具二:数据库查询
3.1 让 Agent 安全地查数据库
直接让LLM写SQL很危险——一条DROP TABLE就灾难了。需要用读写分离 + SQL白名单做安全控制:
importsqlite3classSafeDatabase:"""安全的数据库工具——只读查询 + SQL白名单"""ALLOWED_KEYWORDS={"SELECT","FROM","WHERE","JOIN","GROUP","ORDER","LIMIT","COUNT","AVG","SUM","MAX","MIN"}def__init__(self,db_path:str):self.db_path=db_pathdefquery(self,sql:str)->str:# 安全检查sql_upper=sql.strip().upper()# 只允许 SELECT 语句ifnotsql_upper.startswith("SELECT"):return"错误:只允许 SELECT 查询"# 检查危险关键词dangerous={"DROP","DELETE","UPDATE","INSERT","ALTER","CREATE"}ifany(kwinsql_upperforkwindangerous):return"错误:不允许修改数据的操作"# 执行查询try:conn=sqlite3.connect(self.db_path)cursor=conn.cursor()cursor.execute(sql)columns=[desc[0]fordescincursor.description]rows=cursor.fetchall()conn.close()# 格式化输出result=" | ".join(columns)+"\n"+"-"*40+"\n"forrowinrows[:20]:# 最多返回20行result+=" | ".join(str(v)forvinrow)+"\n"returnresultifrowselse"查询无结果"exceptExceptionase:returnf"查询错误:{e}"db_tool=Tool(name="database_query",description="查询SQLite数据库。参数 sql: 合法的SELECT语句。""表结构: users(id, name, department, salary), orders(id, user_id, amount, date)",func=SafeDatabase("company.db").query,)3.2 带着表结构描述的 Tool
LLM 需要知道表结构才能写出正确的 SQL。所以在 Tool 描述中要写明表名和字段:
DATABASE_SCHEMA=""" 数据库包含以下表: - employees: id, name, department, salary, hire_date - departments: id, name, manager_id - projects: id, name, budget, status """4 ~> 工具三:Python 代码执行器
4.1 为什么要让 Agent 执行代码
有些任务LLM推理做不了——比如"这组数据的标准差是多少"、“把这个JSON排序”。让Agent直接写代码执行,比让它"算"准确得多。
4.2 沙箱式代码执行
importsysfromioimportStringIOdefexecute_python(code:str)->str:"""在受限环境中执行Python代码,捕获输出"""# 禁止危险操作forbidden=["os.","subprocess","shutil","__import__","open(","eval(","exec("]forwordinforbidden:ifwordincode:returnf"安全限制:代码中不允许使用 '{word}'"# 重定向stdoutold_stdout=sys.stdout sys.stdout=captured=StringIO()try:exec(code,{"__builtins__":{"print":print,"len":len,"range":range,"int":int,"float":float,"str":str,"list":list,"dict":dict,"sum":sum,"max":max,"min":min,"sorted":sorted,"abs":abs,"round":round,"zip":zip,}})output=captured.getvalue()returnoutputifoutputelse"代码执行成功(无输出)"exceptExceptionase:returnf"执行错误:{type(e).__name__}:{e}"finally:sys.stdout=old_stdout code_tool=Tool(name="python_executor",description="执行Python代码进行数学计算或数据处理。""参数 code: Python代码字符串。""可用函数: print, len, range, int, float, str, list, dict, sum, max, min, sorted, abs, round, zip",func=execute_python,)5 ~> 三合一 Agent 实战
5.1 架构
5.2 完整代码
tools={"web_search":web_search,"database_query":SafeDatabase("company.db").query,"python_executor":execute_python,}# 提供给LLM的工具描述TOOLS_DESC=""" - web_search[关键词]: 搜索互联网获取实时信息 - database_query[SQL]: 查询公司数据库(只读SELECT) - python_executor[代码]: 执行Python代码进行数学计算 数据库表: employees(id, name, dept, salary) """agent=ReActAgent(llm=ChatOpenAI(model="gpt-4"),tools=tools,tools_prompt=TOOLS_DESC,max_steps=10)# 复杂任务:需要三个工具协同result=agent.run("查一下技术部的平均薪资,然后搜索行业平均水平,""最后算算我们的薪资比行业高了多少百分比")5.3 执行过程
Step1: Thought: 先查技术部平均薪资 → database_query[SELECT AVG(salary)FROM employees WHEREdept='技术部']→ Observation:15000Step2: Thought: 搜索行业平均薪资 → web_search[Python开发工程师 平均薪资2024]→ Observation: 全国平均约12000元 Step3: Thought: 计算差距百分比 → python_executor[(15000-12000)/12000*100]→ Observation:25.0Final Answer: 技术部的平均薪资为15000元,比行业平均水平(12000元)高出25%思考 && 总结
- 工具描述是 Agent 准确调用的第一道关口:花时间把每个Tool的
description写清楚——做什么、输入什么、返回什么、什么时候该用它。这比代码实现更重要。 - 搜索引擎让 Agent 突破了"知识截止日"的限制:不用微调、不用RAG,一个搜索API就能让Agent拥有实时信息获取能力。
- 数据库查询必须加安全层:你绝对不会想让LLM直接执行它生成的SQL。读写分离 + 关键词白名单 + 行数限制,三保险。
- 代码执行器需要沙箱:限制可用的builtins函数、禁止文件操作和系统调用、超时控制——否则你的服务器就是一颗定时炸弹。
- 工具的组合是 Agent 价值的放大器:单个工具能解决的问题有限,三个工具组合起来就能处理"搜索→分析→计算"的完整数据链路。
工具多了,Agent才真正有了"手和脚"。下次别人问你"Agent能做什么"的时候,把这三个工具的运行记录给他看——比说一百句都管用。
结尾
各位小伙伴,本文的内容到这里就全部结束了,源码骑士在这里再次感谢您的阅读!
源码骑士 — Android Framework & 全栈开发
👀关注:跟博主一起从源码视角深耕底层原理,见证每一次成长
❤️点赞:让优质内容被更多人看见,让知识传递更有力量
⭐收藏:把核心知识点存好,在需要时随时查、随时用
💬评论:分享你的经验或疑问,评论区一起交流避坑
🔄一键四连:不要忘记给博主"一键四连"哦!
🗡️寄语:技术之路难免有困惑,但同行的人会让前进更有方向
结语:给Agent装工具就像给程序员配开发环境——工具越全,能做的事情就越多。本文的三个工具是你Agent工具箱的起点,之后你可以继续加邮件发送、文件操作、API调用……Agent的能力边界只受限于你的想象力。不要忘记给博主"一键四连"哦!