7.3 工具类型与能力框架《AI智能体应用开发》
AI智能体应用开发 鲍亮崔江涛李倩范涛 清华大学出版社【行情 报价 价格 评测】-京东
《AI智能体应用开发》1~6章试读-CSDN博客
在7.1节和7.2节中,我们系统地阐述了智能体工具能力的概念、核心机制与重要性,为其勾勒了一幅宏观的理论蓝图。然而,要真正驾驭这项能力,我们需要从抽象走向具体,从理论走向实践。本章将带领读者深入智能体的“工具箱”,通过具体的、可运行的实例,拆解不同类型的工具如何被集成与调用,从而构建起一个直观的能力框架。
本节假设读者拥有大模型调用的基础知识。为了方便且专业地演示这些实例,我们将选用LangChain[2]这一广泛使用的开源框架。LangChain并非唯一选择,但它为智能体与工具的集成提供了层次清晰、模块化的优秀抽象,极大地简化了将大语言模型与外部能力组合在一起的过程。在本章中,我们使用LangChain的目的在于:快速、规范地构建一个具备工具调用能力的智能体原型,并以其为标准范例,阐释工具集成的通用模式和内在原理。我们将重点分析两类基础但至关重要的工具:信息获取类(以数据库为例)和推理与计算类(数值计算与代码执行)。
7.3.1 数据库
在许多实际应用场景中,智能体需要与组织的核心数据资产—数据库进行交互。例如,一个客户服务智能体可能需要查询订单状态;一个数据分析智能体可能需要汇总销售报表;一个内部管理智能体可能需要检索员工信息。让智能体直接、安全地查询数据库,可以使其回答基于真实、最新的业务数据,价值巨大。
为了演示,我们假设一个简化的电商业务数据库test.db,使用SQLite3作为数据库,包含如图7-1所示的表结构。
图7-1 数据库ER图
代码清单7.1展示了如何使用LangChain构建一个能够理解自然语言问题并生成正确SQL查询的数据库查询智能体。为了缩小代码占用的篇章,7.3.2节及之后的代码依赖引入部分略去,详细的代码可以参考本书之后提供的代码仓库。
代码清单7.1:数据库工具调用实例
from langchain_community.utilities.sql_database import SQLDatabase
from langchain_openai import ChatOpenAI
from langchain_community.agent_toolkits.sql.toolkit import SQLDatabaseToolkit
from langchain.agents import create_agent
from dotenv import load_dotenv
from langchain_core.prompts import SystemMessagePromptTemplate
from prompt import PROMPT_TEMPLATE
load_dotenv("../.env")
db = SQLDatabase.from_uri("sqlite:///test.db")
llm = ChatOpenAI(model='qwen-plus', temperature=0)
toolkit = SQLDatabaseToolkit(db=db, llm=llm)
system_message =
SystemMessagePromptTemplate.from_template(PROMPT_TEMPLATE).format(dialect="SQLite", top_k=5) # PROMPT_TEMPLATE见代码仓库
agent = create_agent(llm, toolkit.get_tools(), system_prompt=system_message)
example_query = "Alice购买了哪些商品"
events = agent.stream(
{"messages": [("user", example_query)]},
stream_mode="values",
)
for event in events:
event["messages"][-1].pretty_print()
代码首先进行了工具封装,SQLDatabaseToolkit是关键组件,它将数据库操作封装成智能体可理解和调用的工具。根据LangChain的SQLDatabaseToolkit文档[3]说明,它提供了InfoSQLDatabaseTool、ListSQLDatabaseTool、QuerySQLCheckerTool、QuerySQLDatabaseTool,分别用于获取数据库元信息、列出数据库包含的表格、检查SQL的正确性、查询数据库。执行流程如表7-1所示。
上述流程稍微有些复杂,从上述智能体执行流程可以看出,智能体在面对用户查询时,展现了一套完整、结构化的问题解决路径。整个过程体现了其自主决策、分步验证与高效执行的特点。
1. 问题理解与目标拆解
智能体首先明确用户查询意图—“Alice购买了哪些商品”,并将其转化为从数据库中检索的具体任务,而非直接尝试猜测或简单回应。
2. 环境探查与信息获取
智能体没有立即编写查询,而是先通过工具理清数据库结构。
3. 方案生成与安全验证
在理解表结构后,智能体主动构建SQL查询语句,并进行语法和逻辑检查。这一步体现了其在执行前的谨慎态度,避免无效或危险查询,提升系统安全性与可靠性。
4. 执行查询与结果整合
确认查询无误后,智能体执行查询,获取原始结果[('Laptop',), ('Phone',)],并将其转化为用户友好的表述形式,清晰列出商品名称。
5. 闭环输出与任务完成
最终,智能体以清晰条目形式总结答案,响应用户初始问题,完成交互闭环。
最后请注意,数据库是核心业务系统,其访问必须受到最严格的限制!对于可能更改数据库内容的权限,强烈建议不要配置到工具中,否则可能会导致数据库内容发生不预期的变更,仅授予查询的权限即可。
7.3.2 数值计算
大语言模型处理数学问题依赖于其在训练数据中见过的数字模式和计算“印象”,本质上是一种基于统计的“估算”,而非精确计算。对于简单算术可能有效,但对于复杂表达式、金融计算或科学计算,其出错概率极高。因此,一个可靠的数值计算工具是必不可少的。
代码清单7.2展示了如何创建一个最简单的自定义计算工具,并将其赋予智能体。
和7.3.1节不同,这里使用@tool装饰器自定义了一个calculate工具,并且简单地使用了eval作为求值的逻辑。需要说明的是,本例中直接使用eval()是极其危险的,因为它会执行输入字符串中的任何有效Python代码。恶意用户可能输入“__import__('os').system('rm-rf/')”这样的指令。这只是一个为演示工具集成原理的最小化示例。一个安全的数值计算工具应该使用安全的数学表达式解析库(如ast.literal_eval,或专门的库,如numexpr、sympy),严格限制可用的运算符和函数白名单,并且在沙箱环境中执行计算。一个较为详细的数值计算工具定义可以参考strands-agents的工具集[4]。由于逻辑较为简单,本例不进行智能体的流程演示,读者可以运行代码并观察智能体的行为。
7.3.3 代码执行
代码执行工具为智能体赋予了前所未有的强大能力。它允许智能体通过编写代码来解决其内部模型无法直接处理的复杂问题,例如数据处理、文件操作、调用特定库函数、实现复杂算法等。这极大地扩展了智能体的行动边界,使其从顾问升级为执行者。
我们可以使用LangChain提供的PythonREPL工具,简单地进行测试,可以参考本书的代码仓库tool-example/numeric_example/repl.py。注意,代码执行工具风险等级更高!这允许智能体执行未经审查的代码,必须配备极其严密的防护措施。我们必须在完全隔离的沙箱(如Docker容器、轻量级虚拟机、或基于操作系统级别的沙箱技术)中运行PythonREPL。这个环境应该无网络访问权限,且与主机文件系统隔离,并且也应该进行文件系统访问控制、资源限制等风险控制。
代码清单7.2:数值计算工具调用实例
load_dotenv('../.env')
@tool
def calculate(expression):
'''
calculate an expression
'''
return eval(expression)
llm = ChatOpenAI(model='qwen-plus', temperature=0)
agent = create_agent(
model = llm,
tools = [calculate]
)
example_query = "帮我计算(1234 * 56) % 11"
events = agent.stream(
{"messages": [("user", example_query)]},
stream_mode="values",
)
for event in events:
event["messages"][-1].pretty_print()