Skip to content

Commit d7b9291

Browse files
committed
fix(llamacpp): resolve --model-dir to the top-level GGUF, not a nested draft
find_gguf globbed **/*.gguf recursively and returned the lexically-first match, so a --model-dir pointing at a directory that also holds the draft/MTP GGUF in a subdirectory resolved the model to the draft (e.g. an object-store FUSE prefix carrying both Model.gguf and MTP/draft.gguf -- "MTP" sorts before the model name). Download mode never hit this because model and draft are separate artifacts in separate mount dirs; fuse delivery surfaces them under one prefix. Prefer GGUFs directly in the given directory and only recurse when none are found there; sharded-shard and nested-only layouts are unaffected. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: Michael Hotan <mike@union.ai>
1 parent 3e2a605 commit d7b9291

2 files changed

Lines changed: 17 additions & 2 deletions

File tree

plugins/llamacpp/src/flyteplugins/llamacpp/_server.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,18 @@
3232
def find_gguf(path: str) -> str:
3333
"""Resolve the GGUF file to serve from a mounted file or directory.
3434
35-
For sharded models only the first shard is passed to llama-server (it discovers
35+
GGUFs directly in `path` win over any in subdirectories: a `--model-dir` may point at a
36+
mount that also holds the draft/MTP GGUF in a *subdirectory* (e.g. an object-store FUSE
37+
prefix carrying both `Model.gguf` and `MTP/draft.gguf`), and a recursive match could
38+
otherwise resolve the model to the draft. Only if no GGUF sits directly in `path` do we
39+
recurse. For sharded models only the first shard is passed to llama-server (it discovers
3640
the rest itself), so `*-00001-of-*.gguf` wins over other matches.
3741
"""
3842
if os.path.isfile(path):
3943
return path
40-
matches = sorted(glob.glob(os.path.join(path, "**", "*.gguf"), recursive=True))
44+
matches = sorted(glob.glob(os.path.join(path, "*.gguf")))
45+
if not matches:
46+
matches = sorted(glob.glob(os.path.join(path, "**", "*.gguf"), recursive=True))
4147
if not matches:
4248
raise FileNotFoundError(f"No .gguf files found under {path!r}")
4349
first_shards = [m for m in matches if "-00001-of-" in Path(m).name]

plugins/llamacpp/tests/test_server_shim.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,15 @@ def test_find_gguf_nested(tmp_path):
3131
assert find_gguf(str(tmp_path)) == gguf
3232

3333

34+
def test_find_gguf_prefers_top_level_over_subdir_draft(tmp_path):
35+
"""A model-dir that also holds the draft/MTP GGUF in a subdirectory (the object-store
36+
FUSE layout) must resolve to the top-level model, not the nested draft -- even though the
37+
draft's path sorts first."""
38+
model = _touch(tmp_path / "Qwen3-27B-Q4_K_M.gguf")
39+
_touch(tmp_path / "MTP" / "mtp-draft-Q4_0.gguf")
40+
assert find_gguf(str(tmp_path)) == model
41+
42+
3443
def test_find_gguf_prefers_first_shard(tmp_path):
3544
# "a-..." sorts before the shard files; the first shard must still win.
3645
_touch(tmp_path / "a-mmproj.gguf")

0 commit comments

Comments
 (0)