前言
今天给大家分享Qwen Agent中mcp & function calling调用的流程。通过分析调用流程,我们可以清楚地了解底层原理,了解输入输出如何适配工具调用。整体示意效果如下:
为了保证结果的完整性,我将保留所有输入输出,篇幅可能较长。重点关注每个轮次messages是如何变化的,role角色如何轮换、tool call相关信息等。
demo设定
sqlite是MCP工具,封装了一系列本地数据库增删改查的操作。提前在数据库中建了几张表,并插入了几条记录。
students 表
id
: 整数类型,主键。name
: 文本类型,不能为空。age
: 整数类型,不能为空。
sqlite_sequence 表
这个表通常由 SQLite 自动维护,用于支持 AUTOINCREMENT 字段。
name
: 文本类型,默认值和是否为空未指定。seq
: 序列号,类型未指定。
log 表
id
: 整数类型,主键。action
: 文本类型,可以为空。timestamp
: 日期时间类型,默认值为当前时间戳(CURRENT_TIMESTAMP),可以为空。
现在我期望agent帮我完成数据库操作相关的事情,通过自然语言对话驱动。事情可以包括几类:
- 简单动作:如数据库有几张表;
- 并行操作类动作:如查看3张表的数据量,期望能并行;
- 串行依赖类动作:如查看student表的某个同学的年龄,然后在log表中记录。
我将完整呈现1次会话,所有LLM的input、output,以及Qwen对input和output的预处理和后处理。
测试的模型包括Qwen-Max,DeepSeek-R1,Qwen3等,整体表现都还不错,不做特别区分。
MCP接入
我们提供的sqlite mcp配置:
tools = [{
"mcpServers": {
"sqlite" : {
"command": "uvx",
"args": [
"mcp-server-sqlite",
"--db-path",
"test.db"
]
}
}
}]
实际可用的tools有6个:
MCPManager代理:单例模式,管理mcp工具,管理clients(工具获取、工具创建、工具调用)
- mcp_manager.py - 109 - INFO - Initializing MCP tools from mcpservers config: {'mcpServers': {'sqlite': {'command': 'uvx', 'args': ['mcp-server-sqlite', '--db-path', 'test.db']}}}
- mcp_manager.py - 246 - INFO - Will initialize a MCP stdio_client, if this takes forever, please check whether the mcp config is correct: {'command': 'uvx', 'args': ['mcp-server-sqlite', '--db-path', 'test.db']}

