Skip to content

fix(backend): resolve relative draft_model paths against the models dir#9680

Merged
mudler merged 2 commits into
masterfrom
fix/draft-model-path-resolution
May 5, 2026
Merged

fix(backend): resolve relative draft_model paths against the models dir#9680
mudler merged 2 commits into
masterfrom
fix/draft-model-path-resolution

Conversation

@localai-bot
Copy link
Copy Markdown
Collaborator

Summary

  • Resolve relative draft_model paths against the configured models directory in core/backend/options.go, mirroring how parameters.model and mmproj already work. Without this, llama.cpp tries to open the path from the backend's CWD and fails with No such file or directory, forcing users to hard-code an absolute path as a workaround.
  • Add an e2e regression test (tests/e2e/path_resolution_test.go) that confirms the main model file, mmproj, and draft_model all arrive at the backend resolved to absolute paths.

Why

Reported in #9675. The user's working parameters.model and broken draft_model had identical relative-path syntax — the config looked symmetric, but only one side was resolved. Their workaround (/models/... absolute path) confirmed the diagnosis.

The fix is one block in grpcModelOpts:

if c.DraftModel != "" && !filepath.IsAbs(c.DraftModel) {
    opts.DraftModel = filepath.Join(modelPath, c.DraftModel)
}

Test plan

  • New spec passes with the fix: go test -count=1 -run TestLocalAI ./tests/e2e/ -ginkgo.label-filter PathResolution
  • New spec fails when the fix is reverted (regression actually caught — verified by temporarily removing the new lines)
  • All 25 existing MockBackend-labelled specs still pass

The mock backend gained a small instrumentation hook: LoadModel records the incoming ModelOptions, and Predict echoes them as JSON when the prompt contains ECHO_LOAD_PARAMS. No new RPC, no test-only fields on the wire.

Closes #9675

mudler added 2 commits May 5, 2026 22:48
The main model file and mmproj are joined with the configured models
directory before reaching the backend, but draft_model was sent
verbatim. With a relative draft_model in the YAML config, llama.cpp
opens the path from the backend process's CWD and fails with "No such
file or directory", forcing users to hard-code an absolute path.

Mirror the existing mmproj resolution: if draft_model is relative,
join it with modelPath. Absolute paths are passed through unchanged.

Adds an e2e regression test against the mock backend that asserts the
main model file, mmproj, and draft_model all arrive at the backend
resolved to absolute paths.

Closes #9675

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Assisted-by: Claude:claude-opus-4-7-1m [Read] [Edit] [Bash] [Write]
…rtcut)

The previous commit kept absolute draft_model paths intact via an
IsAbs check. That left a path-traversal vector open: a user-supplied
YAML config could set draft_model to /etc/passwd (or any other host
file the backend process can read) and the path would be sent through
unchanged.

filepath.Join cleans the leading slash from absolute components, so
joining unconditionally — the way mmproj already does — keeps the
result rooted at the configured models directory regardless of input.

Adds a second e2e spec that feeds an absolute draft_model into the
mock backend and asserts the path is clamped under modelsPath.

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
Assisted-by: Claude:claude-opus-4-7-1m [Read] [Edit] [Bash]
@mudler mudler merged commit 70cf8ac into master May 5, 2026
19 of 20 checks passed
@mudler mudler deleted the fix/draft-model-path-resolution branch May 5, 2026 22:58
@localai-bot localai-bot added the bug Something isn't working label May 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Draft Model Issue

2 participants