mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-24 00:31:10 +00:00
117 lines
4.1 KiB
TypeScript
117 lines
4.1 KiB
TypeScript
import os from "node:os";
|
|
import path from "node:path";
|
|
import type {
|
|
ModelDefinitionConfig,
|
|
ModelProviderConfig,
|
|
} from "openclaw/plugin-sdk/provider-model-shared";
|
|
|
|
export const LLAMA_CPP_PROVIDER_ID = "llama-cpp";
|
|
export const LLAMA_CPP_PROVIDER_LABEL = "Local model (llama.cpp)";
|
|
const LLAMA_CPP_LOCAL_AUTH_MARKER = "llama-cpp-local";
|
|
const LLAMA_CPP_LOCAL_BASE_URL = "local://llama-cpp";
|
|
|
|
export function resolveLlamaCppSyntheticApiKey(): string {
|
|
return LLAMA_CPP_LOCAL_AUTH_MARKER;
|
|
}
|
|
|
|
export const DEFAULT_LLAMA_CPP_MODEL_ID = "gemma-4-e4b-it-q4_k_m";
|
|
export const DEFAULT_LLAMA_CPP_MODEL_REF = `${LLAMA_CPP_PROVIDER_ID}/${DEFAULT_LLAMA_CPP_MODEL_ID}`;
|
|
// Verified 2026-07-16: 4,977,169,568 bytes (about 5.0 GB) from the public
|
|
// Unsloth Hugging Face repository metadata and response headers.
|
|
export const DEFAULT_LLAMA_CPP_MODEL_URI =
|
|
"hf:unsloth/gemma-4-E4B-it-GGUF/gemma-4-E4B-it-Q4_K_M.gguf";
|
|
export const DEFAULT_LLAMA_CPP_MODEL_CACHE_FILE =
|
|
"hf_unsloth_gemma-4-E4B-it-GGUF_gemma-4-E4B-it-Q4_K_M.gguf";
|
|
export const DEFAULT_LLAMA_CPP_MODEL_SIZE_BYTES = 4_977_169_568;
|
|
export const DEFAULT_LLAMA_CPP_CONTEXT_SIZE = 8192;
|
|
|
|
// 5 GB weights + KV cache + OS headroom. Below 16 GiB the bundled default
|
|
// thrashes, so the owner decision for 2026-07 is to omit that offer entirely.
|
|
const LLAMA_CPP_DEFAULT_MODEL_RAM_FLOOR_BYTES = 16 * 1024 ** 3;
|
|
|
|
export function meetsLlamaCppDefaultModelRamFloor(totalmemBytes = os.totalmem()): boolean {
|
|
return totalmemBytes >= LLAMA_CPP_DEFAULT_MODEL_RAM_FLOOR_BYTES;
|
|
}
|
|
|
|
export function resolveLlamaCppModelCacheDir(provider?: ModelProviderConfig): string {
|
|
const configured = provider?.params?.modelCacheDir;
|
|
return typeof configured === "string" && configured.trim()
|
|
? resolveHomePath(configured.trim())
|
|
: path.join(os.homedir(), ".node-llama-cpp", "models");
|
|
}
|
|
|
|
function resolveHomePath(value: string): string {
|
|
if (value === "~") {
|
|
return os.homedir();
|
|
}
|
|
if (value.startsWith("~/")) {
|
|
return path.join(os.homedir(), value.slice(2));
|
|
}
|
|
return value;
|
|
}
|
|
|
|
export function resolveLlamaCppModelSource(model: {
|
|
id: string;
|
|
params?: Record<string, unknown>;
|
|
}): string {
|
|
const configured = model.params?.modelPath;
|
|
if (typeof configured === "string" && configured.trim()) {
|
|
return resolveHomePath(configured.trim());
|
|
}
|
|
return model.id === DEFAULT_LLAMA_CPP_MODEL_ID
|
|
? DEFAULT_LLAMA_CPP_MODEL_URI
|
|
: resolveHomePath(model.id);
|
|
}
|
|
|
|
export function resolveCachedLlamaCppModelPath(params: {
|
|
model: Pick<ModelDefinitionConfig, "id" | "params">;
|
|
provider?: ModelProviderConfig;
|
|
}): string | null {
|
|
const source = resolveLlamaCppModelSource(params.model);
|
|
const cacheDir = resolveLlamaCppModelCacheDir(params.provider);
|
|
if (source === DEFAULT_LLAMA_CPP_MODEL_URI) {
|
|
return path.join(cacheDir, DEFAULT_LLAMA_CPP_MODEL_CACHE_FILE);
|
|
}
|
|
if (/^hf:/i.test(source)) {
|
|
return null;
|
|
}
|
|
if (/^https?:\/\//i.test(source)) {
|
|
return null;
|
|
}
|
|
const localPath = resolveHomePath(source);
|
|
return path.isAbsolute(localPath) ? localPath : path.resolve(cacheDir, localPath);
|
|
}
|
|
|
|
function buildDefaultLlamaCppModel(): ModelDefinitionConfig {
|
|
return {
|
|
id: DEFAULT_LLAMA_CPP_MODEL_ID,
|
|
name: "Gemma 4 E4B (Q4_K_M)",
|
|
api: "openai-completions",
|
|
reasoning: false,
|
|
input: ["text"],
|
|
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
contextWindow: DEFAULT_LLAMA_CPP_CONTEXT_SIZE,
|
|
contextTokens: DEFAULT_LLAMA_CPP_CONTEXT_SIZE,
|
|
maxTokens: 2048,
|
|
params: {
|
|
modelPath: DEFAULT_LLAMA_CPP_MODEL_URI,
|
|
contextSize: "auto",
|
|
},
|
|
compat: { supportsTools: true, supportsUsageInStreaming: true },
|
|
};
|
|
}
|
|
|
|
export function buildLlamaCppProviderConfig(existing?: ModelProviderConfig): ModelProviderConfig {
|
|
const defaultModel = buildDefaultLlamaCppModel();
|
|
const configuredModels = existing?.models ?? [];
|
|
const models = configuredModels.some((model) => model.id === defaultModel.id)
|
|
? configuredModels
|
|
: [...configuredModels, defaultModel];
|
|
return {
|
|
...existing,
|
|
baseUrl: existing?.baseUrl ?? LLAMA_CPP_LOCAL_BASE_URL,
|
|
api: existing?.api ?? "openai-completions",
|
|
models,
|
|
};
|
|
}
|