核心实现init_config_async:基于用户提供的配置,在create_tool_class中创建MCP Tool,继承自Qwen Agent的工具基础类BaseTool,实现调用。
class MCPManager:
_instance = None# Private class variable to store the unique instance
def __new__(cls, *args, **kwargs):
if cls._instance isNone:
cls._instance = super(MCPManager, cls).__new__(cls, *args, **kwargs)
return cls._instance
...
async def init_config_async(self, config: Dict):
tools: list = []
mcp_servers = config['mcpServers']
for server_name in mcp_servers:
client = MCPClient()
server = mcp_servers[server_name]
await client.connection_server(server) # Attempt to connect to the server
client_id = server_name + '_' + str(uuid.uuid4()) # To allow the same server name be used across different running agents
self.clients[client_id] = client # Add to clients dict after successful connection
for tool in client.tools:
"""MCP tool example:
{
"name": "read_query",
"description": "Execute a SELECT query on the SQLite database",
"inputSchema": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "SELECT SQL query to execute"
}
},
"required": ["query"]
}
"""
parameters = tool.inputSchema
# The required field in inputSchema may be empty and needs to be initialized.
if'required'notin parameters:
parameters['required'] = []
# Remove keys from parameters that do not conform to the standard OpenAI schema
# Check if the required fields exist
required_fields = {'type', 'properties', 'required'}
missing_fields = required_fields - parameters.keys()
if missing_fields:
raise ValueError(f'Missing required fields in schema: {missing_fields}')
# Keep only the necessary fields
cleaned_parameters = {
'type': parameters['type'],
'properties': parameters['properties'],
'required': parameters['required']
}
register_name = server_name + '-' + tool.name
agent_tool = self.create_tool_class(register_name=register_name, register_client_id=client_id,
tool_name=tool.name, tool_desc=tool.description, tool_parameters=cleaned_parameters)
tools.append(agent_tool)
return tools
def create_tool_class(self, register_name, register_client_id, tool_name, tool_desc, tool_parameters):
class ToolClass(BaseTool):
name = register_name
description = tool_desc
parameters = tool_parameters
client_id = register_client_id
def call(self, params: Union[str, dict], **kwargs) -> str:
tool_args = json.loads(params)
# Submit coroutine to the event loop and wait for the result
manager = MCPManager()
client = manager.clients[register_client_id]
future = asyncio.run_coroutine_threadsafe(client.execute_function(tool_name, tool_args), manager.loop)
try:
result = future.result()
return result
except Exception as e:
logger.info(f'Failed in executing MCP tool: {e}')
raise e
ToolClass.__name__ = f'{register_name}_Class'
return ToolClass()
mcp client:连接服务器,包括sse模式和Stdio模式,返回可用tools、执行调用返回结果。
class MCPClient:
def __init__(self):
from mcp import ClientSession
# Initialize session and client objects
self.session: Optional[ClientSession] = None
self.tools: list = None
self.exit_stack = AsyncExitStack()
async def connection_server(self, mcp_server):
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
from mcp.client.sse import sse_client
"""Connect to an MCP server and retrieve the available tools."""
try:
if'url'in mcp_server:
self._streams_context = sse_client(url=mcp_server.get('url'), headers=mcp_server.get('headers', {"Accept": "text/event-stream"}))
streams = await self.exit_stack.enter_async_context(self._streams_context)
self._session_context = ClientSession(*streams)
self.session = await self.exit_stack.enter_async_context(self._session_context)
else:
server_params = StdioServerParameters(
command = mcp_server["command"],
args = mcp_server["args"],
env = mcp_server.get("env", None)
)
stdio_transport = await self.exit_stack.enter_async_context(stdio_client(server_params))
self.stdio, self.write = stdio_transport
self.session = await self.exit_stack.enter_async_context(ClientSession(self.stdio, self.write))
logger.info(f'Will initialize a MCP stdio_client, if this takes forever, please check whether the mcp config is correct: {mcp_server}')
await self.session.initialize()
list_tools = await self.session.list_tools()
self.tools = list_tools.tools
except Exception as e:
logger.info(f"Failed in connecting to MCP server: {e}")
raise e
async def execute_function(self, tool_name, tool_args: dict):
response = await self.session.call_tool(tool_name, tool_args)
texts = []
for content in response.content:
if content.type == 'text':
texts.append(content.text)
if texts:
return'\n\n'.join(texts)
else:
return'execute error'
async def cleanup(self):
await self.exit_stack.aclose()
Round 1:数据库有几张表
原始Input:
[ { 'content': '你扮演一个数据库助手,你具有查询数据库的能力',
'reasoning_content': '',
'role': 'system'},
{ 'content': [{'text': '数据库有几张表'}],
'name': 'user',
'reasoning_content': '',
'role': 'user'}]
预处理后的Input:模型真正的输入,会将tools列表和功能描述作为system prompt的一部分,插在原始system的尾部。
[ { 'content': '你扮演一个数据库助手,你具有查询数据库的能力\n'
'\n'
'# Tools\n'
'\n'
'You may call one or more functions to assist with the user '
'query.\n'
'\n'
'You are provided with function signatures within '
'<tools></tools> XML tags:\n'
'<tools>\n'
'{"type": "function", "function": {"name": "sqlite-read_query", '
'"description": "Execute a SELECT query on the SQLite '
'database", "parameters": {"type": "object", "properties": '
'{"query": {"type": "string", "description": "SELECT SQL query '
'to execute"}}, "required": ["query"]}}}\n'
'{"type": "function", "function": {"name": '
'"sqlite-write_query", "description": "Execute an INSERT, '
'UPDATE, or DELETE query on the SQLite database", "parameters": '
'{"type": "object", "properties": {"query": {"type": "string", '
'"description": "SQL query to execute"}}, "required": '
'["query"]}}}\n'
'{"type": "function", "function": {"name": '
'"sqlite-create_table", "description": "Create a new table in '
'the SQLite database", "parameters": {"type": "object", '
'"properties": {"query": {"type": "string", "description": '
'"CREATE TABLE SQL statement"}}, "required": ["query"]}}}\n'
'{"type": "function", "function": {"name": '
'"sqlite-list_tables", "description": "List all tables in the '
'SQLite database", "parameters": {"type": "object", '
'"properties": {}, "required": []}}}\n'
'{"type": "function", "function": {"name": '
'"sqlite-describe_table", "description": "Get the schema '
'information for a specific table", "parameters": {"type": '
'"object", "properties": {"table_name": {"type": "string", '
'"description": "Name of the table to describe"}}, "required": '
'["table_name"]}}}\n'
'{"type": "function", "function": {"name": '
'"sqlite-append_insight", "description": "Add a business '
'insight to the memo", "parameters": {"type": "object", '
'"properties": {"insight": {"type": "string", "description": '
'"Business insight discovered from data analysis"}}, '
'"required": ["insight"]}}}\n'
'</tools>\n'
'\n'
'For each function call, return a json object with function '
'name and arguments within <tool_call></tool_call> XML tags:\n'
'<tool_call>\n'
'{"name": <function-name>, "arguments": <args-json-object>}\n'
'</tool_call>',
'role': 'system'},
{'content': '数据库有几张表', 'role': 'user'}]
具体的实现在function_calling.py -> BaseFnCallModel -> _preprocess_messages
、nous_fncall_prompt.py -> NousFnCallPrompt -> preprocess_fncall_messages
。
LLM的原始output:在content中通过<tool_call>包裹工具调用命令。和gpt-4o原生返回tool_calls字段不一样,意味着工具解析引擎需要做适配。当然,底层原生模型训练的时候也需要特定样本定制训练,提升工具调用准确性。训练后面再单独分享。
[ { 'content': '<tool_call>\n'
'{"name": "sqlite-list_tables", "arguments": {}}\n'
'</tool_call>',
'reasoning_content': '',
'role': 'assistant'}]
后处理后的output: 会解析content,将<tool_call>信息转成function_call结构化输出,Qwen定制了message结构,将function_call结构化。
[ { 'content': [],
'function_call': {'arguments': '{}', 'name': 'sqlite-list_tables'},
'reasoning_content': '',
'role': 'assistant'}]
原始Input: 可以看到,输入中增加了function_call调用后的返回结果,且role是’function’。具体实现在:fncall_agent.py -> FnCallAgent -> _run
。会基于上述function_call结构化信息,检测工具并调用返回结果,然后构造新的1条message插入到history会话中。
[ { 'content': '你扮演一个数据库助手,你具有查询数据库的能力',
'reasoning_content': '',
'role': 'system'},
{ 'content': [{'text': '数据库有几张表'}],
'name': 'user',
'reasoning_content': '',
'role': 'user'},
{ 'content': '',
'function_call': {'arguments': '{}', 'name': 'sqlite-list_tables'},
'name': '数据库助手',
'reasoning_content': '',
'role': 'assistant'},
{ 'content': "[{'name': 'students'}, {'name': 'sqlite_sequence'}, {'name': "
"'log'}]",
'name': 'sqlite-list_tables',
'reasoning_content': '',
'role': 'function'}]
预处理后的Input: 可以看到,function是Qwen自定义的,oai标准格式不支持,因此要转化一下,<tool_response>包裹,并以’user’ role的方式输入,oai api原生主要支持user/assistant交互。
[ { 'content': '你扮演一个数据库助手,你具有查询数据库的能力\n'
'\n'
'# Tools\n'
'\n'
'You may call one or more functions to assist with the user '
'query.\n'
'\n'
'You are provided with function signatures within '
'<tools></tools> XML tags:\n'
'<tools>\n'
'{"type": "function", "function": {"name": "sqlite-read_query", '
'"description": "Execute a SELECT query on the SQLite '
'database", "parameters": {"type": "object", "properties": '
'{"query": {"type": "string", "description": "SELECT SQL query '
'to execute"}}, "required": ["query"]}}}\n'
'{"type": "function", "function": {"name": '
'"sqlite-write_query", "description": "Execute an INSERT, '
'UPDATE, or DELETE query on the SQLite database", "parameters": '
'{"type": "object", "properties": {"query": {"type": "string", '
'"description": "SQL query to execute"}}, "required": '
'["query"]}}}\n'
'{"type": "function", "function": {"name": '
'"sqlite-create_table", "description": "Create a new table in '
'the SQLite database", "parameters": {"type": "object", '
'"properties": {"query": {"type": "string", "description": '
'"CREATE TABLE SQL statement"}}, "required": ["query"]}}}\n'
'{"type": "function", "function": {"name": '
'"sqlite-list_tables", "description": "List all tables in the '
'SQLite database", "parameters": {"type": "object", '
'"properties": {}, "required": []}}}\n'
'{"type": "function", "function": {"name": '
'"sqlite-describe_table", "description": "Get the schema '
'information for a specific table", "parameters": {"type": '
'"object", "properties": {"table_name": {"type": "string", '
'"description": "Name of the table to describe"}}, "required": '
'["table_name"]}}}\n'
'{"type": "function", "function": {"name": '
'"sqlite-append_insight", "description": "Add a business '
'insight to the memo", "parameters": {"type": "object", '
'"properties": {"insight": {"type": "string", "description": '
'"Business insight discovered from data analysis"}}, '
'"required": ["insight"]}}}\n'
'</tools>\n'
'\n'
'For each function call, return a json object with function '
'name and arguments within <tool_call></tool_call> XML tags:\n'
'<tool_call>\n'
'{"name": <function-name>, "arguments": <args-json-object>}\n'
'</tool_call>',
'role': 'system'},
{'content': '数据库有几张表', 'role': 'user'},
{ 'content': '<tool_call>\n'
'{"name": "sqlite-list_tables", "arguments": {}}\n'
'</tool_call>',
'role': 'assistant'},
{ 'content': '<tool_response>\n'
"[{'name': 'students'}, {'name': 'sqlite_sequence'}, {'name': "
"'log'}]\n"
'</tool_response>',
'role': 'user'}]
LLM的原始output: 基于上述信息,即可回答。
[ { 'content': '当前数据库中有三张表,分别是 `students`、`sqlite_sequence` 和 '
'`log`。如果你需要了解每张表的具体结构或进行其他操作,请告诉我。',
'reasoning_content': '',
'role': 'assistant'}]
LLM的后处理后的output: 无function call等,保持和上面一样
[ { 'content': [ { 'text': '当前数据库中有三张表,分别是 `students`、`sqlite_sequence` 和 '
'`log`。如果你需要了解每张表的具体结构或进行其他操作,请告诉我。'}],
'reasoning_content': '',
'role': 'assistant'}]
**小结:**表面上执行了1次对话,实际上背后执行了2次。第一次获取function call的调用指令、第二次将工具调用结果补充到会话中获取答案。
Round2:分别有多少条记录
并行处理任务,理想情况下可并行发起多条数据库查询指令,仍然只需要2次交互即可。
原始Input:
[ { 'content': '你扮演一个数据库助手,你具有查询数据库的能力',
'reasoning_content': '',
'role': 'system'},
{ 'content': [{'text': '数据库有几张表'}],
'name': 'user',
'reasoning_content': '',
'role': 'user'},
{ 'content': '',
'function_call': {'arguments': '{}', 'name': 'sqlite-list_tables'},
'name': '数据库助手',
'reasoning_content': '',
'role': 'assistant'},
{ 'content': "[{'name': 'students'}, {'name': 'sqlite_sequence'}, {'name': "
"'log'}]",
'name': 'sqlite-list_tables',
'reasoning_content': '',
'role': 'function'},
{ 'content': '当前数据库中有三张表,分别是 `students`、`sqlite_sequence` 和 '
'`log`。如果你需要了解每张表的具体结构或进行其他操作,请告诉我。',
'name': '数据库助手',
'reasoning_content': '',
'role': 'assistant'},
{ 'content': [{'text': '分别有多少条记录'}],
'name': 'user',
'reasoning_content': '',
'role': 'user'}]
预处理后的Input: 模型真正的输入,仍然只有user/assistant角色。function等会转成<tool_response>,并作为user role传入。
[ { 'content': '你扮演一个数据库助手,你具有查询数据库的能力\n'
'\n'
'# Tools\n'
'\n'
'You may call one or more functions to assist with the user '
'query.\n'
'\n'
'You are provided with function signatures within '
'<tools></tools> XML tags:\n'
'<tools>\n'
'{"type": "function", "function": {"name": "sqlite-read_query", '
'"description": "Execute a SELECT query on the SQLite '
'database", "parameters": {"type": "object", "properties": '
'{"query": {"type": "string", "description": "SELECT SQL query '
'to execute"}}, "required": ["query"]}}}\n'
'{"type": "function", "function": {"name": '
'"sqlite-write_query", "description": "Execute an INSERT, '
'UPDATE, or DELETE query on the SQLite database", "parameters": '
'{"type": "object", "properties": {"query": {"type": "string", '
'"description": "SQL query to execute"}}, "required": '
'["query"]}}}\n'
'{"type": "function", "function": {"name": '
'"sqlite-create_table", "description": "Create a new table in '
'the SQLite database", "parameters": {"type": "object", '
'"properties": {"query": {"type": "string", "description": '
'"CREATE TABLE SQL statement"}}, "required": ["query"]}}}\n'
'{"type": "function", "function": {"name": '
'"sqlite-list_tables", "description": "List all tables in the '
'SQLite database", "parameters": {"type": "object", '
'"properties": {}, "required": []}}}\n'
'{"type": "function", "function": {"name": '
'"sqlite-describe_table", "description": "Get the schema '
'information for a specific table", "parameters": {"type": '
'"object", "properties": {"table_name": {"type": "string", '
'"description": "Name of the table to describe"}}, "required": '
'["table_name"]}}}\n'
'{"type": "function", "function": {"name": '
'"sqlite-append_insight", "description": "Add a business '
'insight to the memo", "parameters": {"type": "object", '
'"properties": {"insight": {"type": "string", "description": '
'"Business insight discovered from data analysis"}}, '
'"required": ["insight"]}}}\n'
'</tools>\n'
'\n'
'For each function call, return a json object with function '
'name and arguments within <tool_call></tool_call> XML tags:\n'
'<tool_call>\n'
'{"name": <function-name>, "arguments": <args-json-object>}\n'
'</tool_call>',
'role': 'system'},
{'content': '数据库有几张表', 'role': 'user'},
{ 'content': '<tool_call>\n'
'{"name": "sqlite-list_tables", "arguments": {}}\n'
'</tool_call>',
'role': 'assistant'},
{ 'content': '<tool_response>\n'
"[{'name': 'students'}, {'name': 'sqlite_sequence'}, {'name': "
"'log'}]\n"
'</tool_response>',
'role': 'user'},
{ 'content': '当前数据库中有三张表,分别是 `students`、`sqlite_sequence` 和 '
'`log`。如果你需要了解每张表的具体结构或进行其他操作,请告诉我。',
'role': 'assistant'},
{'content': '分别有多少条记录', 'role': 'user'}]
LLM原始Output:可以发现1次性返回多个函数调用指令。意味着可以并行调用多个工具。这点底层模型训练时肯定做了针对性优化。
[ { 'content': '<tool_call>\n'
'{"name": "sqlite-read_query", "arguments": {"query": "SELECT '
'COUNT(*) FROM students"}}\n'
'</tool_call>\n'
'<tool_call>\n'
'{"name": "sqlite-read_query", "arguments": {"query": "SELECT '
'COUNT(*) FROM sqlite_sequence"}}\n'
'</tool_call>\n'
'<tool_call>\n'
'{"name": "sqlite-read_query", "arguments": {"query": "SELECT '
'COUNT(*) FROM log"}}\n'
'</tool_call>',
'reasoning_content': '',
'role': 'assistant'}]
LLM后处理的Output, 拆成3个指令。
[ { 'content': [],
'function_call': { 'arguments': '{"query": "SELECT COUNT(*) FROM '
'students"}',
'name': 'sqlite-read_query'},
'reasoning_content': '',
'role': 'assistant'},
{ 'content': [],
'function_call': { 'arguments': '{"query": "SELECT COUNT(*) FROM '
'sqlite_sequence"}',
'name': 'sqlite-read_query'},
'reasoning_content': '',
'role': 'assistant'},
{ 'content': [],
'function_call': { 'arguments': '{"query": "SELECT COUNT(*) FROM log"}',
'name': 'sqlite-read_query'},
'reasoning_content': '',
'role': 'assistant'}]
原始Input: 将tool调用的结果通过function role给出:
[ { 'content': '你扮演一个数据库助手,你具有查询数据库的能力',
'reasoning_content': '',
'role': 'system'},
{ 'content': [{'text': '数据库有几张表'}],
'name': 'user',
'reasoning_content': '',
'role': 'user'},
{ 'content': '',
'function_call': {'arguments': '{}', 'name': 'sqlite-list_tables'},
'name': '数据库助手',
'reasoning_content': '',
'role': 'assistant'},
{ 'content': "[{'name': 'students'}, {'name': 'sqlite_sequence'}, {'name': "
"'log'}]",
'name': 'sqlite-list_tables',
'reasoning_content': '',
'role': 'function'},
{ 'content': '当前数据库中有三张表,分别是 `students`、`sqlite_sequence` 和 '
'`log`。如果你需要了解每张表的具体结构或进行其他操作,请告诉我。',
'name': '数据库助手',
'reasoning_content': '',
'role': 'assistant'},
{ 'content': [{'text': '分别有多少条记录'}],
'name': 'user',
'reasoning_content': '',
'role': 'user'},
{ 'content': '',
'function_call': { 'arguments': '{"query": "SELECT COUNT(*) FROM '
'students"}',
'name': 'sqlite-read_query'},
'name': '数据库助手',
'reasoning_content': '',
'role': 'assistant'},
{ 'content': '',
'function_call': { 'arguments': '{"query": "SELECT COUNT(*) FROM '
'sqlite_sequence"}',
'name': 'sqlite-read_query'},
'name': '数据库助手',
'reasoning_content': '',
'role': 'assistant'},
{ 'content': '',
'function_call': { 'arguments': '{"query": "SELECT COUNT(*) FROM log"}',
'name': 'sqlite-read_query'},
'name': '数据库助手',
'reasoning_content': '',
'role': 'assistant'},
{ 'content': "[{'COUNT(*)': 2}]",
'name': 'sqlite-read_query',
'reasoning_content': '',
'role': 'function'},
{ 'content': "[{'COUNT(*)': 1}]",
'name': 'sqlite-read_query',
'reasoning_content': '',
'role': 'function'},
{ 'content': "[{'COUNT(*)': 1}]",
'name': 'sqlite-read_query',
'reasoning_content': '',
'role': 'function'}]
预处理后的input,tool_response和tool_call指令按照顺序一一对应,模型能理解这个对应关系。
[ { 'content': '你扮演一个数据库助手,你具有查询数据库的能力\n'
'\n'
'# Tools\n'
'\n'
'You may call one or more functions to assist with the user '
'query.\n'
'\n'
'You are provided with function signatures within '
'<tools></tools> XML tags:\n'
'<tools>\n'
'{"type": "function", "function": {"name": "sqlite-read_query", '
'"description": "Execute a SELECT query on the SQLite '
'database", "parameters": {"type": "object", "properties": '
'{"query": {"type": "string", "description": "SELECT SQL query '
'to execute"}}, "required": ["query"]}}}\n'
'{"type": "function", "function": {"name": '
'"sqlite-write_query", "description": "Execute an INSERT, '
'UPDATE, or DELETE query on the SQLite database", "parameters": '
'{"type": "object", "properties": {"query": {"type": "string", '
'"description": "SQL query to execute"}}, "required": '
'["query"]}}}\n'
'{"type": "function", "function": {"name": '
'"sqlite-create_table", "description": "Create a new table in '
'the SQLite database", "parameters": {"type": "object", '
'"properties": {"query": {"type": "string", "description": '
'"CREATE TABLE SQL statement"}}, "required": ["query"]}}}\n'
'{"type": "function", "function": {"name": '
'"sqlite-list_tables", "description": "List all tables in the '
'SQLite database", "parameters": {"type": "object", '
'"properties": {}, "required": []}}}\n'
'{"type": "function", "function": {"name": '
'"sqlite-describe_table", "description": "Get the schema '
'information for a specific table", "parameters": {"type": '
'"object", "properties": {"table_name": {"type": "string", '
'"description": "Name of the table to describe"}}, "required": '
'["table_name"]}}}\n'
'{"type": "function", "function": {"name": '
'"sqlite-append_insight", "description": "Add a business '
'insight to the memo", "parameters": {"type": "object", '
'"properties": {"insight": {"type": "string", "description": '
'"Business insight discovered from data analysis"}}, '
'"required": ["insight"]}}}\n'
'</tools>\n'
'\n'
'For each function call, return a json object with function '
'name and arguments within <tool_call></tool_call> XML tags:\n'
'<tool_call>\n'
'{"name": <function-name>, "arguments": <args-json-object>}\n'
'</tool_call>',
'role': 'system'},
{'content': '数据库有几张表', 'role': 'user'},
{ 'content': '<tool_call>\n'
'{"name": "sqlite-list_tables", "arguments": {}}\n'
'</tool_call>',
'role': 'assistant'},
{ 'content': '<tool_response>\n'
"[{'name': 'students'}, {'name': 'sqlite_sequence'}, {'name': "
"'log'}]\n"
'</tool_response>',
'role': 'user'},
{ 'content': '当前数据库中有三张表,分别是 `students`、`sqlite_sequence` 和 '
'`log`。如果你需要了解每张表的具体结构或进行其他操作,请告诉我。',
'role': 'assistant'},
{'content': '分别有多少条记录', 'role': 'user'},
{ 'content': '<tool_call>\n'
'{"name": "sqlite-read_query", "arguments": {"query": "SELECT '
'COUNT(*) FROM students"}}\n'
'</tool_call>\n'
'<tool_call>\n'
'{"name": "sqlite-read_query", "arguments": {"query": "SELECT '
'COUNT(*) FROM sqlite_sequence"}}\n'
'</tool_call>\n'
'<tool_call>\n'
'{"name": "sqlite-read_query", "arguments": {"query": "SELECT '
'COUNT(*) FROM log"}}\n'
'</tool_call>',
'role': 'assistant'},
{ 'content': '<tool_response>\n'
"[{'COUNT(*)': 2}]\n"
'</tool_response>\n'
'<tool_response>\n'
"[{'COUNT(*)': 1}]\n"
'</tool_response>\n'
'<tool_response>\n'
"[{'COUNT(*)': 1}]\n"
'</tool_response>',
'role': 'user'}]
LLM原始Output:
[ { 'content': '各表的记录数如下:\n'
'\n'
'- `students` 表有 2 条记录。\n'
'- `sqlite_sequence` 表有 1 条记录。\n'
'- `log` 表有 1 条记录。\n'
'\n'
'如果你需要进一步的信息或对特定表进行操作,请告知我。',
'reasoning_content': '',
'role': 'assistant'}]
LLM后处理后的output: 和上面一样。
[ { 'content': [ { 'text': '各表的记录数如下:\n'
'\n'
'- `students` 表有 2 条记录。\n'
'- `sqlite_sequence` 表有 1 条记录。\n'
'- `log` 表有 1 条记录。\n'
'\n'
'如果你需要进一步的信息或对特定表进行操作,请告知我。'}],
'reasoning_content': '',
'role': 'assistant'}]
小结:可实现并行调用,仍然通过2轮完成。
追加问了个并行类的问题,这几个表的结构分别是什么样的
,仍然可以解决,此处省略:
Round3:查询韩梅梅的年龄,然后在log表里记录下
串行类问题,必须查询完结果,然后才能在log里记录查询行为和时间戳。
原始Input:
[ { 'content': '你扮演一个数据库助手,你具有查询数据库的能力',
'reasoning_content': '',
'role': 'system'},
{ 'content': [{'text': '数据库有几张表'}],
'name': 'user',
'reasoning_content': '',
'role': 'user'},
{ 'content': '',
'function_call': {'arguments': '{}', 'name': 'sqlite-list_tables'},
'name': '数据库助手',
'reasoning_content': '',
'role': 'assistant'},
{ 'content': "[{'name': 'students'}, {'name': 'sqlite_sequence'}, {'name': "
"'log'}]",
'name': 'sqlite-list_tables',
'reasoning_content': '',
'role': 'function'},
{ 'content': '当前数据库中有三张表,分别是 `students`、`sqlite_sequence` 和 '
'`log`。如果你需要了解每张表的具体结构或进行其他操作,请告诉我。',
'name': '数据库助手',
'reasoning_content': '',
'role': 'assistant'},
{ 'content': [{'text': '分别有多少条记录'}],
'name': 'user',
'reasoning_content': '',
'role': 'user'},
{ 'content': '',
'function_call': { 'arguments': '{"query": "SELECT COUNT(*) FROM '
'students"}',
'name': 'sqlite-read_query'},
'name': '数据库助手',
'reasoning_content': '',
'role': 'assistant'},
{ 'content': '',
'function_call': { 'arguments': '{"query": "SELECT COUNT(*) FROM '
'sqlite_sequence"}',
'name': 'sqlite-read_query'},
'name': '数据库助手',
'reasoning_content': '',
'role': 'assistant'},
{ 'content': '',
'function_call': { 'arguments': '{"query": "SELECT COUNT(*) FROM log"}',
'name': 'sqlite-read_query'},
'name': '数据库助手',
'reasoning_content': '',
'role': 'assistant'},
{ 'content': "[{'COUNT(*)': 2}]",
'name': 'sqlite-read_query',
'reasoning_content': '',
'role': 'function'},
{ 'content': "[{'COUNT(*)': 1}]",
'name': 'sqlite-read_query',
'reasoning_content': '',
'role': 'function'},
{ 'content': "[{'COUNT(*)': 1}]",
'name': 'sqlite-read_query',
'reasoning_content': '',
'role': 'function'},
{ 'content': '各表的记录数如下:\n'
'\n'
'- `students` 表有 2 条记录。\n'
'- `sqlite_sequence` 表有 1 条记录。\n'
'- `log` 表有 1 条记录。\n'
'\n'
'如果你需要进一步的信息或对特定表进行操作,请告知我。',
'name': '数据库助手',
'reasoning_content': '',
'role': 'assistant'},
{ 'content': [{'text': '这几个表的结构分别是什么样的'}],
'name': 'user',
'reasoning_content': '',
'role': 'user'},
{ 'content': '',
'function_call': { 'arguments': '{"table_name": "students"}',
'name': 'sqlite-describe_table'},
'name': '数据库助手',
'reasoning_content': '',
'role': 'assistant'},
{ 'content': '',
'function_call': { 'arguments': '{"table_name": "sqlite_sequence"}',
'name': 'sqlite-describe_table'},
'name': '数据库助手',
'reasoning_content': '',
'role': 'assistant'},
{ 'content': '',
'function_call': { 'arguments': '{"table_name": "log"}',
'name': 'sqlite-describe_table'},
'name': '数据库助手',
'reasoning_content': '',
'role': 'assistant'},
{ 'content': "[{'cid': 0, 'name': 'id', 'type': 'INTEGER', 'notnull': 0, "
"'dflt_value': None, 'pk': 1}, {'cid': 1, 'name': 'name', "
"'type': 'TEXT', 'notnull': 1, 'dflt_value': None, 'pk': 0}, "
"{'cid': 2, 'name': 'age', 'type': 'INTEGER', 'notnull': 1, "
"'dflt_value': None, 'pk': 0}]",
'name': 'sqlite-describe_table',
'reasoning_content': '',
'role': 'function'},
{ 'content': "[{'cid': 0, 'name': 'name', 'type': '', 'notnull': 0, "
"'dflt_value': None, 'pk': 0}, {'cid': 1, 'name': 'seq', "
"'type': '', 'notnull': 0, 'dflt_value': None, 'pk': 0}]",
'name': 'sqlite-describe_table',
'reasoning_content': '',
'role': 'function'},
{ 'content': "[{'cid': 0, 'name': 'id', 'type': 'INTEGER', 'notnull': 0, "
"'dflt_value': None, 'pk': 1}, {'cid': 1, 'name': 'action', "
"'type': 'TEXT', 'notnull': 0, 'dflt_value': None, 'pk': 0}, "
"{'cid': 2, 'name': 'timestamp', 'type': 'DATETIME', 'notnull': "
"0, 'dflt_value': 'CURRENT_TIMESTAMP', 'pk': 0}]",
'name': 'sqlite-describe_table',
'reasoning_content': '',
'role': 'function'},
{ 'content': '下面是各表的结构详情:\n'
'\n'
'### students 表\n'
'- `id`: 整数类型,主键。\n'
'- `name`: 文本类型,不能为空。\n'
'- `age`: 整数类型,不能为空。\n'
'\n'
'### sqlite_sequence 表\n'
'这个表通常由 SQLite 自动维护,用于支持 AUTOINCREMENT 字段。\n'
'- `name`: 文本类型,默认值和是否为空未指定。\n'
'- `seq`: 序列号,类型未指定,默认值和是否为空未指定。\n'
'\n'
'### log 表\n'
'- `id`: 整数类型,主键。\n'
'- `action`: 文本类型,可以为空。\n'
'- `timestamp`: 日期时间类型,默认值为当前时间戳(CURRENT_TIMESTAMP),可以为空。\n'
'\n'
'这些信息可以帮助你了解每个表的设计。如果你需要进一步的操作或有其他问题,请告诉我。',
'name': '数据库助手',
'reasoning_content': '',
'role': 'assistant'},
{ 'content': [{'text': '查询韩梅梅的年龄,然后在log表里记录下'}],
'name': 'user',
'reasoning_content': '',
'role': 'user'}]
预处理后的Input:
[ { 'content': '你扮演一个数据库助手,你具有查询数据库的能力\n'
'\n'
'# Tools\n'
'\n'
'You may call one or more functions to assist with the user '
'query.\n'
'\n'
'You are provided with function signatures within '
'<tools></tools> XML tags:\n'
'<tools>\n'
'{"type": "function", "function": {"name": "sqlite-read_query", '
'"description": "Execute a SELECT query on the SQLite '
'database", "parameters": {"type": "object", "properties": '
'{"query": {"type": "string", "description": "SELECT SQL query '
'to execute"}}, "required": ["query"]}}}\n'
'{"type": "function", "function": {"name": '
'"sqlite-write_query", "description": "Execute an INSERT, '
'UPDATE, or DELETE query on the SQLite database", "parameters": '
'{"type": "object", "properties": {"query": {"type": "string", '
'"description": "SQL query to execute"}}, "required": '
'["query"]}}}\n'
'{"type": "function", "function": {"name": '
'"sqlite-create_table", "description": "Create a new table in '
'the SQLite database", "parameters": {"type": "object", '
'"properties": {"query": {"type": "string", "description": '
'"CREATE TABLE SQL statement"}}, "required": ["query"]}}}\n'
'{"type": "function", "function": {"name": '
'"sqlite-list_tables", "description": "List all tables in the '
'SQLite database", "parameters": {"type": "object", '
'"properties": {}, "required": []}}}\n'
'{"type": "function", "function": {"name": '
'"sqlite-describe_table", "description": "Get the schema '
'information for a specific table", "parameters": {"type": '
'"object", "properties": {"table_name": {"type": "string", '
'"description": "Name of the table to describe"}}, "required": '
'["table_name"]}}}\n'
'{"type": "function", "function": {"name": '
'"sqlite-append_insight", "description": "Add a business '
'insight to the memo", "parameters": {"type": "object", '
'"properties": {"insight": {"type": "string", "description": '
'"Business insight discovered from data analysis"}}, '
'"required": ["insight"]}}}\n'
'</tools>\n'
'\n'
'For each function call, return a json object with function '
'name and arguments within <tool_call></tool_call> XML tags:\n'
'<tool_call>\n'
'{"name": <function-name>, "arguments": <args-json-object>}\n'
'</tool_call>',
'role': 'system'},
{'content': '数据库有几张表', 'role': 'user'},
{ 'content': '<tool_call>\n'
'{"name": "sqlite-list_tables", "arguments": {}}\n'
'</tool_call>',
'role': 'assistant'},
{ 'content': '<tool_response>\n'
"[{'name': 'students'}, {'name': 'sqlite_sequence'}, {'name': "
"'log'}]\n"
'</tool_response>',
'role': 'user'},
{ 'content': '当前数据库中有三张表,分别是 `students`、`sqlite_sequence` 和 '
'`log`。如果你需要了解每张表的具体结构或进行其他操作,请告诉我。',
'role': 'assistant'},
{'content': '分别有多少条记录', 'role': 'user'},
{ 'content': '<tool_call>\n'
'{"name": "sqlite-read_query", "arguments": {"query": "SELECT '
'COUNT(*) FROM students"}}\n'
'</tool_call>\n'
'<tool_call>\n'
'{"name": "sqlite-read_query", "arguments": {"query": "SELECT '
'COUNT(*) FROM sqlite_sequence"}}\n'
'</tool_call>\n'
'<tool_call>\n'
'{"name": "sqlite-read_query", "arguments": {"query": "SELECT '
'COUNT(*) FROM log"}}\n'
'</tool_call>',
'role': 'assistant'},
{ 'content': '<tool_response>\n'
"[{'COUNT(*)': 2}]\n"
'</tool_response>\n'
'<tool_response>\n'
"[{'COUNT(*)': 1}]\n"
'</tool_response>\n'
'<tool_response>\n'
"[{'COUNT(*)': 1}]\n"
'</tool_response>',
'role': 'user'},
{ 'content': '各表的记录数如下:\n'
'\n'
'- `students` 表有 2 条记录。\n'
'- `sqlite_sequence` 表有 1 条记录。\n'
'- `log` 表有 1 条记录。\n'
'\n'
'如果你需要进一步的信息或对特定表进行操作,请告知我。',
'role': 'assistant'},
{'content': '这几个表的结构分别是什么样的', 'role': 'user'},
{ 'content': '<tool_call>\n'
'{"name": "sqlite-describe_table", "arguments": {"table_name": '
'"students"}}\n'
'</tool_call>\n'
'<tool_call>\n'
'{"name": "sqlite-describe_table", "arguments": {"table_name": '
'"sqlite_sequence"}}\n'
'</tool_call>\n'
'<tool_call>\n'
'{"name": "sqlite-describe_table", "arguments": {"table_name": '
'"log"}}\n'
'</tool_call>',
'role': 'assistant'},
{ 'content': '<tool_response>\n'
"[{'cid': 0, 'name': 'id', 'type': 'INTEGER', 'notnull': 0, "
"'dflt_value': None, 'pk': 1}, {'cid': 1, 'name': 'name', "
"'type': 'TEXT', 'notnull': 1, 'dflt_value': None, 'pk': 0}, "
"{'cid': 2, 'name': 'age', 'type': 'INTEGER', 'notnull': 1, "
"'dflt_value': None, 'pk': 0}]\n"
'</tool_response>\n'
'<tool_response>\n'
"[{'cid': 0, 'name': 'name', 'type': '', 'notnull': 0, "
"'dflt_value': None, 'pk': 0}, {'cid': 1, 'name': 'seq', "
"'type': '', 'notnull': 0, 'dflt_value': None, 'pk': 0}]\n"
'</tool_response>\n'
'<tool_response>\n'
"[{'cid': 0, 'name': 'id', 'type': 'INTEGER', 'notnull': 0, "
"'dflt_value': None, 'pk': 1}, {'cid': 1, 'name': 'action', "
"'type': 'TEXT', 'notnull': 0, 'dflt_value': None, 'pk': 0}, "
"{'cid': 2, 'name': 'timestamp', 'type': 'DATETIME', 'notnull': "
"0, 'dflt_value': 'CURRENT_TIMESTAMP', 'pk': 0}]\n"
'</tool_response>',
'role': 'user'},
{ 'content': '下面是各表的结构详情:\n'
'\n'
'### students 表\n'
'- `id`: 整数类型,主键。\n'
'- `name`: 文本类型,不能为空。\n'
'- `age`: 整数类型,不能为空。\n'
'\n'
'### sqlite_sequence 表\n'
'这个表通常由 SQLite 自动维护,用于支持 AUTOINCREMENT 字段。\n'
'- `name`: 文本类型,默认值和是否为空未指定。\n'
'- `seq`: 序列号,类型未指定,默认值和是否为空未指定。\n'
'\n'
'### log 表\n'
'- `id`: 整数类型,主键。\n'
'- `action`: 文本类型,可以为空。\n'
'- `timestamp`: 日期时间类型,默认值为当前时间戳(CURRENT_TIMESTAMP),可以为空。\n'
'\n'
'这些信息可以帮助你了解每个表的设计。如果你需要进一步的操作或有其他问题,请告诉我。',
'role': 'assistant'},
{'content': '查询韩梅梅的年龄,然后在log表里记录下', 'role': 'user'}]
原始LLM的output:可以发现此时先进行数据查询!串行操作
`[ { 'content': '<tool_call>\n' '{"name": "sqlite-read_query", "arguments": {"query": "SELECT ' 'age FROM students WHERE name = \'韩梅梅\'"}}\n' '</tool_call>', 'reasoning_content': '', 'role': 'assistant'}]`
LLM后处理后的output: 转成function_call的message
`[ { 'content': [], 'function_call': { 'arguments': '{"query": "SELECT age FROM students WHERE ' 'name = \'韩梅梅\'"}', 'name': 'sqlite-read_query'}, 'reasoning_content': '', 'role': 'assistant'}]`
原始LLM的input: 查询到具体的年龄=6
`[ { 'content': '你扮演一个数据库助手,你具有查询数据库的能力', 'reasoning_content': '', 'role': 'system'}, { 'content': [{'text': '数据库有几张表'}], 'name': 'user', 'reasoning_content': '', 'role': 'user'}, { 'content': '', 'function_call': {'arguments': '{}', 'name': 'sqlite-list_tables'}, 'name': '数据库助手', 'reasoning_content': '', 'role': 'assistant'}, { 'content': "[{'name': 'students'}, {'name': 'sqlite_sequence'}, {'name': " "'log'}]", 'name': 'sqlite-list_tables', 'reasoning_content': '', 'role': 'function'}, { 'content': '当前数据库中有三张表,分别是 `students`、`sqlite_sequence` 和 ' '`log`。如果你需要了解每张表的具体结构或进行其他操作,请告诉我。', 'name': '数据库助手', 'reasoning_content': '', 'role': 'assistant'}, { 'content': [{'text': '分别有多少条记录'}], 'name': 'user', 'reasoning_content': '', 'role': 'user'}, { 'content': '', 'function_call': { 'arguments': '{"query": "SELECT COUNT(*) FROM ' 'students"}', 'name': 'sqlite-read_query'}, 'name': '数据库助手', 'reasoning_content': '', 'role': 'assistant'}, { 'content': '', 'function_call': { 'arguments': '{"query": "SELECT COUNT(*) FROM ' 'sqlite_sequence"}', 'name': 'sqlite-read_query'}, 'name': '数据库助手', 'reasoning_content': '', 'role': 'assistant'}, { 'content': '', 'function_call': { 'arguments': '{"query": "SELECT COUNT(*) FROM log"}', 'name': 'sqlite-read_query'}, 'name': '数据库助手', 'reasoning_content': '', 'role': 'assistant'}, { 'content': "[{'COUNT(*)': 2}]", 'name': 'sqlite-read_query', 'reasoning_content': '', 'role': 'function'}, { 'content': "[{'COUNT(*)': 1}]", 'name': 'sqlite-read_query', 'reasoning_content': '', 'role': 'function'}, { 'content': "[{'COUNT(*)': 1}]", 'name': 'sqlite-read_query', 'reasoning_content': '', 'role': 'function'}, { 'content': '各表的记录数如下:\n' '\n' '- `students` 表有 2 条记录。\n' '- `sqlite_sequence` 表有 1 条记录。\n' '- `log` 表有 1 条记录。\n' '\n' '如果你需要进一步的信息或对特定表进行操作,请告知我。', 'name': '数据库助手', 'reasoning_content': '', 'role': 'assistant'}, { 'content': [{'text': '这几个表的结构分别是什么样的'}], 'name': 'user', 'reasoning_content': '', 'role': 'user'}, { 'content': '', 'function_call': { 'arguments': '{"table_name": "students"}', 'name': 'sqlite-describe_table'}, 'name': '数据库助手', 'reasoning_content': '', 'role': 'assistant'}, { 'content': '', 'function_call': { 'arguments': '{"table_name": "sqlite_sequence"}', 'name': 'sqlite-describe_table'}, 'name': '数据库助手', 'reasoning_content': '', 'role': 'assistant'}, { 'content': '', 'function_call': { 'arguments': '{"table_name": "log"}', 'name': 'sqlite-describe_table'}, 'name': '数据库助手', 'reasoning_content': '', 'role': 'assistant'}, { 'content': "[{'cid': 0, 'name': 'id', 'type': 'INTEGER', 'notnull': 0, " "'dflt_value': None, 'pk': 1}, {'cid': 1, 'name': 'name', " "'type': 'TEXT', 'notnull': 1, 'dflt_value': None, 'pk': 0}, " "{'cid': 2, 'name': 'age', 'type': 'INTEGER', 'notnull': 1, " "'dflt_value': None, 'pk': 0}]", 'name': 'sqlite-describe_table', 'reasoning_content': '', 'role': 'function'}, { 'content': "[{'cid': 0, 'name': 'name', 'type': '', 'notnull': 0, " "'dflt_value': None, 'pk': 0}, {'cid': 1, 'name': 'seq', " "'type': '', 'notnull': 0, 'dflt_value': None, 'pk': 0}]", 'name': 'sqlite-describe_table', 'reasoning_content': '', 'role': 'function'}, { 'content': "[{'cid': 0, 'name': 'id', 'type': 'INTEGER', 'notnull': 0, " "'dflt_value': None, 'pk': 1}, {'cid': 1, 'name': 'action', " "'type': 'TEXT', 'notnull': 0, 'dflt_value': None, 'pk': 0}, " "{'cid': 2, 'name': 'timestamp', 'type': 'DATETIME', 'notnull': " "0, 'dflt_value': 'CURRENT_TIMESTAMP', 'pk': 0}]", 'name': 'sqlite-describe_table', 'reasoning_content': '', 'role': 'function'}, { 'content': '下面是各表的结构详情:\n' '\n' '### students 表\n' '- `id`: 整数类型,主键。\n' '- `name`: 文本类型,不能为空。\n' '- `age`: 整数类型,不能为空。\n' '\n' '### sqlite_sequence 表\n' '这个表通常由 SQLite 自动维护,用于支持 AUTOINCREMENT 字段。\n' '- `name`: 文本类型,默认值和是否为空未指定。\n' '- `seq`: 序列号,类型未指定,默认值和是否为空未指定。\n' '\n' '### log 表\n' '- `id`: 整数类型,主键。\n' '- `action`: 文本类型,可以为空。\n' '- `timestamp`: 日期时间类型,默认值为当前时间戳(CURRENT_TIMESTAMP),可以为空。\n' '\n' '这些信息可以帮助你了解每个表的设计。如果你需要进一步的操作或有其他问题,请告诉我。', 'name': '数据库助手', 'reasoning_content': '', 'role': 'assistant'}, { 'content': [{'text': '查询韩梅梅的年龄,然后在log表里记录下'}], 'name': 'user', 'reasoning_content': '', 'role': 'user'}, { 'content': '', 'function_call': { 'arguments': '{"query": "SELECT age FROM students WHERE ' 'name = \'韩梅梅\'"}', 'name': 'sqlite-read_query'}, 'name': '数据库助手', 'reasoning_content': '', 'role': 'assistant'}, { 'content': "[{'age': 6}]", 'name': 'sqlite-read_query', 'reasoning_content': '', 'role': 'function'}]`
后处理后的LLM的input: function call的结果转化为,并以user role的形式传入[ { ‘content’: ‘你扮演一个数据库助手,你具有查询数据库的能力\n’
'\n'
'# Tools\n'
'\n'
'You may call one or more functions to assist with the user '
'query.\n'
'\n'
'You are provided with function signatures within '
'<tools></tools> XML tags:\n'
'<tools>\n'
'{"type": "function", "function": {"name": "sqlite-read_query", '
'"description": "Execute a SELECT query on the SQLite '
'database", "parameters": {"type": "object", "properties": '
'{"query": {"type": "string", "description": "SELECT SQL query '
'to execute"}}, "required": ["query"]}}}\n'
'{"type": "function", "function": {"name": '
'"sqlite-write_query", "description": "Execute an INSERT, '
'UPDATE, or DELETE query on the SQLite database", "parameters": '
'{"type": "object", "properties": {"query": {"type": "string", '
'"description": "SQL query to execute"}}, "required": '
'["query"]}}}\n'
'{"type": "function", "function": {"name": '
'"sqlite-create_table", "description": "Create a new table in '
'the SQLite database", "parameters": {"type": "object", '
'"properties": {"query": {"type": "string", "description": '
'"CREATE TABLE SQL statement"}}, "required": ["query"]}}}\n'
'{"type": "function", "function": {"name": '
'"sqlite-list_tables", "description": "List all tables in the '
'SQLite database", "parameters": {"type": "object", '
'"properties": {}, "required": []}}}\n'
'{"type": "function", "function": {"name": '
'"sqlite-describe_table", "description": "Get the schema '
'information for a specific table", "parameters": {"type": '
'"object", "properties": {"table_name": {"type": "string", '
'"description": "Name of the table to describe"}}, "required": '
'["table_name"]}}}\n'
'{"type": "function", "function": {"name": '
'"sqlite-append_insight", "description": "Add a business '
'insight to the memo", "parameters": {"type": "object", '
'"properties": {"insight": {"type": "string", "description": '
'"Business insight discovered from data analysis"}}, '
'"required": ["insight"]}}}\n'
'</tools>\n'
'\n'
'For each function call, return a json object with function '
'name and arguments within <tool_call></tool_call> XML tags:\n'
'<tool_call>\n'
'{"name": <function-name>, "arguments": <args-json-object>}\n'
'</tool_call>',
'role': 'system'},
{'content': '数据库有几张表', 'role': 'user'},
{ 'content': '<tool_call>\n'
'{"name": "sqlite-list_tables", "arguments": {}}\n'
'</tool_call>',
'role': 'assistant'},
{ 'content': '<tool_response>\n'
"[{'name': 'students'}, {'name': 'sqlite_sequence'}, {'name': "
"'log'}]\n"
'</tool_response>',
'role': 'user'},
{ 'content': '当前数据库中有三张表,分别是 `students`、`sqlite_sequence` 和 '
'`log`。如果你需要了解每张表的具体结构或进行其他操作,请告诉我。',
'role': 'assistant'},
{'content': '分别有多少条记录', 'role': 'user'},
{ 'content': '<tool_call>\n'
'{"name": "sqlite-read_query", "arguments": {"query": "SELECT '
'COUNT(*) FROM students"}}\n'
'</tool_call>\n'
'<tool_call>\n'
'{"name": "sqlite-read_query", "arguments": {"query": "SELECT '
'COUNT(*) FROM sqlite_sequence"}}\n'
'</tool_call>\n'
'<tool_call>\n'
'{"name": "sqlite-read_query", "arguments": {"query": "SELECT '
'COUNT(*) FROM log"}}\n'
'</tool_call>',
'role': 'assistant'},
{ 'content': '<tool_response>\n'
"[{'COUNT(*)': 2}]\n"
'</tool_response>\n'
'<tool_response>\n'
"[{'COUNT(*)': 1}]\n"
'</tool_response>\n'
'<tool_response>\n'
"[{'COUNT(*)': 1}]\n"
'</tool_response>',
'role': 'user'},
{ 'content': '各表的记录数如下:\n'
'\n'
'- `students` 表有 2 条记录。\n'
'- `sqlite_sequence` 表有 1 条记录。\n'
'- `log` 表有 1 条记录。\n'
'\n'
'如果你需要进一步的信息或对特定表进行操作,请告知我。',
'role': 'assistant'},
{'content': '这几个表的结构分别是什么样的', 'role': 'user'},
{ 'content': '<tool_call>\n'
'{"name": "sqlite-describe_table", "arguments": {"table_name": '
'"students"}}\n'
'</tool_call>\n'
'<tool_call>\n'
'{"name": "sqlite-describe_table", "arguments": {"table_name": '
'"sqlite_sequence"}}\n'
'</tool_call>\n'
'<tool_call>\n'
'{"name": "sqlite-describe_table", "arguments": {"table_name": '
'"log"}}\n'
'</tool_call>',
'role': 'assistant'},
{ 'content': '<tool_response>\n'
"[{'cid': 0, 'name': 'id', 'type': 'INTEGER', 'notnull': 0, "
"'dflt_value': None, 'pk': 1}, {'cid': 1, 'name': 'name', "
"'type': 'TEXT', 'notnull': 1, 'dflt_value': None, 'pk': 0}, "
"{'cid': 2, 'name': 'age', 'type': 'INTEGER', 'notnull': 1, "
"'dflt_value': None, 'pk': 0}]\n"
'</tool_response>\n'
'<tool_response>\n'
"[{'cid': 0, 'name': 'name', 'type': '', 'notnull': 0, "
"'dflt_value': None, 'pk': 0}, {'cid': 1, 'name': 'seq', "
"'type': '', 'notnull': 0, 'dflt_value': None, 'pk': 0}]\n"
'</tool_response>\n'
'<tool_response>\n'
"[{'cid': 0, 'name': 'id', 'type': 'INTEGER', 'notnull': 0, "
"'dflt_value': None, 'pk': 1}, {'cid': 1, 'name': 'action', "
"'type': 'TEXT', 'notnull': 0, 'dflt_value': None, 'pk': 0}, "
"{'cid': 2, 'name': 'timestamp', 'type': 'DATETIME', 'notnull': "
"0, 'dflt_value': 'CURRENT_TIMESTAMP', 'pk': 0}]\n"
'</tool_response>',
'role': 'user'},
{ 'content': '下面是各表的结构详情:\n'
'\n'
'### students 表\n'
'- `id`: 整数类型,主键。\n'
'- `name`: 文本类型,不能为空。\n'
'- `age`: 整数类型,不能为空。\n'
'\n'
'### sqlite_sequence 表\n'
'这个表通常由 SQLite 自动维护,用于支持 AUTOINCREMENT 字段。\n'
'- `name`: 文本类型,默认值和是否为空未指定。\n'
'- `seq`: 序列号,类型未指定,默认值和是否为空未指定。\n'
'\n'
'### log 表\n'
'- `id`: 整数类型,主键。\n'
'- `action`: 文本类型,可以为空。\n'
'- `timestamp`: 日期时间类型,默认值为当前时间戳(CURRENT_TIMESTAMP),可以为空。\n'
'\n'
'这些信息可以帮助你了解每个表的设计。如果你需要进一步的操作或有其他问题,请告诉我。',
'role': 'assistant'},
{'content': '查询韩梅梅的年龄,然后在log表里记录下', 'role': 'user'},
{ 'content': '<tool_call>\n'
'{"name": "sqlite-read_query", "arguments": {"query": "SELECT '
'age FROM students WHERE name = \'韩梅梅\'"}}\n'
'</tool_call>',
'role': 'assistant'},
{ 'content': "<tool_response>\n[{'age': 6}]\n</tool_response>",
'role': 'user'}]
LLM的原始output: 继续串行执行插入日志的命令。此处没有中断总结前面的操作,而是继续下一个工具调用,挺灵活的。
`[ { 'content': '<tool_call>\n' '{"name": "sqlite-write_query", "arguments": {"query": "INSERT ' 'INTO log (action) VALUES (\'查询了韩梅梅的年龄\')"}}\n' '</tool_call>', 'reasoning_content': '', 'role': 'assistant'}]`
LLM后处理后的output:
`[ { 'content': [], 'function_call': { 'arguments': '{"query": "INSERT INTO log (action) ' 'VALUES (\'查询了韩梅梅的年龄\')"}', 'name': 'sqlite-write_query'}, 'reasoning_content': '', 'role': 'assistant'}]`
LLM的原始Input: 调用插入指令获取插入成功的信息
`[ { 'content': '你扮演一个数据库助手,你具有查询数据库的能力', 'reasoning_content': '', 'role': 'system'}, { 'content': [{'text': '数据库有几张表'}], 'name': 'user', 'reasoning_content': '', 'role': 'user'}, { 'content': '', 'function_call': {'arguments': '{}', 'name': 'sqlite-list_tables'}, 'name': '数据库助手', 'reasoning_content': '', 'role': 'assistant'}, { 'content': "[{'name': 'students'}, {'name': 'sqlite_sequence'}, {'name': " "'log'}]", 'name': 'sqlite-list_tables', 'reasoning_content': '', 'role': 'function'}, { 'content': '当前数据库中有三张表,分别是 `students`、`sqlite_sequence` 和 ' '`log`。如果你需要了解每张表的具体结构或进行其他操作,请告诉我。', 'name': '数据库助手', 'reasoning_content': '', 'role': 'assistant'}, { 'content': [{'text': '分别有多少条记录'}], 'name': 'user', 'reasoning_content': '', 'role': 'user'}, { 'content': '', 'function_call': { 'arguments': '{"query": "SELECT COUNT(*) FROM ' 'students"}', 'name': 'sqlite-read_query'}, 'name': '数据库助手', 'reasoning_content': '', 'role': 'assistant'}, { 'content': '', 'function_call': { 'arguments': '{"query": "SELECT COUNT(*) FROM ' 'sqlite_sequence"}', 'name': 'sqlite-read_query'}, 'name': '数据库助手', 'reasoning_content': '', 'role': 'assistant'}, { 'content': '', 'function_call': { 'arguments': '{"query": "SELECT COUNT(*) FROM log"}', 'name': 'sqlite-read_query'}, 'name': '数据库助手', 'reasoning_content': '', 'role': 'assistant'}, { 'content': "[{'COUNT(*)': 2}]", 'name': 'sqlite-read_query', 'reasoning_content': '', 'role': 'function'}, { 'content': "[{'COUNT(*)': 1}]", 'name': 'sqlite-read_query', 'reasoning_content': '', 'role': 'function'}, { 'content': "[{'COUNT(*)': 1}]", 'name': 'sqlite-read_query', 'reasoning_content': '', 'role': 'function'}, { 'content': '各表的记录数如下:\n' '\n' '- `students` 表有 2 条记录。\n' '- `sqlite_sequence` 表有 1 条记录。\n' '- `log` 表有 1 条记录。\n' '\n' '如果你需要进一步的信息或对特定表进行操作,请告知我。', 'name': '数据库助手', 'reasoning_content': '', 'role': 'assistant'}, { 'content': [{'text': '这几个表的结构分别是什么样的'}], 'name': 'user', 'reasoning_content': '', 'role': 'user'}, { 'content': '', 'function_call': { 'arguments': '{"table_name": "students"}', 'name': 'sqlite-describe_table'}, 'name': '数据库助手', 'reasoning_content': '', 'role': 'assistant'}, { 'content': '', 'function_call': { 'arguments': '{"table_name": "sqlite_sequence"}', 'name': 'sqlite-describe_table'}, 'name': '数据库助手', 'reasoning_content': '', 'role': 'assistant'}, { 'content': '', 'function_call': { 'arguments': '{"table_name": "log"}', 'name': 'sqlite-describe_table'}, 'name': '数据库助手', 'reasoning_content': '', 'role': 'assistant'}, { 'content': "[{'cid': 0, 'name': 'id', 'type': 'INTEGER', 'notnull': 0, " "'dflt_value': None, 'pk': 1}, {'cid': 1, 'name': 'name', " "'type': 'TEXT', 'notnull': 1, 'dflt_value': None, 'pk': 0}, " "{'cid': 2, 'name': 'age', 'type': 'INTEGER', 'notnull': 1, " "'dflt_value': None, 'pk': 0}]", 'name': 'sqlite-describe_table', 'reasoning_content': '', 'role': 'function'}, { 'content': "[{'cid': 0, 'name': 'name', 'type': '', 'notnull': 0, " "'dflt_value': None, 'pk': 0}, {'cid': 1, 'name': 'seq', " "'type': '', 'notnull': 0, 'dflt_value': None, 'pk': 0}]", 'name': 'sqlite-describe_table', 'reasoning_content': '', 'role': 'function'}, { 'content': "[{'cid': 0, 'name': 'id', 'type': 'INTEGER', 'notnull': 0, " "'dflt_value': None, 'pk': 1}, {'cid': 1, 'name': 'action', " "'type': 'TEXT', 'notnull': 0, 'dflt_value': None, 'pk': 0}, " "{'cid': 2, 'name': 'timestamp', 'type': 'DATETIME', 'notnull': " "0, 'dflt_value': 'CURRENT_TIMESTAMP', 'pk': 0}]", 'name': 'sqlite-describe_table', 'reasoning_content': '', 'role': 'function'}, { 'content': '下面是各表的结构详情:\n' '\n' '### students 表\n' '- `id`: 整数类型,主键。\n' '- `name`: 文本类型,不能为空。\n' '- `age`: 整数类型,不能为空。\n' '\n' '### sqlite_sequence 表\n' '这个表通常由 SQLite 自动维护,用于支持 AUTOINCREMENT 字段。\n' '- `name`: 文本类型,默认值和是否为空未指定。\n' '- `seq`: 序列号,类型未指定,默认值和是否为空未指定。\n' '\n' '### log 表\n' '- `id`: 整数类型,主键。\n' '- `action`: 文本类型,可以为空。\n' '- `timestamp`: 日期时间类型,默认值为当前时间戳(CURRENT_TIMESTAMP),可以为空。\n' '\n' '这些信息可以帮助你了解每个表的设计。如果你需要进一步的操作或有其他问题,请告诉我。', 'name': '数据库助手', 'reasoning_content': '', 'role': 'assistant'}, { 'content': [{'text': '查询韩梅梅的年龄,然后在log表里记录下'}], 'name': 'user', 'reasoning_content': '', 'role': 'user'}, { 'content': '', 'function_call': { 'arguments': '{"query": "SELECT age FROM students WHERE ' 'name = \'韩梅梅\'"}', 'name': 'sqlite-read_query'}, 'name': '数据库助手', 'reasoning_content': '', 'role': 'assistant'}, { 'content': "[{'age': 6}]", 'name': 'sqlite-read_query', 'reasoning_content': '', 'role': 'function'}, { 'content': '', 'function_call': { 'arguments': '{"query": "INSERT INTO log (action) ' 'VALUES (\'查询了韩梅梅的年龄\')"}', 'name': 'sqlite-write_query'}, 'name': '数据库助手', 'reasoning_content': '', 'role': 'assistant'}, { 'content': "[{'affected_rows': 1}]", 'name': 'sqlite-write_query', 'reasoning_content': '', 'role': 'function'}]`
LLM后处理后的Input: 以user role传入[ { ‘content’: ‘你扮演一个数据库助手,你具有查询数据库的能力\n’
'\n'
'# Tools\n'
'\n'
'You may call one or more functions to assist with the user '
'query.\n'
'\n'
'You are provided with function signatures within '
'<tools></tools> XML tags:\n'
'<tools>\n'
'{"type": "function", "function": {"name": "sqlite-read_query", '
'"description": "Execute a SELECT query on the SQLite '
'database", "parameters": {"type": "object", "properties": '
'{"query": {"type": "string", "description": "SELECT SQL query '
'to execute"}}, "required": ["query"]}}}\n'
'{"type": "function", "function": {"name": '
'"sqlite-write_query", "description": "Execute an INSERT, '
'UPDATE, or DELETE query on the SQLite database", "parameters": '
'{"type": "object", "properties": {"query": {"type": "string", '
'"description": "SQL query to execute"}}, "required": '
'["query"]}}}\n'
'{"type": "function", "function": {"name": '
'"sqlite-create_table", "description": "Create a new table in '
'the SQLite database", "parameters": {"type": "object", '
'"properties": {"query": {"type": "string", "description": '
'"CREATE TABLE SQL statement"}}, "required": ["query"]}}}\n'
'{"type": "function", "function": {"name": '
'"sqlite-list_tables", "description": "List all tables in the '
'SQLite database", "parameters": {"type": "object", '
'"properties": {}, "required": []}}}\n'
'{"type": "function", "function": {"name": '
'"sqlite-describe_table", "description": "Get the schema '
'information for a specific table", "parameters": {"type": '
'"object", "properties": {"table_name": {"type": "string", '
'"description": "Name of the table to describe"}}, "required": '
'["table_name"]}}}\n'
'{"type": "function", "function": {"name": '
'"sqlite-append_insight", "description": "Add a business '
'insight to the memo", "parameters": {"type": "object", '
'"properties": {"insight": {"type": "string", "description": '
'"Business insight discovered from data analysis"}}, '
'"required": ["insight"]}}}\n'
'</tools>\n'
'\n'
'For each function call, return a json object with function '
'name and arguments within <tool_call></tool_call> XML tags:\n'
'<tool_call>\n'
'{"name": <function-name>, "arguments": <args-json-object>}\n'
'</tool_call>',
'role': 'system'},
{'content': '数据库有几张表', 'role': 'user'},
{ 'content': '<tool_call>\n'
'{"name": "sqlite-list_tables", "arguments": {}}\n'
'</tool_call>',
'role': 'assistant'},
{ 'content': '<tool_response>\n'
"[{'name': 'students'}, {'name': 'sqlite_sequence'}, {'name': "
"'log'}]\n"
'</tool_response>',
'role': 'user'},
{ 'content': '当前数据库中有三张表,分别是 `students`、`sqlite_sequence` 和 '
'`log`。如果你需要了解每张表的具体结构或进行其他操作,请告诉我。',
'role': 'assistant'},
{'content': '分别有多少条记录', 'role': 'user'},
{ 'content': '<tool_call>\n'
'{"name": "sqlite-read_query", "arguments": {"query": "SELECT '
'COUNT(*) FROM students"}}\n'
'</tool_call>\n'
'<tool_call>\n'
'{"name": "sqlite-read_query", "arguments": {"query": "SELECT '
'COUNT(*) FROM sqlite_sequence"}}\n'
'</tool_call>\n'
'<tool_call>\n'
'{"name": "sqlite-read_query", "arguments": {"query": "SELECT '
'COUNT(*) FROM log"}}\n'
'</tool_call>',
'role': 'assistant'},
{ 'content': '<tool_response>\n'
"[{'COUNT(*)': 2}]\n"
'</tool_response>\n'
'<tool_response>\n'
"[{'COUNT(*)': 1}]\n"
'</tool_response>\n'
'<tool_response>\n'
"[{'COUNT(*)': 1}]\n"
'</tool_response>',
'role': 'user'},
{ 'content': '各表的记录数如下:\n'
'\n'
'- `students` 表有 2 条记录。\n'
'- `sqlite_sequence` 表有 1 条记录。\n'
'- `log` 表有 1 条记录。\n'
'\n'
'如果你需要进一步的信息或对特定表进行操作,请告知我。',
'role': 'assistant'},
{'content': '这几个表的结构分别是什么样的', 'role': 'user'},
{ 'content': '<tool_call>\n'
'{"name": "sqlite-describe_table", "arguments": {"table_name": '
'"students"}}\n'
'</tool_call>\n'
'<tool_call>\n'
'{"name": "sqlite-describe_table", "arguments": {"table_name": '
'"sqlite_sequence"}}\n'
'</tool_call>\n'
'<tool_call>\n'
'{"name": "sqlite-describe_table", "arguments": {"table_name": '
'"log"}}\n'
'</tool_call>',
'role': 'assistant'},
{ 'content': '<tool_response>\n'
"[{'cid': 0, 'name': 'id', 'type': 'INTEGER', 'notnull': 0, "
"'dflt_value': None, 'pk': 1}, {'cid': 1, 'name': 'name', "
"'type': 'TEXT', 'notnull': 1, 'dflt_value': None, 'pk': 0}, "
"{'cid': 2, 'name': 'age', 'type': 'INTEGER', 'notnull': 1, "
"'dflt_value': None, 'pk': 0}]\n"
'</tool_response>\n'
'<tool_response>\n'
"[{'cid': 0, 'name': 'name', 'type': '', 'notnull': 0, "
"'dflt_value': None, 'pk': 0}, {'cid': 1, 'name': 'seq', "
"'type': '', 'notnull': 0, 'dflt_value': None, 'pk': 0}]\n"
'</tool_response>\n'
'<tool_response>\n'
"[{'cid': 0, 'name': 'id', 'type': 'INTEGER', 'notnull': 0, "
"'dflt_value': None, 'pk': 1}, {'cid': 1, 'name': 'action', "
"'type': 'TEXT', 'notnull': 0, 'dflt_value': None, 'pk': 0}, "
"{'cid': 2, 'name': 'timestamp', 'type': 'DATETIME', 'notnull': "
"0, 'dflt_value': 'CURRENT_TIMESTAMP', 'pk': 0}]\n"
'</tool_response>',
'role': 'user'},
{ 'content': '下面是各表的结构详情:\n'
'\n'
'### students 表\n'
'- `id`: 整数类型,主键。\n'
'- `name`: 文本类型,不能为空。\n'
'- `age`: 整数类型,不能为空。\n'
'\n'
'### sqlite_sequence 表\n'
'这个表通常由 SQLite 自动维护,用于支持 AUTOINCREMENT 字段。\n'
'- `name`: 文本类型,默认值和是否为空未指定。\n'
'- `seq`: 序列号,类型未指定,默认值和是否为空未指定。\n'
'\n'
'### log 表\n'
'- `id`: 整数类型,主键。\n'
'- `action`: 文本类型,可以为空。\n'
'- `timestamp`: 日期时间类型,默认值为当前时间戳(CURRENT_TIMESTAMP),可以为空。\n'
'\n'
'这些信息可以帮助你了解每个表的设计。如果你需要进一步的操作或有其他问题,请告诉我。',
'role': 'assistant'},
{'content': '查询韩梅梅的年龄,然后在log表里记录下', 'role': 'user'},
{ 'content': '<tool_call>\n'
'{"name": "sqlite-read_query", "arguments": {"query": "SELECT '
'age FROM students WHERE name = \'韩梅梅\'"}}\n'
'</tool_call>',
'role': 'assistant'},
{ 'content': "<tool_response>\n[{'age': 6}]\n</tool_response>",
'role': 'user'},
{ 'content': '<tool_call>\n'
'{"name": "sqlite-write_query", "arguments": {"query": "INSERT '
'INTO log (action) VALUES (\'查询了韩梅梅的年龄\')"}}\n'
'</tool_call>',
'role': 'assistant'},
{ 'content': "<tool_response>\n[{'affected_rows': 1}]\n</tool_response>",
'role': 'user'}]
LLM的原始output:
`[ { 'content': '韩梅梅的年龄是 6 岁,并且我已经在 `log` 表里记录下了这次查询操作。', 'reasoning_content': '', 'role': 'assistant'}]`
LLM的后处理的output:
`[ { 'content': [{'text': '韩梅梅的年龄是 6 岁,并且我已经在 `log` 表里记录下了这次查询操作。'}], 'reasoning_content': '', 'role': 'assistant'}]`
小结: 共执行了4次对话,获取查询年龄的指令、查询年龄并得到具体年龄6岁、获取插入日志的指令、执行插入并回答插入完成。
Tracing
我们可以将上述过程通过weave工具[2]可视化出来,能够清晰的了解各个流程、mcp工具等如何调用和运转。
总结
整体流程比较清晰。1)通常先经过1次询问,llm返回工具调用指令;2)再基于指令调用工具得到结果,以user的形式喂给llm,得出答案。Qwen3号称在这块原生支持mcp,笔者认为主要是Qwen Agent支持。只不过在返回’调用指令’这块,Qwen3可能使用了function calling样本进行针对性优化,使得工具调用更加丝滑。
Qwen Agent封装了不少通用工具,如代码执行器,搜索工具,mcp工具等。在工具解析引擎上适配不同格式,配合Qwen3在工具调用准度的提升,整体比较丝滑。
最后的最后
感谢你们的阅读和喜欢,作为一位在一线互联网行业奋斗多年的老兵,我深知在这个瞬息万变的技术领域中,持续学习和进步的重要性。
为了帮助更多热爱技术、渴望成长的朋友,我特别整理了一份涵盖大模型领域的宝贵资料集。
这些资料不仅是我多年积累的心血结晶,也是我在行业一线实战经验的总结。
这些学习资料不仅深入浅出,而且非常实用,让大家系统而高效地掌握AI大模型的各个知识点。如果你愿意花时间沉下心来学习,相信它们一定能为你提供实质性的帮助。
这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费
】

大模型知识脑图
为了成为更好的 AI大模型 开发者,这里为大家提供了总的路线图。它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。
经典书籍阅读
阅读AI大模型经典书籍可以帮助读者提高技术水平,开拓视野,掌握核心技术,提高解决问题的能力,同时也可以借鉴他人的经验。对于想要深入学习AI大模型开发的读者来说,阅读经典书籍是非常有必要的。
实战案例
光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。
面试资料
我们学习AI大模型必然是想找到高薪的工作,下面这些面试题都是总结当前最新、最热、最高频的面试题,并且每道题都有详细的答案,面试前刷完这套面试题资料,小小offer,不在话下
640套AI大模型报告合集
这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。
这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费
】
