Skip to content

Commit 1b51f6e

Browse files
authored
Merge pull request #1518 from rstudio/keras-constraints
Set `UV_CONSTRAINT` and `UV_OVERRIDE` for better compat with `keras-hub` and `tensorflow-text`
2 parents f1e3ff8 + da7f902 commit 1b51f6e

File tree

4 files changed

+81
-2
lines changed

4 files changed

+81
-2
lines changed

R/install.R

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,8 @@ use_backend <- function(backend, gpu = NA) {
170170
reticulate::import("os")$environ$update(list(KERAS_BACKEND = backend))
171171
}
172172

173+
set_envvar("UV_CONSTRAINT", pkg_file("keras-constraints.txt"),
174+
action = "append", sep = " ", unique = TRUE)
173175

174176
switch(
175177
paste0(get_os(), "_", backend),
@@ -222,18 +224,19 @@ use_backend <- function(backend, gpu = NA) {
222224
gpu <- has_gpu()
223225

224226
if (gpu) {
227+
uv_unset_override_tf_cpu()
225228
py_require(action = "remove", c("tensorflow", "tensorflow-cpu"))
226229
py_require("tensorflow[and-cuda]")
227230
} else {
228-
py_require(action = "remove", c("tensorflow", "tensorflow[and-cuda]"))
229-
py_require("tensorflow-cpu")
231+
uv_set_override_tf_cpu()
230232
}
231233
},
232234

233235
Linux_jax = {
234236
py_require(action = "remove",
235237
c("tensorflow", "tensorflow[and-cuda]",
236238
"jax[cuda12]", "jax[cpu]"))
239+
uv_set_override_tf_cpu()
237240

238241
if (is.na(gpu))
239242
gpu <- has_gpu()
@@ -248,6 +251,7 @@ use_backend <- function(backend, gpu = NA) {
248251

249252
Linux_torch = {
250253
py_require(c("tensorflow", "tensorflow[and-cuda]"), action = "remove")
254+
uv_set_override_tf_cpu()
251255

252256
if (is.na(gpu))
253257
gpu <- has_gpu()
@@ -264,6 +268,7 @@ use_backend <- function(backend, gpu = NA) {
264268
},
265269

266270
Linux_numpy = {
271+
uv_set_override_tf_cpu()
267272
py_require(c("tensorflow", "tensorflow[and-cuda]"), action = "remove")
268273
py_require(c("tensorflow-cpu", "numpy", "jax[cpu]"))
269274
},
@@ -301,8 +306,62 @@ use_backend <- function(backend, gpu = NA) {
301306
invisible(backend)
302307
}
303308

309+
set_envvar <- function(
310+
name,
311+
value,
312+
action = c("replace", "append", "prepend"),
313+
sep = .Platform$path.sep,
314+
unique = FALSE
315+
) {
316+
old <- Sys.getenv(name, NA)
317+
318+
if (is.null(value) || is.na(value)) {
319+
Sys.unsetenv(name)
320+
return(invisible(old))
321+
}
322+
323+
if (!is.na(old)) {
324+
value <- switch(
325+
match.arg(action),
326+
replace = value,
327+
append = paste(old, value, sep = sep),
328+
prepend = paste(value, old, sep = sep)
329+
)
330+
if (unique) {
331+
value <- unique(unlist(strsplit(value, sep, fixed = TRUE)))
332+
value <- paste0(value, collapse = sep)
333+
}
334+
}
335+
336+
value <- list(value)
337+
names(value) <- name
338+
do.call(Sys.setenv, value)
339+
invisible(old)
340+
}
304341

342+
uv_set_override_tf_cpu <- function() {
343+
py_require(action = "remove", c(
344+
"tensorflow", "tensorflow[and-cuda]", "tensorflow-cpu",
345+
"tensorflow-metal", "tensorflow-macos"
346+
))
347+
py_require(if (is_linux()) "tensorflow-cpu" else "tensorflow")
348+
set_envvar("UV_OVERRIDE", pkg_file("tf-cpu-override.txt"),
349+
action = "append", sep = " ", unique = TRUE)
350+
}
305351

352+
uv_unset_override_tf_cpu <- function() {
353+
override <- Sys.getenv("UV_OVERRIDE", NA)
354+
if (is.na(override)) return()
355+
cpu_override <- pkg_file("tf-cpu-override.txt")
356+
if (override == cpu_override) {
357+
Sys.unsetenv(override)
358+
} else {
359+
new <- gsub(cpu_override, "", override, fixed = TRUE)
360+
new <- gsub(" +", " ", new)
361+
Sys.setenv("UV_OVERRIDE" = new)
362+
}
363+
invisible(override)
364+
}
306365

307366
get_os <- function() {
308367
if (is_windows()) "Windows" else if (is_mac_arm64()) "macOS" else "Linux"
@@ -321,6 +380,13 @@ is_keras_loaded <- function() {
321380
!exists("module", envir = keras)
322381
}
323382

383+
pkg_file <- function(..., package = "keras3") {
384+
path <- system.file(..., package = "keras3", mustWork = TRUE)
385+
if(is_windows())
386+
path <- utils::shortPathName(path)
387+
path
388+
}
389+
324390

325391
has_gpu <- function() {
326392

inst/keras-constraints.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
2+
# unconstrained keras-hub in a larger requirements list might resolve to v0.19.0,
3+
# which is over a year old and generally what people want, and arguably a bug with `uv`.
4+
# This is a workaround to nudge uv to resolve the latest keras-hub.
5+
keras-hub>0.19.0
6+
7+
8+
# tensorflow-text 2.19.* fails to load with tensorflow-cpu>=2.19.0
9+
tensorflow-cpu==2.18.*

inst/tf-cpu-override.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
tensorflow; sys_platform == "never"

tools/install.R

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/usr/bin/Rscript
2+
3+
remotes::install_local(force = TRUE)

0 commit comments

Comments
 (0)