🔗 参考文章:知乎 - Qwen-Agent 实战
在大模型时代,LLM 不仅能「对话」,更能结合各种工具,变成超能助手。比如——
✅ 能写 SQL
✅ 能操作数据库
✅ 能帮你执行数据分析
这就是 工具调用 (Tool-Calling) 的魅力。而阿里通义 Qwen 团队推出的 Qwen-Agent,帮我们轻松把 LLM 和各种工具串起来。
今天这篇文章,就手把手教你:
- 如何用 Qwen-Agent + MCP + uvx
- 让大模型化身一名真正的 数据库管理员
- 从 0 到 1 创建数据库表,并写入数据
跟着做,你也能拥有自己的 AI DBA!
🌟 项目亮点
这篇文章的方案核心有三大亮点:
✅ Qwen-Agent:通义团队官方 Agent 框架,封装了 LLM 调用流程,支持 Tool Calling
✅ MCP (Multi-Channel Processor):类似 Function Calling,但更通用。支持将外部工具注册为 MCP Server,LLM 调用时只需要传 JSON,就能远程执行
✅ uvx:超轻量级多进程异步工具,可用来快速构建 MCP Server
在这篇实战里,我们用 uvx 启动 SQLite 的 MCP Server,让 LLM 具备真正的「写数据库」能力。
⚙️ 环境安装
下面在 Python 3.10 环境里安装依赖:
# Python3.10 环境
pip install qwen_agent
pip install python-dateutil
pip install dotenv
pip install -U mcp
pip install uv
各依赖的作用:
库名 | 作用 |
---|---|
qwen_agent | 通义 Qwen 官方 Agent 框架 |
python-dateutil | 时间工具,Agent 框架常用 |
dotenv | 加载环境变量 |
mcp | MCP 协议实现 |
uv | 启动 MCP Server 的轻量工具 |
💡 技术原理
很多人会问:
「Qwen-Agent 怎么帮 LLM 调用数据库?」
核心原理就两个字:工具 (Tool)。
Qwen-Agent 定义工具的方法,和 OpenAI Function Calling 非常像,就是描述一个 JSON Schema:
{
"mcpServers": {
"sqlite": {
"command": "uvx",
"args": [
"mcp-server-sqlite",
"--db-path",
"test.db"
]
}
}
}
- LLM 只需要输出一段 JSON,Qwen-Agent 就会帮它把 JSON 参数发送到 MCP Server
- MCP Server 执行真正的系统指令,比如写入 SQLite
- 再把结果返回给 LLM
这样 LLM 就能「动手」执行外部操作,而不仅仅是生成文本。
📝 完整代码实战
下面上完整 Python 代码,一步到位:
1. 导入依赖
from qwen_agent.agents import Assistant
from qwen_agent.utils.output_beautify import typewriter_print
2. 初始化 Agent
先定义 LLM 配置,以及 MCP Tool:
def init_agent_service():
llm_cfg = {
'model': 'qwen-plus-0112',
'model_server': 'dashscope',
'api_key': 'sk-xxxxxxxxxxxxxxxxxxxxxxx', # 填入你自己的 API Key
'generate_cfg': {
'top_p': 0.8
}
}
tools = [{
"mcpServers": {
"sqlite": {
"command": "uvx",
"args": [
"mcp-server-sqlite",
"--db-path",
"test.db"
]
}
}
}]
bot = Assistant(
llm=llm_cfg,
name='数据库管理员',
description='你是一位数据库管理员,具有对本地数据库的增删改查能力',
system_message='你扮演一个数据库助手,你具有查询数据库的能力',
function_list=tools,
)
return bot
这段配置里,重点:
- MCP Server 用 uvx 启动
mcp-server-sqlite
- SQLite 文件是
test.db
- 这样 LLM 就能执行 SQLite 命令
3. 执行对话
我们写一个 run_query 方法,用来向 Agent 发出 SQL 请求:
def run_query(query=None):
bot = init_agent_service()
messages = []
messages.append({'role': 'user', 'content': [{'text': query}]})
previous_text = ""
print('数据库管理员: ', end='', flush=True)
for response in bot.run(messages):
previous_text = typewriter_print(response, previous_text)
这里做了:
- 创建 User Prompt
- 用
bot.run()
循环获取流式回复 - 用
typewriter_print
优雅打印 LLM 输出
4. 测试案例
比如,我们让 LLM 创建表 + 插入一条数据:
if __name__ == '__main__':
query = '''
帮我创建一个学生表,
表名是students,
包含id, name, age, gender, score字段,
然后插入一条数据,
id为1, name为张三, age为20, gender为男, score为95
'''
run_query(query)
💻 效果演示
如果你环境都配好,执行以上脚本,你将看到类似效果:
数据库管理员: 好的,正在创建表 students...
创建成功!已插入数据:
id=1, name=张三, age=20, gender=男, score=95
👇 示意图:
是不是很酷? 你已经拥有了一个可以真正写数据库的 AI DBA!
❓ 常见问题
uvx 是什么?
uvx
是一个超轻量的进程执行器,能快速运行子进程并管理异步 I/O。它在 Qwen-Agent 里常被用来启动 MCP Server。
MCP 和 Function Calling 有啥区别?
特点 | MCP | Function Calling |
---|---|---|
调用协议 | JSON Schema + Server | JSON Schema + 内部执行 |
可调用外部进程 | ✅ | ❌ |
灵活度 | 更强 | 相对有限 |
所以 MCP 不仅能写代码,还能执行系统级命令,适合更复杂的场景。
🔗 参考资料
🔥 小结
今天,你学会了:
✅ Qwen-Agent 基本用法
✅ MCP 的工作原理
✅ 如何让 LLM 写 SQLite
未来,你可以继续拓展:
- MySQL / Postgres MCP
- 本地文件系统操作
- 调用爬虫或爬取数据
大模型 + MCP,让你的工具链无限可能!
快去试试吧 🚀
完整代码如下,跑起来就是一个小型 AI DBA。祝你玩得开心!🚀
from qwen_agent.agents import Assistant
from qwen_agent.utils.output_beautify import typewriter_print
def init_agent_service():
llm_cfg={
'model': 'qwen-plus-0112',
'model_server': 'dashscope',
'api_key': 'sk-xxxxxxxxxxxxxxxxxxxxxxx',
'generate_cfg':{
'top_p': 0.8
}
}
# 定义MCP服务配置,优点类似Function Calling调用的JSON Schema格式
tools = [{
"mcpServers": {
"sqlite": {
"command": "uvx",
"args": [
"mcp-server-sqlite",
"--db-path",
"test.db"
]
}
}
}]
bot = Assistant(
llm=llm_cfg,
name='数据库管理员',
description='你是一位数据库管理员,具有对本地数据库的增删改查能力',
system_message='你扮演一个数据库助手,你具有查询数据库的能力',
function_list=tools,
)
return bot
def run_query(query=None):
# 定义数据库助手
bot = init_agent_service()
# 执行对话逻辑
messages = []
messages.append({'role': 'user', 'content': [{'text': query}]})
# 跟踪前一次的输出,用于增量打印
previous_text = ""
print('数据库管理员: ', end='', flush=True)
for response in bot.run(messages):
previous_text = typewriter_print(response, previous_text)
if __name__ == '__main__':
query = '帮我创建一个学生表,表名是students,包含id, name, age, gender, score字段,然后插入一条数据,id为1,name为张三,age为20,gender为男,score为95'
run_query(query)