使用Qwen-agent构建智能体解决大模型数学计算问题
·
场景: 在某些场景中,需要大模型准确计算数学公式, 而语言模型天生不适合进行复杂的逻辑计算。因此把计算封装成函数。 使用agent解决逻辑计算问题.
第一步: 起模型服务
可以本地起服务
llm_cfg = {
# Use your own model service compatible with OpenAI API by vLLM/SGLang:
'model': 'Qwen/Qwen3-32B',
'model_server': 'http://localhost:8000/v1', # api_base
'api_key': 'EMPTY',
'generate_cfg': {
# When using vLLM/SGLang OAI API, pass the parameter of whether to enable thinking mode in this way
'extra_body': {
'chat_template_kwargs': {'enable_thinking': False}
},
# Add: When the content is `<think>this is the thought</think>this is the answer`
# Do not add: When the response has been separated by reasoning_content and content
# This parameter will affect the parsing strategy of tool call
# 'thought_in_content': True,
},
}
也可以调用部署好的云服务, 我使用的是阿里云百联的云服务.
llm_cfg = {
# Use the model service provided by DashScope:
'model': 'qwen3-30b-a3b-instruct-2507',
'model_type': 'qwen_dashscope',
'api_key': 'sk-',
# (Optional) LLM hyperparameters for generation:
'generate_cfg': {
'top_p': 0.8,
}
}
第二步,构建智能体主函数
@register_tool('tuixiu2')
class MyTuixiu(BaseTool):
# The `description` tells the agent the functionality of this tool.
description = '查询用户退休日期的工具, 提取用户的出生日期,格式是yyyy-MM, 返回用户的退休日期.'
# The `parameters` tell the agent what input parameters the tool has.
parameters = [{
'name': 'prompt',
'type': 'string',
'description': '用户的出生日期,格式是yyyy-MM',
'required': True
}]
这个地方要注意:
1) register_tool('tuixiu2')这个是你注册的函数, 要记下来
2)description 很重要, 大模型能不能关联到这个工具, 以及是否过度关联错误, 都需要这里描述. 主要描述这个工具的功能是什么, 什么查询意图下,调用这个工具, 以及工具需要提取的参数什么格式.
3)parameters这个是你提取的参数的格式, 重点要解释清楚提取什么格式的参数,传入到函数中.
如果提取的不干净,函数里面就要写异常处理,
这一步是函数的构建函数,也是核心的逻辑处理程序, 主要是接收parameters之后的处理过程,
就是一个python函数,改写即可
def call(self, params: str, **kwargs) -> str:
# `params` are the arguments generated by the LLM agent.
prompt = json5.loads(params)['prompt']
birth_date = str(prompt)
if isinstance(birth_date, str):
try:
# 支持 "YYYY-MM" 格式
parts = birth_date.split('-')
if len(parts) != 2:
raise ValueError("输入格式应为 YYYY-MM")
y, m = int(parts[0]), int(parts[1])
birth_date = date(y, m, 1) # 日期设为1号
except Exception as e:
raise ValueError(f"无法解析出生日期 '{birth_date}': {e}")
elif not isinstance(birth_date, date):
raise TypeError("birth_date 必须是 datetime.date 对象或可解析的日期字符串")
# 判断出生年月属于哪个区间
birth_year = birth_date.year
birth_month = birth_date.month
# 1964年12月及之前出生的,60周岁退休
if birth_year < 1965 or (birth_year == 1965 and birth_month == 1):
retirement_date = birth_date + relativedelta(years=60)
# 1965年1月至1976年8月出生的,按规则延迟
elif (birth_year == 1965 and birth_month >= 1) or \
(birth_year > 1965 and birth_year < 1976) or \
(birth_year == 1976 and birth_month <= 8):
# 计算从1965年1月开始的月份数
months_since_1965 = (birth_year - 1965) * 12 + (birth_month - 1)
# 每4个月为一个区间,每个区间延迟月数递增1个月
delay_months = months_since_1965 // 4 + 1
retirement_date = birth_date + relativedelta(years=60, months=delay_months)
# 1976年9月及之后出生的,63周岁退休
else:
retirement_date = birth_date + relativedelta(years=63)
return f"{retirement_date.year}-{retirement_date.month:02d}"
第三步, 系统配置
system_instruction = '''
你是一个客服助手,善于用精简的答案回复用户的问题。你需要遵循以下指示:
分析我的需求是否需要调用工具。如果不需要工具,你可以直接思考并提供答案。
我会给你很多工具,其中一些功能相似。请仔细分析当前需要调用哪个工具。
如果需要调用工具,你必须在每一轮中至少调用一个工具,直到任务完成。
如果你从工具调用中获得了有用的链接或图片,请在回答中一并输出。
仔细检查工具返回的结果:它包含什么内容?是否包含你需要的信息?
你没有内置的地理编码/坐标/链接。不要输出任何伪造的地理编码、坐标或链接。必须先通过工具查询这些信息!
不要随意调用工具。
对于需要执行特定任务或检索信息的请求,你必须使用以下格式(使用用户语言):
```
用户需要……
我已经详细分析了该请求,并将其分解为以下步骤:……
```
如果你有可用的工具来帮助解决问题,请按以下格式回答:
```
用户需要……
我已经详细分析了该请求,并将其分解为以下步骤:……
首先,我应该使用[Tool Name],因为[explain relevance]。所需的输入参数为:……
……
我已仔细审查了工具的输出结果。该结果确实/未能完全满足我的预期。接下来,我需要……
```
'''
tools = ['tuixiu2', 'code_interpreter'] #tuixiu2 是上一步,你注册的,名字要一致 `code_interpreter` is a built-in tool for executing code. For configuration details, please refer to the FAQ.
bot = Assistant(llm=llm_cfg,
system_message=system_instruction,
function_list=tools,)
这里我分享了一个不错的系统prompt, 用起来比较不错
我在windows下面没跑通, 在linux下面跑通的, 需要提前安装:https://github.com/QwenLM/Qwen-Agent
下面是完整的代码,用来计算男性的退休日期,
import pprint
import urllib.parse
import json5
from qwen_agent.agents import Assistant
from qwen_agent.tools.base import BaseTool, register_tool
from qwen_agent.utils.output_beautify import typewriter_print
import os
from datetime import date
from dateutil.relativedelta import relativedelta
# Step 1 (Optional): Add a custom tool named `my_image_gen`.
@register_tool('tuixiu2')
class MyTuixiu(BaseTool):
# The `description` tells the agent the functionality of this tool.
description = '查询用户退休日期的工具, 提取用户的出生日期,格式是yyyy-MM, 返回用户的退休日期.'
# The `parameters` tell the agent what input parameters the tool has.
parameters = [{
'name': 'prompt',
'type': 'string',
'description': '用户的出生日期,格式是yyyy-MM',
'required': True
}]
def call(self, params: str, **kwargs) -> str:
# `params` are the arguments generated by the LLM agent.
prompt = json5.loads(params)['prompt']
birth_date = str(prompt)
if isinstance(birth_date, str):
try:
# 支持 "YYYY-MM" 格式
parts = birth_date.split('-')
if len(parts) != 2:
raise ValueError("输入格式应为 YYYY-MM")
y, m = int(parts[0]), int(parts[1])
birth_date = date(y, m, 1) # 日期设为1号
except Exception as e:
raise ValueError(f"无法解析出生日期 '{birth_date}': {e}")
elif not isinstance(birth_date, date):
raise TypeError("birth_date 必须是 datetime.date 对象或可解析的日期字符串")
# 判断出生年月属于哪个区间
birth_year = birth_date.year
birth_month = birth_date.month
# 1964年12月及之前出生的,60周岁退休
if birth_year < 1965 or (birth_year == 1965 and birth_month == 1):
retirement_date = birth_date + relativedelta(years=60)
# 1965年1月至1976年8月出生的,按规则延迟
elif (birth_year == 1965 and birth_month >= 1) or \
(birth_year > 1965 and birth_year < 1976) or \
(birth_year == 1976 and birth_month <= 8):
# 计算从1965年1月开始的月份数
months_since_1965 = (birth_year - 1965) * 12 + (birth_month - 1)
# 每4个月为一个区间,每个区间延迟月数递增1个月
delay_months = months_since_1965 // 4 + 1
retirement_date = birth_date + relativedelta(years=60, months=delay_months)
# 1976年9月及之后出生的,63周岁退休
else:
retirement_date = birth_date + relativedelta(years=63)
return f"{retirement_date.year}-{retirement_date.month:02d}"
# Step 2: Configure the LLM you are using.
llm_cfg = {
# Use the model service provided by DashScope:
'model': 'qwen3-30b-a3b-instruct-2507',
'model_type': 'qwen_dashscope',
'api_key': 'sk-',
# (Optional) LLM hyperparameters for generation:
'generate_cfg': {
'top_p': 0.8,
}
}
# Step 3: Create an agent. Here we use the `Assistant` agent as an example, which is capable of using tools and reading files.
system_instruction = '''
你是一个客服助手,善于用精简的答案回复用户的问题。你需要遵循以下指示:
分析我的需求是否需要调用工具。如果不需要工具,你可以直接思考并提供答案。
我会给你很多工具,其中一些功能相似。请仔细分析当前需要调用哪个工具。
如果需要调用工具,你必须在每一轮中至少调用一个工具,直到任务完成。
如果你从工具调用中获得了有用的链接或图片,请在回答中一并输出。
仔细检查工具返回的结果:它包含什么内容?是否包含你需要的信息?
你没有内置的地理编码/坐标/链接。不要输出任何伪造的地理编码、坐标或链接。必须先通过工具查询这些信息!
不要随意调用工具。
对于需要执行特定任务或检索信息的请求,你必须使用以下格式(使用用户语言):
```
用户需要……
我已经详细分析了该请求,并将其分解为以下步骤:……
```
如果你有可用的工具来帮助解决问题,请按以下格式回答:
```
用户需要……
我已经详细分析了该请求,并将其分解为以下步骤:……
首先,我应该使用[Tool Name],因为[explain relevance]。所需的输入参数为:……
……
我已仔细审查了工具的输出结果。该结果确实/未能完全满足我的预期。接下来,我需要……
```
'''
tools = ['tuixiu2', 'code_interpreter'] # `code_interpreter` is a built-in tool for executing code. For configuration details, please refer to the FAQ.
bot = Assistant(llm=llm_cfg,
system_message=system_instruction,
function_list=tools,)
# Step 4: Run the agent as a chatbot.
messages = [] # This stores the chat history.
while True:
# For example, enter the query "draw a dog and rotate it 90 degrees".
query = input('\nuser query: ')
# Append the user query to the chat history.
messages.append({'role': 'user', 'content': query})
response = []
response_plain_text = ''
print('bot response:')
for response in bot.run(messages=messages):
# Streaming output.
response_plain_text = typewriter_print(response, response_plain_text)
# Append the bot responses to the chat history.
messages.extend(response)
更多推荐
所有评论(0)