Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion extensions/llamacpp-extension/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,18 @@
"recommended": ""
}
},

{
"key": "llamacpp_env",
"title": "Environmental variables",
"description": "Environmental variables for llama.cpp(KEY=VALUE), separated by ';'",
"controllerType": "input",
"controllerProps": {
"value": "none",
"placeholder": "Eg, GGML_VK_VISIBLE_DEVICES='0,1'",
"type": "text",
"textAlign": "right"
}
},
{
"key": "auto_update_engine",
"title": "Auto update engine",
Expand Down
33 changes: 33 additions & 0 deletions extensions/llamacpp-extension/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ type LlamacppConfig = {
version_backend: string
auto_update_engine: boolean
auto_unload: boolean
llamacpp_env: string
chat_template: string
n_gpu_layers: number
offload_mmproj: boolean
Expand Down Expand Up @@ -146,6 +147,7 @@ const logger = {
export default class llamacpp_extension extends AIEngine {
provider: string = 'llamacpp'
autoUnload: boolean = true
llamacpp_env: string = ''
readonly providerId: string = 'llamacpp'

private config: LlamacppConfig
Expand Down Expand Up @@ -175,6 +177,7 @@ export default class llamacpp_extension extends AIEngine {
this.config = loadedConfig as LlamacppConfig

this.autoUnload = this.config.auto_unload
this.llamacpp_env = this.config.llamacpp_env

// This sets the base directory where model files for this provider are stored.
this.providerPath = await joinPath([
Expand Down Expand Up @@ -801,6 +804,8 @@ export default class llamacpp_extension extends AIEngine {
closure()
} else if (key === 'auto_unload') {
this.autoUnload = value as boolean
} else if (key === 'llamacpp_env') {
this.llamacpp_env = value as string
}
}

Expand Down Expand Up @@ -1133,6 +1138,27 @@ export default class llamacpp_extension extends AIEngine {
}
}

private parseEnvFromString(
target: Record<string, string>,
envString: string
): void {
envString
.split(';')
.filter((pair) => pair.trim())
.forEach((pair) => {
const [key, ...valueParts] = pair.split('=')
const cleanKey = key?.trim()

if (
cleanKey &&
valueParts.length > 0 &&
!cleanKey.startsWith('LLAMA')
) {
target[cleanKey] = valueParts.join('=').trim()
}
})
}

override async load(
modelId: string,
overrideSettings?: Partial<LlamacppConfig>,
Expand Down Expand Up @@ -1221,6 +1247,9 @@ export default class llamacpp_extension extends AIEngine {
const api_key = await this.generateApiKey(modelId, String(port))
envs['LLAMA_API_KEY'] = api_key

// set user envs
this.parseEnvFromString(envs, this.llamacpp_env)

// model option is required
// NOTE: model_path and mmproj_path can be either relative to Jan's data folder or absolute path
const modelPath = await joinPath([
Expand Down Expand Up @@ -1596,6 +1625,9 @@ export default class llamacpp_extension extends AIEngine {
`Invalid version/backend format: ${cfg.version_backend}. Expected format: <version>/<backend>`
)
}
// set envs
const envs: Record<string, string> = {}
this.parseEnvFromString(envs, this.llamacpp_env)

// Ensure backend is downloaded and ready before proceeding
await this.ensureBackendReady(backend, version)
Expand All @@ -1606,6 +1638,7 @@ export default class llamacpp_extension extends AIEngine {
const dList = await invoke<DeviceList[]>('plugin:llamacpp|get_devices', {
backendPath,
libraryPath,
envs,
})
return dList
} catch (error) {
Expand Down
3 changes: 2 additions & 1 deletion src-tauri/plugins/tauri-plugin-llamacpp/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,8 +265,9 @@ pub async fn unload_llama_model<R: Runtime>(
pub async fn get_devices(
backend_path: &str,
library_path: Option<&str>,
envs: HashMap<String, String>
) -> ServerResult<Vec<DeviceInfo>> {
get_devices_from_backend(backend_path, library_path).await
get_devices_from_backend(backend_path, library_path, envs).await
}

/// Generate API key using HMAC-SHA256
Expand Down
3 changes: 3 additions & 0 deletions src-tauri/plugins/tauri-plugin-llamacpp/src/device.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::process::Stdio;
use std::time::Duration;
use tokio::process::Command;
Expand All @@ -19,6 +20,7 @@ pub struct DeviceInfo {
pub async fn get_devices_from_backend(
backend_path: &str,
library_path: Option<&str>,
envs: HashMap<String, String>,
) -> ServerResult<Vec<DeviceInfo>> {
log::info!("Getting devices from server at path: {:?}", backend_path);

Expand All @@ -27,6 +29,7 @@ pub async fn get_devices_from_backend(
// Configure the command to run the server with --list-devices
let mut command = Command::new(backend_path);
command.arg("--list-devices");
command.envs(envs);

// Set up library path
setup_library_path(library_path, &mut command);
Expand Down
Loading