Update LLM support for llama.cpp and enhance configuration management
- Added support for `llamacpp-models.yaml` in `.gitignore` and implemented logic to copy it in `gpu-rent.ps1` and `gpu-rent.sh`. - Enhanced CLI to prompt for llama.cpp model presets during setup and execution, improving user experience. - Updated configuration handling to include `llamacpp_models_manifest` and related functions for managing llama.cpp models. - Improved documentation in `cli.md` and `llm.md` to reflect changes in llama.cpp integration and model management. - Refactored provisioning logic to handle llama.cpp model downloads and configurations effectively.
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
from pathlib import Path
|
||||
|
||||
from gpu_rent.llm_runtime import (
|
||||
gguf_filename_from_url,
|
||||
parse_llamacpp_models,
|
||||
write_llamacpp_models_preset,
|
||||
)
|
||||
|
||||
|
||||
def test_gguf_filename_from_url():
|
||||
url = (
|
||||
"https://huggingface.co/org/repo/resolve/main/"
|
||||
"Qwen2.5-3B-Instruct-Q4_K_M.gguf"
|
||||
)
|
||||
assert gguf_filename_from_url(url) == "Qwen2.5-3B-Instruct-Q4_K_M.gguf"
|
||||
|
||||
|
||||
def test_write_and_parse_llamacpp_preset(tmp_path: Path):
|
||||
path = tmp_path / "llamacpp-models.yaml"
|
||||
write_llamacpp_models_preset(path, "light")
|
||||
entries = parse_llamacpp_models(path)
|
||||
assert len(entries) == 1
|
||||
assert entries[0].default is True
|
||||
assert "Qwen2.5-3B" in entries[0].url
|
||||
assert entries[0].url.startswith("https://")
|
||||
|
||||
|
||||
def test_parse_llamacpp_empty(tmp_path: Path):
|
||||
path = tmp_path / "llamacpp-models.yaml"
|
||||
write_llamacpp_models_preset(path, "empty")
|
||||
assert parse_llamacpp_models(path) == []
|
||||
@@ -0,0 +1,61 @@
|
||||
from gpu_rent.inventory import FlavorInfo
|
||||
from gpu_rent.ux import prompt_server_plan
|
||||
from gpu_rent.varsfile import parse_vars_file, upsert_vars
|
||||
|
||||
|
||||
def _cfg_stub(monkeypatch, data_gb: int = 100):
|
||||
monkeypatch.setenv("OS_AUTH_URL", "https://example.invalid/identity/v3")
|
||||
monkeypatch.setenv("OS_USER_DOMAIN_NAME", "999")
|
||||
monkeypatch.setenv("OS_USERNAME", "svc")
|
||||
monkeypatch.setenv("OS_PASSWORD", "secret")
|
||||
monkeypatch.setenv("OS_PROJECT_ID", "proj")
|
||||
monkeypatch.setenv("OS_REGION_NAME", "ru-7")
|
||||
monkeypatch.setenv("GPU_RENT_AZ", "ru-7a")
|
||||
monkeypatch.setenv("DATA_VOLUME_SIZE_GB", str(data_gb))
|
||||
from gpu_rent.config import load_config
|
||||
|
||||
return load_config(require_auth=True)
|
||||
|
||||
|
||||
def test_prompt_server_plan_with_ranked(monkeypatch, tmp_path):
|
||||
cfg = _cfg_stub(monkeypatch)
|
||||
monkeypatch.setattr("gpu_rent.paths.app_root", lambda: tmp_path)
|
||||
f1 = FlavorInfo(
|
||||
id="a", name="small", vcpus=4, ram_mb=16384, disabled=False, extra={}, label="4090-24"
|
||||
)
|
||||
f2 = FlavorInfo(
|
||||
id="b", name="big", vcpus=12, ram_mb=65536, disabled=False, extra={}, label="4090-48"
|
||||
)
|
||||
|
||||
monkeypatch.setattr(
|
||||
"gpu_rent.ux.list_ranked_flavors",
|
||||
lambda flavors, cfg: [f1, f2],
|
||||
)
|
||||
answers = iter(["2", "200", "n"])
|
||||
|
||||
def ask(msg: str, default: str = "") -> str:
|
||||
return next(answers)
|
||||
|
||||
remembered: list[bool] = []
|
||||
|
||||
plan = prompt_server_plan(
|
||||
cfg,
|
||||
["x"],
|
||||
picked=f1,
|
||||
spot=True,
|
||||
ask=ask,
|
||||
confirm=lambda m: remembered.append(True) or False,
|
||||
)
|
||||
assert plan.flavor.id == "b"
|
||||
assert plan.data_gb == 200
|
||||
assert plan.spot is False
|
||||
assert remembered
|
||||
|
||||
|
||||
def test_upsert_vars(tmp_path):
|
||||
path = tmp_path / "gpu-rent.vars"
|
||||
path.write_text("# c\nLLM_RUNTIME=none\n", encoding="utf-8")
|
||||
upsert_vars(path, {"LLM_RUNTIME": "llamacpp", "DATA_VOLUME_SIZE_GB": "200"})
|
||||
data = parse_vars_file(path)
|
||||
assert data["LLM_RUNTIME"] == "llamacpp"
|
||||
assert data["DATA_VOLUME_SIZE_GB"] == "200"
|
||||
Reference in New Issue
Block a user