Eval bug: Segmentation fault if a tool named “call” is called on llama-server

在 llama-server 上启用工具调用(tools / OpenAI function calling)时,如果请求里的函数名恰好叫 call ,服务端会在构建 PEG 语法时发生规则名冲突,导致解析器无限递归并触发崩溃: Eval bug: Segmentation fault if a t

快速结论:在 llama-server 上启用工具调用(tools / OpenAI function calling)时,如果请求里的函数名恰好叫 call,服务端会在构建 PEG 语法时发生规则名冲突,导致解析器无限递归并触发崩溃:Eval bug: Segmentation fault if a tool named "call" is called on llama-server。优先排查工具/函数名是否与内部规则名冲突。

适用环境:Issue 中确认的环境为 Linux x86_64、CPU backend(-dev none)、llama-server version 0.5.0-dev(build 11376, commit a55e952b8)、使用 --jinja,测试模型为 bartowski/Llama-3.2-1B-Instruct-GGUF:Q4_0。

最快修复方案:暂无确认的一步修复方案。Issue 中给出了社区修复方向(用工具索引派生规则名、避免规则名冲突),并标注“PR’s are welcome”,但截至 Issue 关闭并未合入已验证的补丁。可优先尝试的规避方式是:不要使用 call 这类可能与内部规则名冲突的短名称作为工具/函数名。

注意事项:改名的规避方式只绕开已知冲突,不修复“规则名碰撞”这个更广泛的问题;Issue 评论指出规则与语法内部构建普遍未做防冲突处理,可能还有其他名称会触发异常行为。仓库维护者建议做通用修复,但该通用修复在本 Issue 中并未给出。

问题场景

用户在 Linux 上运行 llama-server,通过 --jinja 启用工具调用能力,并以 OpenAI 兼容的 /v1/chat/completions 接口发送请求。请求中定义了一个名为 call 的函数(tool/function name)。

复现过程中,先调用名为 phone 的工具可以正常返回 tool_calls;随后调用名为 call 的工具时,llama-server 进程直接段错误崩溃。

Issue 作者指出 call 是合法的 OpenAI function name(name = [a-zA-Z0-9_-],长度 ≤ 64),属于正常输入,而不是畸形请求。

报错原文

Eval bug: Segmentation fault if a tool named "call" is called on llama-server

repro.sh: line 15: 1950028 Segmentation fault      (core dumped) "$SERVER" -hf bartowski/Llama-3.2-1B-Instruct-GGUF:Q4_0 -dev none --jinja -fit off --port $PORT > /dev/null 2>&1

The parse tree is
Sequence(Literal(<|start_header_id|>assistant<|end_header_id|>

), Space, Epsilon, Repetition(Tag(content, Until({)), 0, 1), Repetition(Rule(tool-call, Sequence(Literal(), Space, Choice([cycle(cyclic reference to Rule)]), Space, Literal())), 0, 1), End)

The parser stuck in a infinite loop of Rule -> Sequence -> Choice -> Rule.

原因分析

根据 Issue 评论中的定位,崩溃的直接原因是 PEG 解析器进入无限递归(infinite recursion / infinite loop):Rule -> Sequence -> Choice -> Rule。

当工具名称为 call 时,构建语法规则时产生了名称碰撞:聊天处理器内部已经使用 tool-call 作为内部规则名,而由工具名派生出的规则名也变成了 tool-call(即为 "tool-" + "call")。后者的定义覆盖了前者,导致内层 Rule() 引用回自身,形成循环引用。

评论中给出的对比证实了这一点:如果把 tool-call 改成类似 tool-callllllll 的其他名称,就工作正常。

Issue 作者认为,语法构建时未对请求文本做转义/保留前缀处理,是更深层的原因;评论区也指出,规则和语法内部构建普遍没有防冲突处理,这不止影响这一个崩溃,还可能造成相关 Issue 中的多种异常行为。

环境排查

  • 确认 llama-server 版本:Issue 中为 version: 0.5.0-dev (build 11376, commit a55e952b8),编译于 Linux x86_64,GNU 13.3.0。
  • 确认后端:Issue 使用 -dev none,即 CPU backend;未涉及 CUDA 或显卡相关设置。
  • 确认启动参数:需包含 --jinja,因为工具调用语法与 Jinja 模板相关。
  • 确认模型:Issue 使用 bartowski/Llama-3.2-1B-Instruct-GGUF:Q4_0。
  • 确认触发请求:/v1/chat/completions 请求体中 tools[].function.name 是否包含 call。
  • 如果复现脚本首次运行需下载模型(约 0.8 GB),确认网络与磁盘空间是否正常。

解决步骤

  1. 在服务端日志或启动命令中确认是否使用了 --jinja,并确认 llama-server 版本与 Issue 一致。
  2. 检查发给 /v1/chat/completions 的请求,确认 tools 数组里是否有 "name": "call"。
  3. 可优先尝试的规避方案:将工具/函数名从 call 改为不与内部规则名冲突的名称,例如 phone 或带前缀的名称,然后重新发起同一请求。
  4. 如果需要确认崩溃点,可用 Issue 中的复现脚本:先调用名为 phone 的工具,再调用名为 call 的工具,观察服务端是否在第二个请求时崩溃。
  5. 目前没有已验证的一步修复补丁。Issue 评论中提到的正确方向包括:用工具索引派生规则名、在名称冲突时给 wrapper 规则追加编号直到名称可用、或对规则构建使用转义/保留前缀。这些均属于建议,尚未在 Issue 中作为合并修复确认。

验证方法

如果采用改名规避:对改名后的工具重新发送相同的 /v1/chat/completions 请求,服务端应正常返回 tool_calls,且不再出现 Segmentation fault (core dumped)。

如果将来应用了防冲突补丁:应能直接用名为 call 的工具正常调用,并返回包含 tool_calls 的响应,同时服务端进程保持存活。

参考来源

ggml-org/llama.cpp #29967

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 28041

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注