Skip to content

Commit 5c3a6fe

Browse files
authored
feat: Add support for custom environmental variables to llama.cpp (#6256)
This commit adds a new setting `llamacpp_env` to the llama.cpp extension, allowing users to specify custom environment variables. These variables are passed to the backend process when it starts. A new function `parseEnvFromString` is introduced to handle the parsing of the semicolon-separated key-value pairs from the user input. The environment variables are then used in the `load` function and when listing available devices. This enables more flexible configuration of the llama.cpp backend, such as specifying visible GPUs for Vulkan. This change also updates the Tauri command `get_devices` to accept environment variables, ensuring that device discovery respects the user's settings.
1 parent 5c4deff commit 5c3a6fe

File tree

4 files changed

+50
-2
lines changed

4 files changed

+50
-2
lines changed

extensions/llamacpp-extension/settings.json

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,18 @@
1010
"recommended": ""
1111
}
1212
},
13-
13+
{
14+
"key": "llamacpp_env",
15+
"title": "Environmental variables",
16+
"description": "Environmental variables for llama.cpp(KEY=VALUE), separated by ';'",
17+
"controllerType": "input",
18+
"controllerProps": {
19+
"value": "none",
20+
"placeholder": "Eg, GGML_VK_VISIBLE_DEVICES='0,1'",
21+
"type": "text",
22+
"textAlign": "right"
23+
}
24+
},
1425
{
1526
"key": "auto_update_engine",
1627
"title": "Auto update engine",

extensions/llamacpp-extension/src/index.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ type LlamacppConfig = {
4141
version_backend: string
4242
auto_update_engine: boolean
4343
auto_unload: boolean
44+
llamacpp_env: string
4445
chat_template: string
4546
n_gpu_layers: number
4647
offload_mmproj: boolean
@@ -153,6 +154,7 @@ const logger = {
153154
export default class llamacpp_extension extends AIEngine {
154155
provider: string = 'llamacpp'
155156
autoUnload: boolean = true
157+
llamacpp_env: string = ''
156158
readonly providerId: string = 'llamacpp'
157159

158160
private config: LlamacppConfig
@@ -183,6 +185,7 @@ export default class llamacpp_extension extends AIEngine {
183185
this.config = loadedConfig as LlamacppConfig
184186

185187
this.autoUnload = this.config.auto_unload
188+
this.llamacpp_env = this.config.llamacpp_env
186189

187190
// This sets the base directory where model files for this provider are stored.
188191
this.providerPath = await joinPath([
@@ -827,6 +830,8 @@ export default class llamacpp_extension extends AIEngine {
827830
closure()
828831
} else if (key === 'auto_unload') {
829832
this.autoUnload = value as boolean
833+
} else if (key === 'llamacpp_env') {
834+
this.llamacpp_env = value as string
830835
}
831836
}
832837

@@ -1253,6 +1258,27 @@ export default class llamacpp_extension extends AIEngine {
12531258
}
12541259
}
12551260

1261+
private parseEnvFromString(
1262+
target: Record<string, string>,
1263+
envString: string
1264+
): void {
1265+
envString
1266+
.split(';')
1267+
.filter((pair) => pair.trim())
1268+
.forEach((pair) => {
1269+
const [key, ...valueParts] = pair.split('=')
1270+
const cleanKey = key?.trim()
1271+
1272+
if (
1273+
cleanKey &&
1274+
valueParts.length > 0 &&
1275+
!cleanKey.startsWith('LLAMA')
1276+
) {
1277+
target[cleanKey] = valueParts.join('=').trim()
1278+
}
1279+
})
1280+
}
1281+
12561282
override async load(
12571283
modelId: string,
12581284
overrideSettings?: Partial<LlamacppConfig>,
@@ -1341,6 +1367,9 @@ export default class llamacpp_extension extends AIEngine {
13411367
const api_key = await this.generateApiKey(modelId, String(port))
13421368
envs['LLAMA_API_KEY'] = api_key
13431369

1370+
// set user envs
1371+
this.parseEnvFromString(envs, this.llamacpp_env)
1372+
13441373
// model option is required
13451374
// NOTE: model_path and mmproj_path can be either relative to Jan's data folder or absolute path
13461375
const modelPath = await joinPath([
@@ -1716,6 +1745,9 @@ export default class llamacpp_extension extends AIEngine {
17161745
`Invalid version/backend format: ${cfg.version_backend}. Expected format: <version>/<backend>`
17171746
)
17181747
}
1748+
// set envs
1749+
const envs: Record<string, string> = {}
1750+
this.parseEnvFromString(envs, this.llamacpp_env)
17191751

17201752
// Ensure backend is downloaded and ready before proceeding
17211753
await this.ensureBackendReady(backend, version)
@@ -1726,6 +1758,7 @@ export default class llamacpp_extension extends AIEngine {
17261758
const dList = await invoke<DeviceList[]>('plugin:llamacpp|get_devices', {
17271759
backendPath,
17281760
libraryPath,
1761+
envs,
17291762
})
17301763
return dList
17311764
} catch (error) {

src-tauri/plugins/tauri-plugin-llamacpp/src/commands.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,8 +265,9 @@ pub async fn unload_llama_model<R: Runtime>(
265265
pub async fn get_devices(
266266
backend_path: &str,
267267
library_path: Option<&str>,
268+
envs: HashMap<String, String>
268269
) -> ServerResult<Vec<DeviceInfo>> {
269-
get_devices_from_backend(backend_path, library_path).await
270+
get_devices_from_backend(backend_path, library_path, envs).await
270271
}
271272

272273
/// Generate API key using HMAC-SHA256

src-tauri/plugins/tauri-plugin-llamacpp/src/device.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use serde::{Deserialize, Serialize};
2+
use std::collections::HashMap;
23
use std::process::Stdio;
34
use std::time::Duration;
45
use tokio::process::Command;
@@ -19,6 +20,7 @@ pub struct DeviceInfo {
1920
pub async fn get_devices_from_backend(
2021
backend_path: &str,
2122
library_path: Option<&str>,
23+
envs: HashMap<String, String>,
2224
) -> ServerResult<Vec<DeviceInfo>> {
2325
log::info!("Getting devices from server at path: {:?}", backend_path);
2426

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

3134
// Set up library path
3235
setup_library_path(library_path, &mut command);

0 commit comments

Comments
 (0)