Skip to content

Commit 3659c82

Browse files
authored
feat: kvbm v2 memory crate (#4012)
Signed-off-by: Ryan Olson <[email protected]>
1 parent bc02088 commit 3659c82

File tree

19 files changed

+3175
-0
lines changed

19 files changed

+3175
-0
lines changed

Cargo.lock

Lines changed: 36 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,16 @@ members = [
66
"launch/dynamo-run",
77
"lib/llm",
88
"lib/runtime",
9+
"lib/config",
910
"lib/tokens",
11+
"lib/memory",
1012
"lib/async-openai",
1113
"lib/parsers",
1214
"lib/bindings/c",
1315
"lib/bindings/python/codegen",
1416
"lib/engines/*",
1517
"lib/kvbm",
18+
"lib/config",
1619
]
1720
# Exclude certain packages that are slow to build and we don't ship as flagship
1821
# features from default build, but keep them in workspace for convenience.
@@ -21,6 +24,7 @@ members = [
2124
default-members = [
2225
"lib/llm",
2326
"lib/runtime",
27+
"lib/config",
2428
"lib/tokens",
2529
"lib/async-openai",
2630
"lib/parsers",
@@ -42,6 +46,7 @@ keywords = ["llm", "genai", "inference", "nvidia", "distributed"]
4246
# Local crates
4347
dynamo-runtime = { path = "lib/runtime", version = "0.6.1" }
4448
dynamo-llm = { path = "lib/llm", version = "0.6.1" }
49+
dynamo-config = { path = "lib/config", version = "0.6.1" }
4550
dynamo-tokens = { path = "lib/tokens", version = "0.6.1" }
4651
dynamo-async-openai = { path = "lib/async-openai", version = "0.6.1", features = [
4752
"byot",

lib/config/Cargo.toml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
[package]
5+
name = "dynamo-config"
6+
version.workspace = true
7+
edition.workspace = true
8+
description.workspace = true
9+
authors.workspace = true
10+
license.workspace = true
11+
homepage.workspace = true
12+
repository.workspace = true
13+
keywords.workspace = true
14+
15+
[dependencies]
16+
anyhow = { workspace = true }

lib/config/src/lib.rs

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
// SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
//! Configuration utilities and trait re-exports.
5+
//!
6+
//! This module provides utility functions for parsing configuration values
7+
//! and re-exports the core configuration traits from the integrations module.
8+
9+
// ===== Environment Variable Utilities =====
10+
11+
/// Check if a string is truthy.
12+
///
13+
/// This will be used to evaluate environment variables or any other subjective
14+
/// configuration parameters that can be set by the user that should be evaluated
15+
/// as a boolean value.
16+
///
17+
/// Truthy values: "1", "true", "on", "yes" (case-insensitive)
18+
///
19+
/// Returns `false` for invalid values. Use [`parse_bool`] if you need to error on invalid values.
20+
pub fn is_truthy(val: &str) -> bool {
21+
matches!(val.to_lowercase().as_str(), "1" | "true" | "on" | "yes")
22+
}
23+
24+
/// Check if a string is falsey.
25+
///
26+
/// This will be used to evaluate environment variables or any other subjective
27+
/// configuration parameters that can be set by the user that should be evaluated
28+
/// as a boolean value (opposite of is_truthy).
29+
///
30+
/// Falsey values: "0", "false", "off", "no" (case-insensitive)
31+
///
32+
/// Returns `false` for invalid values. Use [`parse_bool`] if you need to error on invalid values.
33+
pub fn is_falsey(val: &str) -> bool {
34+
matches!(val.to_lowercase().as_str(), "0" | "false" | "off" | "no")
35+
}
36+
37+
/// Parse a string as a boolean value, returning an error if invalid.
38+
///
39+
/// This function strictly validates that the input is a valid boolean representation.
40+
///
41+
/// # Arguments
42+
/// * `val` - The string value to parse
43+
///
44+
/// # Returns
45+
/// * `Ok(true)` - For truthy values: "1", "true", "on", "yes" (case-insensitive)
46+
/// * `Ok(false)` - For falsey values: "0", "false", "off", "no" (case-insensitive)
47+
/// * `Err(_)` - For any other value
48+
///
49+
/// # Example
50+
/// ```ignore
51+
/// assert_eq!(parse_bool("true")?, true);
52+
/// assert_eq!(parse_bool("0")?, false);
53+
/// assert!(parse_bool("maybe").is_err());
54+
/// ```
55+
pub fn parse_bool(val: &str) -> anyhow::Result<bool> {
56+
if is_truthy(val) {
57+
Ok(true)
58+
} else if is_falsey(val) {
59+
Ok(false)
60+
} else {
61+
anyhow::bail!(
62+
"Invalid boolean value: '{}'. Expected one of: true/false, 1/0, on/off, yes/no",
63+
val
64+
)
65+
}
66+
}
67+
68+
/// Check if an environment variable is truthy.
69+
///
70+
/// Returns `false` if the environment variable is not set or is invalid.
71+
/// Use [`env_parse_bool`] if you need to distinguish between unset, valid, and invalid values.
72+
pub fn env_is_truthy(env: &str) -> bool {
73+
match std::env::var(env) {
74+
Ok(val) => is_truthy(val.as_str()),
75+
Err(_) => false,
76+
}
77+
}
78+
79+
/// Check if an environment variable is falsey.
80+
///
81+
/// Returns `false` if the environment variable is not set or is invalid.
82+
/// Use [`env_parse_bool`] if you need to distinguish between unset, valid, and invalid values.
83+
pub fn env_is_falsey(env: &str) -> bool {
84+
match std::env::var(env) {
85+
Ok(val) => is_falsey(val.as_str()),
86+
Err(_) => false,
87+
}
88+
}
89+
90+
/// Parse an environment variable as a boolean, returning an error if invalid.
91+
///
92+
/// # Arguments
93+
/// * `env` - The environment variable name
94+
///
95+
/// # Returns
96+
/// * `Ok(Some(true))` - If the env var is set to a truthy value
97+
/// * `Ok(Some(false))` - If the env var is set to a falsey value
98+
/// * `Ok(None)` - If the env var is not set
99+
/// * `Err(_)` - If the env var is set to an invalid value
100+
///
101+
/// # Example
102+
/// ```ignore
103+
/// match env_parse_bool("MY_FLAG")? {
104+
/// Some(true) => println!("enabled"),
105+
/// Some(false) => println!("disabled"),
106+
/// None => println!("not configured"),
107+
/// }
108+
/// ```
109+
pub fn env_parse_bool(env: &str) -> anyhow::Result<Option<bool>> {
110+
match std::env::var(env) {
111+
Ok(val) => parse_bool(&val).map(Some),
112+
Err(std::env::VarError::NotPresent) => Ok(None),
113+
Err(e) => anyhow::bail!("Failed to read environment variable {}: {}", env, e),
114+
}
115+
}
116+
117+
#[cfg(test)]
118+
mod tests {
119+
use super::*;
120+
121+
#[test]
122+
fn test_is_truthy() {
123+
assert!(is_truthy("1"));
124+
assert!(is_truthy("true"));
125+
assert!(is_truthy("True"));
126+
assert!(is_truthy("TRUE"));
127+
assert!(is_truthy("on"));
128+
assert!(is_truthy("ON"));
129+
assert!(is_truthy("yes"));
130+
assert!(is_truthy("YES"));
131+
132+
assert!(!is_truthy("0"));
133+
assert!(!is_truthy("false"));
134+
assert!(!is_truthy("off"));
135+
assert!(!is_truthy("no"));
136+
assert!(!is_truthy(""));
137+
assert!(!is_truthy("random"));
138+
}
139+
140+
#[test]
141+
fn test_is_falsey() {
142+
assert!(is_falsey("0"));
143+
assert!(is_falsey("false"));
144+
assert!(is_falsey("False"));
145+
assert!(is_falsey("FALSE"));
146+
assert!(is_falsey("off"));
147+
assert!(is_falsey("OFF"));
148+
assert!(is_falsey("no"));
149+
assert!(is_falsey("NO"));
150+
151+
assert!(!is_falsey("1"));
152+
assert!(!is_falsey("true"));
153+
assert!(!is_falsey("on"));
154+
assert!(!is_falsey("yes"));
155+
assert!(!is_falsey(""));
156+
assert!(!is_falsey("random"));
157+
}
158+
159+
#[test]
160+
fn test_env_is_truthy_not_set() {
161+
// Test with a variable that definitely doesn't exist
162+
assert!(!env_is_truthy("DEFINITELY_NOT_SET_VAR_12345"));
163+
}
164+
165+
#[test]
166+
fn test_env_is_falsey_not_set() {
167+
// Test with a variable that definitely doesn't exist
168+
assert!(!env_is_falsey("DEFINITELY_NOT_SET_VAR_12345"));
169+
}
170+
171+
#[test]
172+
fn test_parse_bool() {
173+
// Truthy values
174+
assert!(parse_bool("1").unwrap());
175+
assert!(parse_bool("true").unwrap());
176+
assert!(parse_bool("TRUE").unwrap());
177+
assert!(parse_bool("on").unwrap());
178+
assert!(parse_bool("yes").unwrap());
179+
180+
// Falsey values
181+
assert!(!parse_bool("0").unwrap());
182+
assert!(!parse_bool("false").unwrap());
183+
assert!(!parse_bool("FALSE").unwrap());
184+
assert!(!parse_bool("off").unwrap());
185+
assert!(!parse_bool("no").unwrap());
186+
187+
// Invalid values
188+
assert!(parse_bool("").is_err());
189+
assert!(parse_bool("maybe").is_err());
190+
assert!(parse_bool("2").is_err());
191+
assert!(parse_bool("random").is_err());
192+
}
193+
194+
#[test]
195+
fn test_env_parse_bool_not_set() {
196+
// Test with a variable that definitely doesn't exist
197+
assert_eq!(
198+
env_parse_bool("DEFINITELY_NOT_SET_VAR_12345").unwrap(),
199+
None
200+
);
201+
}
202+
}

lib/memory/Cargo.toml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
[package]
5+
name = "dynamo-memory"
6+
version.workspace = true
7+
edition.workspace = true
8+
authors.workspace = true
9+
license.workspace = true
10+
repository.workspace = true
11+
12+
[features]
13+
default = ["testing-all"]
14+
15+
# feature to enable unsafe slices of memory descriptors
16+
# for advanced testing in other crates
17+
unsafe-slices = []
18+
19+
# test features for hardware-specific tests
20+
testing-cuda = []
21+
testing-nixl = []
22+
testing-all = ["testing-cuda", "testing-nixl"]
23+
24+
[dependencies]
25+
dynamo-config = { workspace = true }
26+
27+
anyhow = { workspace = true }
28+
cudarc = { workspace = true }
29+
nixl-sys = { version = "0.7" }
30+
serde = { workspace = true}
31+
thiserror = { workspace = true }
32+
tracing = { workspace = true }
33+
34+
libc = { version = "0.2" }
35+
nix = { version = "0.30", features = ["fs"] }
36+
offset-allocator = "0.2"
37+
38+
[dev-dependencies]
39+
tempfile = "3"

0 commit comments

Comments
 (0)