最近在尝试用Qwen2.5和Llama3.1本地搭一个简单的AI Agent,主要想让它调用几个自定义工具(比如查天气、发邮件)。但发现一个问题:模型经常在工具调用时“脑补”参数,比如明明工具要求city参数是字符串,它给我传个数字,或者干脆不传就瞎执行。我用的是function calling格式,也试过ReAct prompt模板,感觉不太稳定。想问下大佬们,这种情况是模型本身对工具调用的理解能力不行,还是我的prompt设计有坑?或者有没有推荐的专门优化过tool use的开源基座模型?求指点,调得有点自闭了。
用开源模型搭Agent,工具调用总翻车,是选型不对还是prompt没写好?
全部回复
共 177 条说实话这俩模型裸跑function calling都容易飘,Qwen2.5对参数约束本来就弱,Llama3.1得把工具描述写进system里反复强调格式才行。我之前也卡在这,后来直接换glm-4-flash或者FireFunction V2这类专门调过的模型,稳定性立马上来了,你可以先拿它们跑通流程再回头调开源版。另外你试试把每个参数的类型和取值范围直接写死在工具描述里,比如“city: string,必填,只能填城市中文名”,能少很多脑补。
Qwen2.5对参数类型约束确实弱,建议把工具schema里的描述写死成例子,比prompt管用。
说实话这种问题我太有共鸣了,qwen2.5和llama3.1我都试过,工具调用翻车基本是常态,尤其参数强约束场景下,模型就是会自作主张。我后来把function calling的schema写得极其啰嗦,每个参数都带上类型说明、取值范围、甚至给个示例值,情况会好不少,但依然不是100%稳定。你提到的“脑补”参数,我怀疑跟温度设置也有关系,调低到0.1或者直接0,能减少很多幻觉式的填充。另外,ReAct模板对这类模型来说其实挺吃提示词工程,我后来换成更结构化的few-shot,就是每个工具都给两三个正反例,效果比单纯描述格式强很多。至于基座模型,可以看看qwen2.5的72b版本,或者试试glm-4系列,它们对tool use的指令跟随能力确实比同尺寸开源模型好一些,但本地部署成本得掂量下。还有个思路是加一层规则校验,模型输出后先硬检查参数类型,不对就强制重试,虽然笨但能兜底。最后想问下,你这些工具是自带的json schema还是自己写的?有时候格式不规范也会让模型理解跑偏。
俩都占点,但更可能是prompt里工具schema写太糙,试试把参数示例和边界条件怼进description里。
我之前也卡在这块,后来发现Qwen2.5对JSON格式的容错率确实低,你试试把工具描述里每个参数都加上例子,比如city写成“北京或Shanghai”,效果会好不少。另外,如果工具不多的话,用Llama3.1配个简单的few-shot示例比ReAct模板稳,让它照着格式模仿。至于专门优化过的模型,你可以看看functionary或者gorilla,这俩对工具调用的指令遵循做得更细,但可能得牺牲点通用能力。
参数校验得靠代码兜底,模型幻觉免不了,工具定义里加few-shot示例试试。
试试把工具描述写得更死板点,加上few-shot示例,Qwen对格式敏感得很。
说实话这问题大概率两样都占点,Qwen2.5的function calling本来就不如它家最新版稳,Llama3.1对复杂工具格式的跟随性也一般。我建议你先把工具描述改成极简的JSON schema,去掉所有多余字段,很多“脑补”其实是prompt里给了模型自由发挥的空间。另外可以试试FireFunction-v2或者GLM-4-Flash这类专门做tool use的模型,本地跑不动的话用API也行,我之前换了之后成功率直接翻倍。
大概率是模型本身工具调用能力不够,Qwen2.5对参数约束比较敏感,换个专门微调过的比如ToolLlama或者试下加个JSON schema强校验会稳很多。
参数校验得自己写死,别指望模型自觉,工具定义里加正则和枚举约束能救一半。
说实话这问题我也踩过坑,Qwen2.5的function calling对参数类型约束确实弱,经常瞎填。你可以试试在prompt里把工具schema写成更严格的JSON示例,比如给city字段加个枚举值列表,能明显减少乱传的情况。另外Llama3.1对工具调用的原生支持不如Qwen,但配合LangChain的tool binding层会稳一点。要是想省事,直接换GLM-4或Mixtral的tool use版本,它们在结构化输出上优化得更好,不过本地部署资源要求也高。
说实话,Qwen2.5和Llama3.1在function calling上确实不是强项,尤其本地部署+自定义工具时,模型对schema的遵循度会明显下降。我之前用Llama3.1试过类似场景,它经常把枚举值理解成自由文本,后来换成专门微调过tool use的模型,比如FireFunction v2或者Gorilla,稳定性直接上了一个台阶。不过你这情况也不全是模型锅,prompt里工具描述的写法很关键——比如把参数类型、示例值、约束条件直接写进description里,比单纯给JSON schema管用得多。另外,你试过在system prompt里加一条“必须严格按给定参数类型输出,禁止猜测或补全”之类的硬性规则吗?有时候模型会默认你有容错机制,所以它才敢乱来。还有个坑是温度设置,调低到0.1以下能减少很多随机性。要是还不行,建议给每个工具加一个预校验层,让模型输出先过一遍pydantic,不合法就重试一次,比让它自己悔改靠谱。
说实话这俩模型裸跑function calling确实容易飘,Qwen对参数类型约束本来就弱,建议试试加一层json schema校验,在prompt里把每个参数的示例值和类型错误惩罚写清楚,会稳很多。另外可以看看FireFunction-v2或者GLM-4系列,这俩对工具调用的指令遵循做得更好,Llama3.1其实更适合走纯文本推理再自己解析。我之前也踩过这个坑,后来直接把工具描述改成“参数必须是字符串,否则返回错误码”,模型反而老实了,你也可以试试这种“威胁式”prompt。
说实话这俩模型在pure function calling上都不算强项,尤其Qwen2.5对参数类型约束比较敏感,建议先试试把工具描述里的类型说明写得更具体,比如直接加示例值进去。另外你如果用的是vLLM或者SGLang部署,检查下是不是没开tool_choice=required,有时候模型会默认跳过调用直接瞎编。实在不行可以看看GLM-4-9B或者Firefunction,这两个对工具调用的稳定性会好一些。
我之前也卡在这块儿,后来发现多半是prompt里给的few-shot示例太少或者太抽象,模型没吃透参数约束。你试试在系统提示里把每个工具的参数格式写成JSON schema的样子,再塞两个极端反例进去,效果会明显好一些。另外Qwen2.5对function calling的指令遵循其实比Llama3.1稳一点,要是还不行可以看看FireFunction-V2或者Toolformer这类专门调过的模型,不过对本地部署的资源要求会高些。
大概率是模型本身tool use能力不够,Qwen2.5得换Qwen2.5-Turbo或者试试glm-4-flash,参数校验逻辑也得在代码里兜底。
Qwen2.5和Llama3.1在function calling上确实不如专门微调过的模型稳定,参数脑补是常见毛病,尤其本地部署时量化精度还会放大这个问题。你可以试试给每个工具加严格的JSON Schema示例,并在prompt里明确说“不匹配就返回错误”,比单纯强调格式管用。另外,目前开源里对tool use优化比较好的有FireFunction-V2和Glaive-function-calling-v2,跑起来比通用模型省心不少。你用的温度是设了多少?如果偏高也会加剧乱填参数。
说实话这俩模型在function calling上确实都不算强项,Qwen2.5好点但也会偶尔抽风。建议你试试把工具schema描述写得更具体,比如在description里直接加“city必须是字符串,别传数字”这种话,能明显减少脑补。另外可以看下ToolACE或者GLM-4这类专门调过tool use的模型,我换过来之后成功率提升挺明显的。
大概率是prompt的锅,Qwen对工具参数约束得写死,加个few-shot例子立马稳。
试试把工具描述写成JSON schema再塞进system,比模板管用。
说实话两个都有点问题,Qwen2.5和Llama3.1原生tool calling能力确实偏弱,特别是参数类型这种细节容易翻车,建议直接换专门微调过的模型比如ToolLlama或者FireFunction,能省不少事。另外你ReAct模板里最好把每个工具的参数schema写得更死板一点,比如直接给例子“city必须是字符串,例如'北京'”,模型跟着样例走会老实很多。我之前也卡这坑里,后来干脆在prompt里加了一步“先输出JSON再执行”,效果稳定不少。