微信扫码
添加专属顾问
我要投稿
掌握QwQ-32B模型的Function Call技能,轻松实现工具调用与多步骤推理。
核心内容:
1. QwQ-32B模型在LiveBench榜单上的优异表现
2. 两种方法实现QwQ-32B的Function Call调用
3. 工具Schema定义与执行函数实现示例
前不久,我们发布了推理模型通义千问QwQ-32B,在 LiveBench 榜单上取得了开源模型的最佳成绩。
在针对模型的 Agent 能力的 BFCL 评测中,千问 QwQ-32B 模型在工具调用准确率、复杂参数解析等核心指标上均有不凡表现,展现出领先的函数调用与多步骤推理能力。
今天,我们将分享如何简单方便地基于 QwQ-32B 进行 Function Call 的调用,通过标准化代码案例,系统讲解其在工具调用场景中的技术实现与应用实践。
调用QwQ-32B的Function Call,我们以以下两种方法为例:
(1)百炼API
(2)Qwen-Agent开源框架
准备工作
(1)定义自己的工具 Schema
(2)实现工具的执行函数
TOOLS = [{
"name": "train_tickets",
"description": "Obtain train tickets and other information based on departure, arrival, and time.",
"parameters": {
"type": "object",
"properties": {
"start": {
"type": "string",
"description": "The departure city."
},
"end": {
"type": "string",
"description": "The arrival city."
},
"date": {
"type": "string",
"description": "The date, such as 2024-02-21. If not clear, do not fill in."
}
},
"required": [
"start",
"end",
"date"
]
}
},
{
"name": "get_weather",
"description": "Weather inquiry.",
"parameters": {
"type": "object",
"properties": {
"area": {
"type": "string",
"description": "Regional name, such as 丽江"
}
},
"required": [
"area"
]
}
}]
import json
def get_weather(area: str):
# 作为示例,这里定义一个假的工具执行函数
res = {
"area": "上海",
"weather": {
"areaid": "101020100",
"temperature": "12",
"weather": "晴",
"wind_direction": "西风",
"wind_power": "0-3级 微风 <5.4m/s",
"weather_code": "00"
},
}
return json.dumps(res, ensure_ascii=False)
def train_tickets(start: str, end: str, date: str):
# 作为示例,这里定义一个假的工具执行函数
if start == '上海' and end == '杭州':
res = {
"costtime": "1小时19分",
"trainno": "C3629",
"arrivaltime": "17:34",
"endstation": "杭州西",
"terminalstationcode": "YWH",
"departstation": "上海虹桥",
"station": "上海虹桥",
"departuretime": "16:15",
"departstationcode": "AOH",
}
elif start == '杭州' and end == '上海':
res = {
"costtime": "0小时48分",
"trainno": "G7336",
"arrivaltime": "8:34",
"endstation": "上海南",
"terminalstationcode": "SNH",
"departstation": "苍南",
"station": "杭州东",
"departuretime": "7:46",
"departstationcode": "CEH",
}
else:
res = {"train_list": "No available train"}
return json.dumps(res, ensure_ascii=False)
TOOL_EXEC_MAP = {
'train_tickets': train_tickets,
'get_weather': get_weather
}
百炼API
运行以下代码,完成一次含有工具调用的请求。
主要包含三个步骤:
(1)发起模型请求,输入用户问题和工具
(2)读取返回内容,如果返回内容包含工具调用,则执行工具,获得工具结果
(3)再次发起模型请求,输入工具结果。循环(1)-->(3)
import os
from openai import OpenAI
# 初始化OpenAI客户端,配置阿里云DashScope服务
client = OpenAI(
# 若没有配置环境变量,请用百炼API Key将下行替换为:api_key="sk-xxx",
api_key=os.getenv("DASHSCOPE_API_KEY"), # 从环境变量读取API密钥
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
)
# 输入用户请求
messages = [{"role": "user", "content": "今天是2025年3月17号,我马上要去上海出差,当天往返,请帮我查询今天从杭州到上海往返的火车票,此外,再帮我查询一下上海今天的天气。"}]
while True:
completion = client.chat.completions.create(
model="qwq-32b",
messages=messages,
tools=[{"type": "function", "function": fn} for fn in TOOLS], # 百炼API要求输入的工具格式
parallel_tool_calls=True,
stream=True,
)
# 打印模型流式回复
reasoning_content = ""
answer_content = ""
tool_calls = []
is_answering = False
print('\n[思考内容]: \n')
for chunk in completion:
delta = chunk.choices[0].delta
# AI的思考过程
if hasattr(delta, 'reasoning_content') and delta.reasoning_content is not None:
reasoning_content += delta.reasoning_content
print(delta.reasoning_content, end="", flush=True) # 实时输出思考过程
# 最终回复内容
if delta.content is not None:
if not is_answering:
is_answering = True
print('\n[回复内容]: \n')
answer_content += delta.content
print(delta.content, end="", flush=True) # 流式输出回复内容
# 工具调用信息(支持并行工具调用)
if delta.tool_calls is not None:
for tool_call in delta.tool_calls:
index = tool_call.index
# 动态扩展工具信息存储列表
if len(tool_calls) <= index:
tool_calls.append({'type': 'function', 'function': {'name': tool_call.function.name, 'arguments': tool_call.function.arguments}})
else:
# 收集函数参数(JSON字符串格式,需要后续解析)
if tool_call.function and tool_call.function.arguments:
tool_calls[index]['function']['arguments'] += tool_call.function.arguments
# 判断是否发起工具调用,如果有,则执行工具
if tool_calls:
print('\n[工具调用]: \n', tool_calls)
response = [{'role': 'assistant', 'content': answer_content, 'reasoning_content': reasoning_content, 'tool_calls': tool_calls}]
tool_response = []
for tool_call in tool_calls:
tool_name = tool_call['function']['name']
tool_args = json.loads(tool_call['function']['arguments'])
tool_exec_res = TOOL_EXEC_MAP[tool_name](**tool_args)
tool_response.append({'role': 'tool', 'content': tool_exec_res, 'name': tool_name})
print('\n[工具结果]: \n', tool_response)
# 拼接工具结果,和LLM进行下一轮对话
messages.extend(response)
messages.extend(tool_response)
else:
# 无工具执行,对话结束
response = [{'role': 'assistant', 'content': answer_content, 'reasoning_content': reasoning_content}]
messages.extend(response)
break
以上代码输出为:
[
{"role": "user", "content": "今天是2025年3月17号,我马上要去上海出差,当天往返,请帮我查询今天从杭州到上海往返的火车票,此外,再帮我查询一下上海今天的天气。"},
{"role": "assistant", "content": "", "reasoning_content": "好的,用户今天需要从杭州到上海出差,当天往返,并且需要查询今天的火车票和上海的天气。首先,我需要确认用户提供的日期是否正确。用户提到今天是2025年3月17日,所以日期参数应该是当天。\n\n对于火车票查询,用户明确提到了出发地是杭州,目的地是上海,日期是今天,也就是2025-03-17。需要往返票,但函数参数里只需要start、end和date,所以可能需要两次查询?或者往返是否需要分开处理?不过根据函数描述,可能每次调用只能查单程,所以可能需要两次调用,但用户可能只需要一次查询往返的信息。不过根据提供的函数参数,必须包含start、end和date,所以可能需要调用一次,但往返可能需要分开处理。但用户可能希望往返的信息,但函数可能不支持往返参数,所以可能需要两次调用?或者可能函数返回的结果包含往返选项?不确定,但按照现有函数结构,可能需要先调用一次从杭州到上海的单程,然后返回时从上海到杭州的单程。因此需要两次调用train_tickets函数,分别查询去程和返程。\n\n不过用户可能只需要一次查询,但根据函数参数,可能需要两次。因此,首先处理去程:start是杭州,end是上海,date是2025-03-17。然后返程是start上海,end杭州,同样的日期。不过用户可能希望当天往返,所以需要确保返程的时间在当天。不过可能用户只需要一次查询往返,但根据函数设计,可能需要分开调用。\n\n接下来是天气查询,用户需要上海今天的天气,所以调用get_weather函数,area参数是上海。\n\n现在需要按照步骤调用这两个函数。首先处理火车票,两次调用,然后天气查询。但可能用户希望先处理火车票再去天气。所以先处理train_tickets两次,然后get_weather一次。不过需要确认是否必须所有参数都正确。例如,用户说当天往返,所以date都是同一天。所以两次train_tickets调用,参数分别是杭州到上海,和上海到杭州,日期都是2025-03-17。\n\n因此,首先生成两个tool_call,然后一个天气查询。", "tool_calls": [{"type": "function", "function": {"name": "train_tickets", "arguments": "{\"start\": \"杭州\", \"end\": \"上海\", \"date\": \"2025-03-17\"}"}}, {"type": "function", "function": {"name": "train_tickets", "arguments": "{\"start\": \"上海\", \"end\": \"杭州\", \"date\": \"2025-03-17\"}"}}, {"type": "function", "function": {"name": "get_weather", "arguments": "{\"area\": \"上海\"}"}}]},
{"role": "tool", "content": "{\"costtime\": \"0小时48分\", \"trainno\": \"G7336\", \"arrivaltime\": \"8:34\", \"endstation\": \"上海南\", \"terminalstationcode\": \"SNH\", \"departstation\": \"苍南\", \"station\": \"杭州东\", \"departuretime\": \"7:46\", \"departstationcode\": \"CEH\"}", "name": "train_tickets"},
{"role": "tool", "content": "{\"costtime\": \"1小时19分\", \"trainno\": \"C3629\", \"arrivaltime\": \"17:34\", \"endstation\": \"杭州西\", \"terminalstationcode\": \"YWH\", \"departstation\": \"上海虹桥\", \"station\": \"上海虹桥\", \"departuretime\": \"16:15\", \"departstationcode\": \"AOH\"}", "name": "train_tickets"},
{"role": "tool", "content": "{\"area\": \"上海\", \"weather\": {\"areaid\": \"101020100\", \"temperature\": \"12\", \"weather\": \"晴\", \"wind_direction\": \"西风\", \"wind_power\": \"0-3级 微风 <5.4m/s\", \"weather_code\": \"00\"}}", "name": "get_weather"},
{"role": "assistant", "content": "好的,以下是您今天(2025年3月17日)从杭州到上海的行程信息及天气情况:\n\n---\n\n### **火车票信息**\n#### **去程(杭州→上海)**\n- **车次**:G7336 \n- **出发站**:杭州东站(CEH) \n- **出发时间**:7:46 \n- **到达站**:上海南站(SNH) \n- **到达时间**:8:34 \n- **耗时**:48分钟 \n\n#### **返程(上海→杭州)**\n- **车次**:C3629 \n- **出发站**:上海虹桥站(AOH) \n- **出发时间**:16:15 \n- **到达站**:杭州西站(YWH) \n- **到达时间**:17:34 \n- **耗时**:1小时19分钟 \n\n---\n\n### **上海今日天气**\n- **温度**:12°C \n- **天气**:晴 \n- **风力**:西风 0-3级(微风,<5.4m/s) \n\n---\n\n### **建议**\n1. **行程安排**: \n - 去程建议提前1小时到杭州东站,返程注意上海虹桥站的乘车时间。 \n - 上海虹桥站与上海南站距离较远,需预留足够换乘时间。 \n\n2. **天气提示**: \n - 白天晴朗但气温较低,建议携带外套和晴雨伞(备用)。 \n\n需要帮您进一步预订车票或提供交通接驳建议吗?", "reasoning_content": "好的,用户今天需要从杭州到上海出差,并且当天往返,还要查询上海的天气。首先,我需要整理一下用户提供的信息和工具返回的结果。\n\n用户给出的日期是2025年3月17日,今天。查询了杭州到上海的往返火车票,以及上海当天的天气。工具返回了两次火车票查询的结果和一次天气数据。\n\n首先看去程的火车票,杭州到上海的G7336次列车,出发时间是7:46,到达上海南站的时间是8:34,耗时48分钟。这趟车次应该很适合用户早上出发,当天就能到达上海开始工作。\n\n然后是返程的C3629次列车,从上海虹桥到杭州西,出发时间16:15,到达时间17:34,耗时1小时19分钟。用户可能需要在下午返回杭州,这样整个行程安排比较紧凑。\n\n接下来是天气情况,上海今天温度12度,天气晴朗,西风0-3级,微风。这样的天气适合出差,不会有降雨或大风影响出行。\n\n现在需要把这些信息以自然的方式呈现给用户。首先确认用户的需求是往返车票和天气,所以需要分点说明去程、返程和天气情况。要注意时间是否合理,比如用户是否能赶上返程的列车,是否有足够的停留时间。比如从早上8点到下午4点左右在上海,时间足够处理工作。\n\n另外,提醒用户注意天气情况,虽然天气晴朗,但温度较低,建议携带外套。同时,确认车次的出发和到达车站,确保用户知道具体站点,避免跑错车站。比如去程是杭州东到上海南,返程是上海虹桥到杭州西,可能需要提醒用户注意车站的不同,避免混淆。\n\n最后,总结一下信息,确保用户清楚所有安排,并询问是否需要进一步帮助,比如订票或交通建议。"}
]
Qwen-Agent
项目地址
https://github.com/QwenLM/Qwen-Agent
Qwen-Agent 封装了适配Qwen的工具调用模版,支持直接使用 OAI 兼容 API(例如 vLLM 部署)或DashScope API 接口,为原生不支持工具调用的 LLM推理接口提供了工具调用能力。
LLM接口:运行以下代码,完成一次含有工具调用的请求:
from qwen_agent.llm import get_chat_model
import os
# 获取封装的llm对象
llm = get_chat_model({
'model': 'qwq-32b',
# 使用dashscope API
'model_type': 'qwen_dashscope',
'api_key': os.getenv('DASHSCOPE_API_KEY')
# 使用自己部署的类OpenAI API(例如vLLM部署):
# 'model_server': 'http://localhost:8000/v1',# api_base
# 'api_key': 'EMPTY',
})
# 输入用户请求
messages = [{"role": "user", "content": "今天是2025年3月17号,我马上要去上海出差,当天往返,请帮我查询今天从杭州到上海往返的火车票,此外,再帮我查询一下上海今天的天气。"}]
while True:
responses = []
for responses in llm.chat(
messages=messages,
functions=TOOLS,
stream=True
):
pass
print('\n[模型回复]: \n', responses)
messages.extend(responses)
tool_response = []
for rsp in responses:
if rsp.get('function_call'):
tool_name = rsp['function_call']['name']
tool_args = json.loads(rsp['function_call']['arguments'])
tool_exec_res = TOOL_EXEC_MAP[tool_name](**tool_args)
tool_response.append({'role': 'function', 'content': tool_exec_res, 'name': tool_name})
print('\n[工具结果]: \n', tool_response)
if tool_response:
messages.extend(tool_response)
else:
break
以上代码完整对话消息为:
[ {"role":"user","content":"今天是2025年3月17号,我马上要去上海出差,当天往返,请帮我查询今天从杭州到上海往返的火车票,此外,再帮我查询一下上海今天的天气。"}, {"role":"assistant","content":"","reasoning_content":"好的,用户今天要从杭州到上海出差,当天往返,需要查询今天的往返火车票,还有上海的天气。首先,我需要确认用户提供的日期是2025年3月17日,所以日期参数没问题。\n\n先处理火车票查询。用户需要往返票,但提供的函数参数里只有单程的信息,可能需要分开查询去程和返程?不过函数可能只支持单程,所以可能需要两次调用?不过用户可能希望往返一起查,但根据工具描述,可能只能先查去程和返程两次。不过用户说当天往返,所以出发和到达城市需要反过来。第一次是杭州到上海,日期今天;第二次是上海回杭州,同样日期。但用户可能希望一次查询往返,但工具可能不支持,所以可能需要两次调用train_tickets函数,分别处理去和回的行程。不过用户的问题里可能只需要一次查询,但参数需要明确。所以可能需要先处理去程,然后返程。\n\n接下来是天气查询,用户需要上海今天的天气,所以调用get_weather函数,参数是上海。\n\n现在需要检查参数是否正确。对于火车票,start是杭州,end是上海,date今天。然后返程的话start是上海,end杭州,date同天。但用户可能希望往返,但工具可能不支持往返查询,所以需要两次调用。但用户的问题可能只需要一次查询,但可能需要分开两次。所以应该生成两个train_tickets的调用,分别去和回。但用户的问题可能只需要一次查询,但根据工具的参数,必须三个参数,所以两次调用。\n\n然后天气查询只需要一次,参数是上海。\n\n现在需要按照工具的格式生成调用。首先处理去程:杭州到上海,日期2025-03-17。然后返程:上海到杭州,同日期。再查询上海天气。\n\n所以需要三个tool_call,两次train_tickets和一次get_weather。"}, {"role":"assistant","content":"","reasoning_content":"","function_call":{"name":"train_tickets","arguments":"{\\"start\\": \\"杭州\\", \\"end\\": \\"上海\\", \\"date\\": \\"2025-03-17\\"}"}}, {"role":"assistant","content":"","reasoning_content":"","function_call":{"name":"train_tickets","arguments":"{\\"start\\": \\"上海\\", \\"end\\": \\"杭州\\", \\"date\\": \\"2025-03-17\\"}"}}, {"role":"assistant","content":"","reasoning_content":"","function_call":{"name":"get_weather","arguments":"{\\"area\\": \\"上海\\"}"}}, {"role":"function","content":"{\\"costtime\\": \\"0小时48分\\", \\"trainno\\": \\"G7336\\", \\"arrivaltime\\": \\"8:34\\", \\"endstation\\": \\"上海南\\", \\"terminalstationcode\\": \\"SNH\\", \\"departstation\\": \\"苍南\\", \\"station\\": \\"杭州东\\", \\"departuretime\\": \\"7:46\\", \\"departstationcode\\": \\"CEH\\"}","name":"train_tickets"}, {"role":"function","content":"{\\"costtime\\": \\"1小时19分\\", \\"trainno\\": \\"C3629\\", \\"arrivaltime\\": \\"17:34\\", \\"endstation\\": \\"杭州西\\", \\"terminalstationcode\\": \\"YWH\\", \\"departstation\\": \\"上海虹桥\\", \\"station\\": \\"上海虹桥\\", \\"departuretime\\": \\"16:15\\", \\"departstationcode\\": \\"AOH\\"}","name":"train_tickets"}, {"role":"function","content":"{\\"area\\": \\"上海\\", \\"weather\\": {\\"areaid\\": \\"101020100\\", \\"temperature\\": \\"12\\", \\"weather\\": \\"晴\\", \\"wind_direction\\": \\"西风\\", \\"wind_power\\": \\"0-3级 微风 <5.4m/s\\", \\"weather_code\\": \\"00\\"}}","name":"get_weather"}, {"role":"assistant","content":"","reasoning_content":"好的,用户今天需要从杭州到上海出差并当天往返,所以需要查询往返的火车票和上海的天气。首先处理火车票的信息。\n\n用户提供的出发地是杭州,目的地上海,日期是2025年3月17日。我需要调用train_tickets两次,一次是杭州到上海,另一次是上海返回杭州。根据工具的参数要求,必须提供start、end和date,所以两次查询都填上日期。\n\n然后看返回的火车票信息。第一次查询杭州到上海的结果是G7336次列车,7:46从杭州东出发,8:34到达上海南,耗时48分钟。这趟车时间很合适,早上出发,很快就能到,适合出差上午的行程。\n\n第二次查询上海返回杭州的是C3629次,16:15从上海虹桥出发,17:34到达杭州西,耗时1小时19分。这趟车下午四点多出发,晚上七点前就能回到杭州,确保当天往返没问题。\n\n接下来是天气查询,用户需要上海当天的天气。调用get_weather,参数是上海。返回的数据显示温度12度,晴,西风0-3级,微风。这样的天气适合出行,但提醒用户可能早晚较凉,建议带件薄外套。\n\n现在需要把这些信息整理成用户易懂的回复。先列出往返的车次和时间,方便用户选择。然后说明天气情况,给出适当的建议。确保信息清晰,没有遗漏关键数据,比如车次号、时间、温度等。同时检查是否有其他需要注意的事项,比如是否需要提前取票或天气变化的可能性,但根据现有数据,可能不需要额外提醒。最后用友好的语气结束,让用户知道有其他需求可以继续询问。"}, {"role":"assistant","content":"好的,以下是您需要的信息:\n\n### 上海往返杭州火车票查询结果:\n1. **杭州→上海(去程)** \n - 车次:G7336 \n - 出发时间:07:46(杭州东站) \n - 到达时间:08:34(上海南站) \n - 时长:48分钟 \n\n2. **上海→杭州(返程)** \n - 车次:C3629 \n - 出发时间:16:15(上海虹桥站) \n - 到达时间:17:34(杭州西站) \n - 时长:1小时19分 \n\n建议您根据行程安排选择以上班次,并提前完成购票。\n\n### 上海今日天气:\n- **温度**:12℃ \n- **天气**:晴 \n- **风力**:西风 0-3级(微风,<5.4m/s) \n- **建议**:白天适合出行,但早晚稍凉,可携带薄外套。\n\n祝您出差顺利,往返安全!如需其他帮助,请随时告诉我。","reasoning_content":""}]
一次完整的带有工具调用的对话 = “模型推理”+“工具执行”+“模型推理”,并且这个算法过程需要在模型外部自行实现。
为此,Qwen-Agent还提供了一个接口`Agent`,将以上过程封装起来,用户只需传入模型和工具,即可自动编排以上过程并获得完整的对话消息。
Agent接口:运行以下代码,完成一次和Agent的交互:
from qwen_agent.tools.base import BaseTool, register_tool
from typing import Union
import os
class GetWeather(BaseTool):
description = 'Weather inquiry.'
parameters = {
"type": "object",
"properties": {
"area": {
"type": "string",
"description": "Regional name, such as 丽江"
},
},
"required": ["area"]
}
def call(self, params: Union[str, dict], **kwargs) -> str:
params = self._verify_json_format_args(params)
tool_exec_res = TOOL_EXEC_MAP['get_weather'](**params)
return tool_exec_res
class TrainTickets(BaseTool):
description = 'Obtain train tickets and other information based on departure, arrival, and time.'
parameters = {
"type": "object",
"properties": {
"start": {
"type": "string",
"description": "The departure city."
},
"end": {
"type": "string",
"description": "The arrival city."
},
"date": {
"type": "string",
"description": "The date, such as 2024-02-21. If not clear, do not fill in."
}
},
"required": [
"start",
"end",
"date"
]
}
def call(self, params: Union[str, dict], **kwargs) -> str:
params = self._verify_json_format_args(params)
tool_exec_res = TOOL_EXEC_MAP['train_tickets'](**params)
return tool_exec_res
from qwen_agent.agents import Assistant
# 获取Agent对象
llm_cfg = {
'model': 'qwq-32b',
# 使用dashscope API
'model_type': 'qwen_dashscope',
'api_key': os.getenv('DASHSCOPE_API_KEY')
# 使用自己部署的类OpenAI API(例如vLLM部署):
# 'model_server': 'http://localhost:8000/v1',# api_base
# 'api_key': 'EMPTY',
}
tools = ['train_tickets', 'get_weather']# 确保工具已经提前被注册到Qwen-Agent中
bot = Assistant(llm=llm_cfg, function_list=tools)
# 对话
messages = [{"role": "user", "content": "今天是2025年3月17号,我马上要去上海出差,当天往返,请帮我查询今天从杭州到上海往返的火车票,此外,再帮我查询一下上海今天的天气。"}]
for responses in bot.run(messages=messages):
# 流式输出,此处做演示直接跳过取最后结果
pass
print('\n[模型回复]: \n', responses)
以上代码完整对话消息和「 LLM接口 」完全一致。
53AI,企业落地大模型首选服务商
产品:场景落地咨询+大模型应用平台+行业解决方案
承诺:免费场景POC验证,效果验证后签署服务协议。零风险落地应用大模型,已交付160+中大型企业
2025-03-26
硬核,字节一口气开源了两个类Manus智能体项目
2025-03-26
解密Manus:MCP协议让人人都能构建智能Agent
2025-03-25
首发!优刻得云平台上新DeepSeek-V3-0324模型
2025-03-25
仅3步!即刻拥有 QwQ-32B,性能比肩全球最强开源模型
2025-03-25
万卡集群真实部署,已节省数百万 GPU 小时!MoE 通信优化技术 COMET 开源
2025-03-25
阿里开源 Qwen2.5-VL-32B:小模型,大能量
2025-03-25
DeepSeek V3-0324 模型更新分析报告,被我和AI协作的9张图总结了
2025-03-25
OpenManus源码小读
2025-01-01
2024-07-25
2025-01-21
2024-05-06
2024-09-20
2024-07-20
2024-06-12
2024-08-13
2024-07-11
2024-12-26
2025-03-25
2025-03-25
2025-03-24
2025-03-22
2025-03-19
2025-03-17
2025-03-17
2025-03-13