基于 AgentFabric 微调 Qwen-7B 实现交互式智能体应用
1. 前言
在构建大模型智能体(Agent)应用时,选择合适的基座模型至关重要。目前,使用 DashScope 提供的 Qwen-Max 或开源的 Qwen-72B 等大规模参数模型,通常能获得较好的工具调用和角色扮演效果。然而,这些大规模模型难以在消费级机器上进行本地部署,推理成本高昂。
相比之下,小模型如 Qwen-7B-Chat 虽然易于部署,但在原生状态下对复杂工具调用的能力较弱。为了在资源受限的环境下实现高效的 Agent 应用,我们需要针对特定场景(如 AgentFabric)对稍小的模型进行微调,使其具备可靠的工具调用能力。
本文旨在介绍如何利用 AgentFabric 的工具调用场景,通过数据集转换和 LoRA 微调方法,使 Qwen-7B-Chat 模型在本地部署后也能完成高质量的工具调用任务。
2. 环境安装与准备
2.1 基础环境配置
首先,需要配置 Python 环境并安装必要的依赖库。建议使用虚拟环境以避免依赖冲突。
pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/
python -m venv swift_env
source swift_env/bin/activate
2.2 安装 Swift 框架
魔搭社区提供了 Swift 框架,用于简化大模型的训练和部署流程。
git clone https://github.com/modelscope/swift.git
cd swift
pip install -e .[llm]
pip install -r requirements/framework.txt -U
pip install -r requirements/llm.txt -U
确保系统已安装 CUDA 驱动,且 PyTorch 版本与 CUDA 版本匹配。推荐使用 CUDA 11.8 或更高版本。
3. 数据准备与处理
为训练 Agent 能力,魔搭官方提供了 ms_agent 开源数据集。但直接使用通用数据集微调后的模型在 AgentFabric 上的表现往往不佳,主要问题包括:不调用工具、调用时参数错误、对工具返回结果总结错误等。
3.1 问题分析
MS-Agent 数据集的 Prompt 格式侧重于标准的 ReAct 模式,而 AgentFabric 更侧重角色扮演和应用场景的 Prompt 组织。两者存在显著差异:
MS-Agent 格式示例:
Answer the following questions as best you can. You have access to the following APIs:
1. fire_recognition: Call this tool...
Use the following format:
Thought: ...
Action: ...
Action Input: ...
Observation: ...
Final Answer: ...
AgentFabric 格式示例:
amap_weather: amap_weather API。获取对应城市的天气数据...
Action: 工具的名称...
Action Input: 工具的输入...
你扮演一个天气预报助手...
由于 Prompt 格式的错位,微调后的模型在 AgentFabric 环境中容易出现'幻觉'或无法正确解析工具参数。
3.2 数据集转换脚本
为解决上述 Prompt 格式不匹配问题,我们需要将 MS-Agent 转换为 AgentFabric 的 Prompt 组织格式。以下是核心转换逻辑的实现代码:
import json
import re
sys_prefix = "\n# 工具\n\n## 你拥有如下工具:\n\n"
def _process_system(text):
apis_info = []
api_pattern = r"(?<=\n\d\.)(.*?})(?=])"
apis = re.findall(api_pattern, text, re.DOTALL)
sys_prompt = sys_prefix
func_names = []
for api in apis:
func_name = re.search(r'(.*?):', api).group(1).strip()
func_names.append(func_name)
api_name = re.search(r'(\S+)\sAPI', api).group(1)
api_desc = re.search(r'useful for?\s(.*?)\.', api).group(1)
sys_prompt += f"{func_name}: {api_name} API。{api_desc}" + "输入参数:{\"type\": \"object\", \"properties\": {"
paras = re.findall(r"Parameters: \[({.*})", api, re.DOTALL)
required_paras = []
for para in paras:
para_name = re.search(r'"name": \"(.*?)"', para).group(1)
desc = re.search(r'"description": \"(.*?)"', para).group(1)
if re.search(r'"required": \"(.*)"', para).group(1).strip().lower() == "true":
required_paras.append(para_name)
sys_prompt += f'"{para_name}": {{"type": "string", "description": "{desc}"}}'
sys_prompt += "},\"required\": " + json.dumps(required_paras) + "} Format the arguments as a JSON object." + "\n\n"
func_names = json.dumps(func_names)
sys_prompt += f"## 当你需要调用工具时,请在你的回复中穿插如下的工具调用命令,可以根据需求调用零次或多次:\n\n工具调用\nAction: 工具的名称,必须是之一\nAction Input: 工具的输入\nObservation: <result>工具返回的结果</result>\nAnswer: 根据 Observation 总结本次工具调用返回的结果,如果结果中出现 url,请使用如下格式展示出来:\n\n\n# 指令\n\n你扮演 AI-Agent,\n你具有下列具体功能:\n下面你将开始扮演\n\n请注意:你具有图像和视频的展示能力,也具有运行代码的能力,不要在回复中说你做不到。\n"
sys_prompt
jsonl_file_path =
target_file_path =
modified_data = []
(jsonl_file_path, , encoding=) file:
line file:
json_obj = json.loads(line)
system_prompt = json_obj[][][]
json_obj[][][] = _process_system(system_prompt)
modified_data.append(json_obj)
(target_file_path, , encoding=) file:
json_obj modified_data:
file.write(json.dumps(json_obj, ensure_ascii=) + )
使用该数据集微调后,模型在 AgentFabric 上的工具调用成功率显著提升,基本能正确调用工具。但仍存在总结能力稍弱、有时无法自动停止输出等问题。
3.3 补充 AgentFabric 真实数据
MS-Agent 数据集全为英文,且缺乏 AgentFabric 特有的 Roleplay 信息。为此,我们通过开源的 AgentFabric 框架实际调用访问,收集了一些真实发送给模型的 Prompt。筛选处理后形成新增数据集,与转换后的 MS-Agent 数据混合微调,进一步修复了总结和停止能力问题。
4. 微调流程
4.1 训练配置
在 GPU 机器上执行微调。假设使用 8 张 A100 显卡,训练时间约需 2-3 小时。如果是单卡训练,需调整 nproc_per_node 参数。
cd examples/pytorch/llm
export PYTHONPATH=../../..
nproc_per_node=8
nohup torchrun \
--nproc_per_node=$nproc_per_node \
--master_port 29500 \
llm_sft.py \
--model_id_or_path qwen/Qwen-7B-Chat \
--model_revision master \
--sft_type lora \
--tuner_backend swift \
--dtype AUTO \
--output_dir output \
--custom_train_dataset_path ms_agent_for_agentfabric/new_ms_agent.jsonl ms_agent_for_agentfabric/addition.jsonl \
--train_dataset_mix_ratio 2.0 \
--train_dataset_sample -1 \
--num_train_epochs 2 \
--max_length 2048 \
--check_dataset_strategy warning \
--lora_rank 8 \
--lora_alpha 32 \
--lora_dropout_p 0.05 \
--lora_target_modules ALL \
--self_cognition_sample 3000 \
--model_name 卡卡罗特 \
--model_author 陶白白 \
--gradient_checkpointing true \
--batch_size 2 \
--weight_decay 0.01 \
--learning_rate 5e-5 \
--gradient_accumulation_steps $(expr 1 / $nproc_per_node) \
--max_grad_norm 0.5 \
--warmup_ratio 0.03 \
--eval_steps 100 \
--save_steps 100 \
--save_total_limit 2 \
--logging_steps 10 &
训练完成后,查看 nohup.out 文件以获取最佳 Checkpoint 路径:
[INFO:swift] best_model_checkpoint: /home/workspace/swift/examples/pytorch/llm/output/qwen-7b-chat/v0-20240314-211944/checkpoint-2828
5. 模型部署
5.1 合并 LoRA 权重
由于使用了 sft_type=lora,部署前需要将 LoRA 权重合并到原始模型中,以便直接加载推理。
python tools/merge_lora_weights_to_model.py \
--model_id_or_path /dir/to/your/base/model \
--model_revision master \
--ckpt_dir /dir/to/your/lora/model
其中 /dir/to/your/base/model 为基模型路径(如 qwen/Qwen-7B-Chat),/dir/to/your/lora/model 为训练得到的最佳 checkpoint 路径。
5.2 拉起服务
使用 vLLM 进行高效部署。
nohup python -m vllm.entrypoints.openai.api_server \
--model /dir/to/your/model-merged \
--trust-remote-code &
当日志显示 Uvicorn running on http://0.0.0.0:8000 时,表示服务启动成功。
5.3 接口测试
curl http://localhost:8000/v1/completions \
-H "Content-Type: application/json" \
-d '{"model": "/dir/to/your/model-merged", "prompt": "San Francisco is a", "max_tokens": 7, "temperature": 0}'
6. 集成与应用
6.1 简单测试
可通过 Python 代码直接测试模型能力。
from modelscope_agent.agents.role_play import RolePlay
def test_weather_role():
role_template = '你扮演一个天气预报助手,你需要查询相应地区的天气,并调用给你的画图工具绘制一张城市的图。'
llm_config = {
"model_server": "openai",
"model": "/dir/to/your/model-merged",
"api_base": "http://localhost:8000/v1",
"is_chat": True,
"is_function_call": False,
"support_stream": False
}
function_list = ['amap_weather']
bot = RolePlay(function_list=function_list, llm=llm_config, instruction=role_template)
response = bot.run('朝阳区天气怎样?')
text = ''
for chunk in response:
text += chunk
print(text)
assert isinstance(text, str)
test_weather_role()
6.2 AgentFabric 中使用
- 进入 AgentFabric 目录:
cd modelscope-agent/apps/agentfabric
- 修改
config/model_config.json,新增本地模型配置:
"my-qwen-7b-chat": {
"type": "openai",
"model": "/dir/to/your/model-merged",
"api_base": "http://localhost:8000/v1",
"is_chat": true,
"is_function_call": false,
"support_stream": false
}
- 启动 Gradio 界面:
GRADIO_SERVER_NAME=0.0.0.0 PYTHONPATH=../../ python app.py
- 在浏览器访问
服务器 IP:7860 即可使用。
7. 常见问题与优化建议
7.1 显存不足
如果在训练或部署过程中遇到 OOM (Out Of Memory) 错误,可以尝试以下优化:
- 减小
batch_size。
- 开启
gradient_checkpointing(已在脚本中启用)。
- 使用更低精度的数据类型(如
--dtype BF16)。
7.2 工具调用失败
如果微调后模型仍偶尔无法调用工具,检查以下几点:
- 确认 System Prompt 中的工具描述是否准确无误。
- 检查训练数据中是否包含足够的正样本(成功调用工具的场景)。
- 适当增加
max_length,允许模型生成更长的思考链。
7.3 响应超时
vLLM 部署时若响应过慢,可调整 gpu_memory_utilization 参数,默认通常为 0.9,可根据显存情况调整至 0.85 或 0.95。
8. 总结
本文详细介绍了如何基于 AgentFabric 框架,利用 Qwen-7B-Chat 模型进行微调以实现交互式智能体应用。通过数据格式转换和混合数据集训练,有效解决了小模型在特定 Agent 框架下工具调用能力弱的问题。该方法不仅降低了硬件成本,还使得在私有化部署场景下构建高性能 Agent 成为可能。后续工作中,可进一步探索多模态数据的融合以及更复杂的任务规划能力。