groq 0.11 上跑 llama-3.1-8b 做函数调用,返回 400 tool_use_failed,原文 failed_generation 里是一段带单引号的伪 JSON,函数名外面还包了 markdown 反引号,把 tools 去掉就正常。
一开始怀疑是「没有开 strict 模式,服务端不做语法约束」,查了一圈,方向不对。
原因不止一个,得分开看。小模型不擅长严格 JSON,参数里混进单引号和注释。少数情况下是工具描述过长,模型把说明文字也写进了参数。
另外,temperature 给到 1,同一请求的结果每次格式都不同。
动手时先把原始 failed_generation 打出来看结构
python -c "import json;d=json.load(open('err.json'));print(d['error']['failed_generation'][:300])"
随后用 json5 兜底解析并统计失败率
python -c "import json5;print(json5.loads(open('raw.txt').read()))"
然后把 temperature 降到 0.1 并把工具描述砍到 80 字
curl -s https://api.groq.com/openai/v1/chat/completions -H "Authorization: Bearer $GROQ_API_KEY" -d '{"model":"llama-3.1-8b-instant","temperature":0.1,"tools":[{"type":"function","function":{"name":"get_price","description":"查价格","parameters":{"type":"object","properties":{"sku":{"type":"string"}},"required":["sku"]}}}]}'
末了加一层重试,第二次附上错误样例再问
python retry_tool.py --max-retry 2 --show-failed
恢复的判定其实很直接。失败率从 18% 降到 1% 以下,failed_generation 里不再出现单引号,函数名与 tools 定义完全一致。
提醒一点。这类失败不是网络问题,是模型输出格式跑偏,兜底解析加一次重问比反复重试同一个提示更有效。这类问题最好一次改到位,反复小改反而容易把原因搅混。
