7步构建智能工具调用系统:Swift Agent全栈开发指南
你是否还在为LLM无法连接现实世界而烦恼?是否尝试过构建工具调用系统却被复杂的模板设计和流程控制劝退?本文将带你用Swift框架从零开始构建生产级Agent系统,无需深厚AI背景,只需掌握基础Python即可上手。读完本文你将获得:完整的Agent开发技术栈、3种主流工具调用模板实现、5个核心功能模块的代码示例,以及1套可直接部署的训练推理流程。
技术架构概览:Swift Agent的5层金字塔
Swift框架采用模块化设计,将Agent系统拆解为5个核心层级,每层都提供可复用的组件和接口。这种架构既保证了灵活性,又降低了开发门槛,即使是新手也能快速组合出强大的智能工具调用系统。
图1:Swift Agent的五层技术架构,从底层的模型引擎到顶层的应用层,每层都有明确的职责边界
核心模块解析
-
模型引擎层:位于架构最底部,负责模型加载、推理加速和资源管理。支持多种后端引擎,包括PyTorch原生引擎(swift/llm/PtEngine)、vLLM和LMDeploy等优化引擎,可根据硬件条件灵活切换。
-
工具调用层:核心层,处理工具定义解析、调用决策和结果解析。提供了丰富的模板系统,支持不同模型的工具调用格式,如React、Qwen、Hermes等。
-
流程控制层:管理多轮对话状态和工具调用流程,决定何时调用工具、何时直接回答。支持并行工具调用和顺序调用两种模式,满足不同场景需求。
-
应用层:提供开箱即用的Agent应用示例,如命令行交互工具(examples/infer/cli_demo.sh)和Web界面(swift/ui/llm_infer),方便快速部署和测试。
-
扩展层:包括自定义工具开发接口和插件系统,允许开发者扩展Agent能力,如添加新的工具类型或集成第三方服务。
快速上手:15分钟构建天气查询Agent
让我们通过一个实际案例来体验Swift Agent的开发流程。这个案例将构建一个能够查询天气的智能Agent,用户只需输入自然语言问题,Agent会自动调用天气工具获取数据并整理成自然语言回答。
步骤1:环境准备与项目克隆
首先确保你的环境满足以下要求:Python 3.8+、CUDA 11.7+、PyTorch 2.0+。然后克隆项目并安装依赖:
git clone https://gitcode.com/GitHub_Trending/swift1/swift
cd swift
pip install -r requirements.txt
步骤2:理解工具定义格式
在Swift中,工具定义遵循JSON Schema规范,包含名称、描述和参数等信息。以下是天气查询工具的定义示例:
{
"name": "get_current_weather",
"description": "Get the current weather in a given location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, e.g. San Francisco, CA"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"]
}
},
"required": ["location"]
}
}
这个定义告诉Agent:工具名称是get_current_weather,需要传入location参数(必填)和unit参数(可选,默认摄氏度)。Agent会根据这个定义生成合适的工具调用请求。
步骤3:创建推理请求与工具绑定
接下来,我们需要创建一个推理请求,包含用户问题和可用工具列表。打开examples/infer/demo_agent.py,可以看到以下关键代码:
def get_infer_request():
return InferRequest(
messages=[{
'role': 'user',
'content': "How's the weather in Beijing today?"
}],
tools=[{
'name': 'get_current_weather',
'description': 'Get the current weather in a given location',
'parameters': {
'type': 'object',
'properties': {
'location': {
'type': 'string',
'description': 'The city and state, e.g. San Francisco, CA'
},
'unit': {
'type': 'string',
'enum': ['celsius', 'fahrenheit']
}
},
'required': ['location']
}
}])
这段代码定义了一个包含天气查询工具的推理请求,用户的问题是询问北京今天的天气。
步骤4:选择工具调用模板
Swift提供了多种工具调用模板,适用于不同模型和场景。常见的模板包括:
- React模板:通用模板,使用Action/Action Input/Observation格式,兼容性好
- Qwen模板:专为Qwen系列模型优化,支持并行工具调用
- Hermes模板:适合长对话场景,记忆管理更高效
在代码中,我们可以通过以下方式选择模板:
from swift.plugin import agent_templates
agent_template = agent_templates['hermes']() # 选择Hermes模板
engine.default_template.agent_template = agent_template
不同模板的实现可以在swift/plugin/agent_template/目录中找到,例如React模板(react.py)和Qwen模板(qwen.py)。
步骤5:运行推理与解析结果
准备工作完成后,就可以运行推理并获取结果了。以下是关键代码片段:
def infer(engine: 'InferEngine', infer_request: 'InferRequest'):
stop = [engine.default_template.agent_template.keyword.observation]
request_config = RequestConfig(max_tokens=512, temperature=0, stop=stop)
resp_list = engine.infer([infer_request], request_config)
query = infer_request.messages[0]['content']
response = resp_list[0].choices[0].message.content
print(f'query: {query}')
print(f'response: {response}')
print(f'tool_calls: {resp_list[0].choices[0].message.tool_calls}')
运行脚本后,你会看到类似以下的输出:
query: How's the weather in Beijing today?
response: Action: get_current_weather
Action Input: {"location": "Beijing"}
Observation:
tool_calls: [{'name': 'get_current_weather', 'arguments': '{"location": "Beijing"}'}]
这表明Agent正确理解了用户问题,并决定调用get_current_weather工具,传入参数{"location": "Beijing"}。
步骤6:处理工具返回结果
获取工具调用请求后,我们需要将其发送给实际的天气API,获取结果后再返回给Agent进行整理。在示例中,我们使用模拟数据来演示这一过程:
tool = '{"temperature": 32, "condition": "Sunny", "humidity": 50}'
print(f'tool_response: {tool}')
infer_request.messages += [
{'role': 'assistant', 'content': response},
{'role': 'tool', 'content': tool}
]
resp_list = engine.infer([infer_request], request_config)
response2 = resp_list[0].choices[0].message.content
print(f'response2: {response2}')
再次运行推理后,Agent会根据工具返回的结果生成自然语言回答:
response2: The weather in Beijing today is sunny with a temperature of 32°C and humidity of 50%.
步骤7:流式输出与用户体验优化
为了提升用户体验,Swift支持流式输出功能,可以实时展示Agent的思考和工具调用过程。相关代码在infer_stream函数中实现:
def infer_stream(engine: 'InferEngine', infer_request: 'InferRequest'):
stop = [engine.default_template.agent_template.keyword.observation]
request_config = RequestConfig(max_tokens=512, temperature=0, stream=True, stop=stop)
gen_list = engine.infer([infer_request], request_config)
query = infer_request.messages[0]['content']
response = ''
print(f'query: {query}\nresponse: ', end='')
for resp in gen_list[0]:
if resp is None:
continue
delta = resp.choices[0].delta.content
response += delta
print(delta, end='', flush=True)
print()
流式输出可以让用户看到Agent的"思考过程",而不是等待整个回答生成,这在处理复杂任务时尤为重要。
深度定制:从模板到训练的全流程优化
基础案例展示了Swift Agent的易用性,接下来我们将深入探讨如何定制和优化Agent系统,包括选择合适的模板、训练专属于你的Agent模型,以及性能调优技巧。
模板选择指南:3大主流模板对比
Swift提供了多种工具调用模板,每种模板都有其适用场景和特点。选择合适的模板可以显著提升Agent的性能和可靠性。
| 模板类型 | 优势 | 适用场景 | 代表模型 | 实现文件 |
|---|---|---|---|---|
| React | 兼容性好,支持大多数模型 | 通用场景,多轮工具调用 | LLaMA系列、Mistral | react.py |
| Qwen | 支持并行工具调用,效率高 | 需要同时调用多个工具的场景 | Qwen系列 | qwen.py |
| Hermes | 长对话管理能力强 | 持续对话场景,如客服机器人 | Hermes系列 | hermes.py |
模板的核心功能在BaseAgentTemplate中定义,包括工具解析、调用生成和结果处理等基础方法。自定义模板时,只需继承该类并实现抽象方法即可。
训练专属Agent:从数据到部署的完整流程
虽然可以直接使用预训练模型构建Agent,但为特定场景训练专属模型可以获得更好的效果。Swift提供了完整的训练流程,支持全参数微调、LoRA等多种训练方式。
数据准备
Agent训练需要工具调用格式的数据,推荐使用AI-ModelScope/function-calling-chatml数据集,包含丰富的工具调用样本。
启动训练
以Qwen2.5模型为例,使用以下命令启动训练:
CUDA_VISIBLE_DEVICES=0 \
swift sft \
--model Qwen/Qwen2.5-3B \
--train_type full \
--dataset AI-ModelScope/function-calling-chatml \
--agent_template hermes \
--torch_dtype bfloat16 \
--num_train_epochs 2 \
--per_device_train_batch_size 1 \
--learning_rate 1e-5 \
--max_length 8192 \
--output_dir output/qwen2.5-agent \
--attn_impl flash_attn
完整的训练脚本可参考examples/train/agent/qwen2_5.sh。训练过程中,关键参数包括:
--agent_template:指定训练使用的工具调用模板--max_length:根据工具调用复杂度调整,建议8192或更高--attn_impl flash_attn:启用FlashAttention加速训练
评估与部署
训练完成后,可以使用examples/eval/llm目录下的脚本评估模型性能。部署时,推荐使用vLLM后端以获得最佳性能:
CUDA_VISIBLE_DEVICES=0 \
python examples/infer/demo_agent.py \
--model path/to/your/trained/model \
--infer_backend vllm
高级技巧:打造生产级Agent系统
要将Agent系统从原型推向生产,还需要考虑性能优化、错误处理和安全防护等关键问题。本节将分享几个实用技巧,帮助你构建稳定可靠的Agent系统。
多引擎切换:根据场景选择最优后端
Swift支持多种推理引擎,各有优缺点,可根据实际场景灵活选择:
- PyTorch引擎:兼容性最好,支持所有模型和特性,但性能一般。适合开发和测试阶段。
engine = PtEngine(model, max_batch_size=64)
- vLLM引擎:吞吐量高,响应速度快,支持长序列。适合高并发场景。
from swift.llm import VllmEngine
engine = VllmEngine(model, max_model_len=8192)
- LMDeploy引擎:内存占用低,支持多模态模型。适合资源受限环境或需要处理图像输入的场景。
from swift.llm import LmdeployEngine
engine = LmdeployEngine(model)
错误处理与重试机制
在实际应用中,工具调用可能会失败,如API超时、参数错误等。因此,实现完善的错误处理机制至关重要。以下是一个简单的重试逻辑示例:
def call_tool_with_retry(tool_name, arguments, max_retries=3):
for i in range(max_retries):
try:
result = call_actual_tool(tool_name, arguments)
return result
except Exception as e:
if i == max_retries - 1:
return f"Error calling tool {tool_name}: {str(e)}"
time.sleep(1) # 重试前等待1秒
更复杂的错误处理策略可以参考swift/llm/app/agent.py中的实现。
性能优化:减少响应时间的5个技巧
-
启用流式推理:使用
stream=True参数,让用户实时看到Agent的思考过程,减少感知等待时间。 -
模型量化:使用INT4/INT8量化减少内存占用,提高推理速度。相关工具在examples/export/quantize目录。
-
工具调用缓存:对相同参数的工具调用结果进行缓存,避免重复请求。
-
批处理请求:在高并发场景下,使用批处理减少模型调用次数。
-
合理设置max_tokens:根据工具返回结果的预期长度设置,避免不必要的长文本生成。
总结与未来展望
通过本文的介绍,你已经掌握了使用Swift框架构建Agent系统的核心技术,包括基础架构、快速上手流程、模型训练和性能优化等方面。Swift提供的模块化设计和丰富的工具链,大大降低了Agent开发的门槛,使你能够专注于业务逻辑而非底层实现。
随着大模型技术的不断发展,Agent系统将在更多领域发挥重要作用。Swift团队也在持续优化框架,未来将支持更复杂的多Agent协作、更智能的工具选择策略,以及更高效的资源管理。
如果你在使用过程中遇到问题,欢迎查阅官方文档或加入社区交流:
最后,别忘了点赞收藏本文,关注项目更新,下期我们将带来"多Agent协作系统设计"的深度解析,敬请期待!
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考






