This commit is contained in:
TheK0tYaRa 2026-02-12 16:11:22 +02:00
commit ce26fcb59c
22 changed files with 2899 additions and 0 deletions

View file

@ -0,0 +1,84 @@
{ config, lib, pkgs, ... }:
let
cfg = config.programs.llama-cpp;
defaultArgsBash =
lib.concatStringsSep " " (map lib.escapeShellArg cfg.defaultArgs);
globalEosTextBash =
lib.escapeShellArg (lib.concatStringsSep "\n" cfg.eosStrings);
presetBash =
lib.concatMapStringsSep "\n" (p: ''
PRESET_PATHS[${lib.escapeShellArg p.name}]=${lib.escapeShellArg p.path}
PRESET_ALIAS[${lib.escapeShellArg p.name}]=${lib.escapeShellArg (p.alias or p.name)}
PRESET_EOS_TEXT[${lib.escapeShellArg p.name}]=${lib.escapeShellArg (lib.concatStringsSep "\n" (p.eosStrings or []))}
'') cfg.presets;
template = builtins.readFile ./llama-serve.sh;
scriptText = lib.replaceStrings
[
"@server_bin@"
"@default_args@"
"@global_eos_text@"
"@preset_bash@"
]
[
"${cfg.package}/bin/${cfg.serverBinary}"
defaultArgsBash
globalEosTextBash
presetBash
]
template;
wrapper = pkgs.writeShellScriptBin cfg.wrapperName scriptText;
in {
options.programs.llama-cpp = {
enable = lib.mkEnableOption "llama.cpp wrapper for llama-server";
package = lib.mkPackageOption pkgs "llama-cpp" { };
serverBinary = lib.mkOption {
type = lib.types.str;
default = "llama-server";
};
wrapperName = lib.mkOption {
type = lib.types.str;
default = "llama-serve";
};
defaultArgs = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
description = "Args always passed to llama-server before user args.";
};
eosStrings = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
};
presets = lib.mkOption {
type = lib.types.listOf (lib.types.submodule ({ ... }: {
options = {
name = lib.mkOption { type = lib.types.str; };
path = lib.mkOption { type = lib.types.str; };
alias = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; };
eosStrings = lib.mkOption { type = lib.types.listOf lib.types.str; default = [ ]; };
};
}));
default = [ ];
};
};
config = lib.mkIf cfg.enable {
home.packages = [
cfg.package
wrapper
];
};
}

View file

@ -0,0 +1,87 @@
#!/usr/bin/env bash
set -euo pipefail
SERVER_BIN="@server_bin@"
DEFAULT_ARGS=( @default_args@ )
GLOBAL_EOS_TEXT=@global_eos_text@
declare -A PRESET_PATHS
declare -A PRESET_ALIAS
declare -A PRESET_EOS_TEXT
@preset_bash@
usage() {
cat >&2 <<'EOF'
Usage:
llama-serve <preset-name|/path/to/model.gguf> [llama-server args...]
If <preset-name> matches programs.llama-cpp.presets[].name, its path/alias/eosStrings are used.
Global eosStrings + preset eosStrings are appended as repeated --reverse-prompt entries.
EOF
if ((${#PRESET_PATHS[@]})); then
echo >&2
echo "Presets:" >&2
for k in "${!PRESET_PATHS[@]}"; do
echo " $k -> ${PRESET_PATHS[$k]}" >&2
done
fi
exit 2
}
((${#} >= 1)) || usage
spec="$1"
shift || true
model_path=""
model_alias=""
preset_eos=""
if [[ -n "${PRESET_PATHS[$spec]+x}" ]]; then
model_path="${PRESET_PATHS[$spec]}"
model_alias="${PRESET_ALIAS[$spec]:-$spec}"
preset_eos="${PRESET_EOS_TEXT[$spec]:-}"
else
model_path="$spec"
model_alias=""
preset_eos=""
fi
# expand ~/...
if [[ "$model_path" == "~/"* ]]; then
model_path="$HOME/${model_path#~/}"
fi
# if [[ ! -f "$model_path" ]]; then
# echo "Model not found: $model_path" >&2
# exit 1
# fi
model_flag="-m"
model_spec="$model_path"
# If arg1 doesn't resolve to an existing local file, treat it as a Hugging Face repo spec.
if [[ ! -f "$model_path" ]]; then
model_flag="-hf"
fi
args=( "${DEFAULT_ARGS[@]}" )
add_reverse_prompts_from_text() {
local text="$1"
[[ -n "$text" ]] || return 0
while IFS= read -r line; do
[[ -n "$line" ]] || continue
args+=( "--reverse-prompt" "$line" )
done <<<"$text"
}
add_reverse_prompts_from_text "$GLOBAL_EOS_TEXT"
add_reverse_prompts_from_text "$preset_eos"
# Optional: set REST API alias when preset provides one (llama-server supports --alias). :contentReference[oaicite:3]{index=3}
if [[ -n "$model_alias" ]]; then
args+=( "--alias" "$model_alias" )
fi
# exec "$SERVER_BIN" -m "$model_path" "${args[@]}" "$@"
exec "$SERVER_BIN" "$model_flag" "$model_spec" "${args[@]}" "$@"