Skip to content

Commit 1d065e5

Browse files
committed
fix: only attempt ollama pull if model is not already local
This also refactors the pip_install_if_needed() logic out of the run module and into the pull module. Signed-off-by: Nick Mitchell <[email protected]>
1 parent 47f1dd6 commit 1d065e5

File tree

4 files changed

+91
-74
lines changed

4 files changed

+91
-74
lines changed

pdl-live-react/src-tauri/src/cli/run.rs

Lines changed: 4 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,10 @@
1-
use ::file_diff::diff;
2-
use ::std::fs::{copy, create_dir_all};
3-
use ::std::path::{Path, PathBuf};
1+
use ::std::path::Path;
42
use duct::cmd;
53
use futures::executor::block_on;
64
use yaml_rust2::yaml::LoadError;
75

8-
use tauri::path::BaseDirectory;
9-
use tauri::Manager;
10-
11-
use crate::interpreter::load;
12-
13-
#[cfg(desktop)]
14-
async fn pip_install_if_needed(app_handle: tauri::AppHandle) -> Result<PathBuf, tauri::Error> {
15-
let cache_path = app_handle.path().cache_dir()?.join("pdl");
16-
17-
create_dir_all(&cache_path)?;
18-
let venv_path = cache_path.join("interpreter-python");
19-
let activate_path = if cfg!(windows) {
20-
venv_path.join("Scripts").join("Activate.ps1")
21-
} else {
22-
venv_path.join("bin/activate")
23-
};
24-
let cached_requirements_path = venv_path
25-
.join("requirements.txt")
26-
.into_os_string()
27-
.into_string()
28-
.unwrap();
29-
/* println!(
30-
"RUN PATHS activate={:?} cached_reqs={:?}",
31-
activate_path, cached_requirements_path
32-
); */
33-
34-
if !venv_path.exists() {
35-
println!("Creating virtual environment...");
36-
let python = if cfg!(target_os = "macos") {
37-
"python3.12"
38-
} else {
39-
"python3"
40-
};
41-
cmd!(python, "-mvenv", &venv_path).run()?;
42-
}
43-
44-
let requirements_path = app_handle
45-
.path()
46-
.resolve("interpreter/requirements.txt", BaseDirectory::Resource)?
47-
.into_os_string()
48-
.into_string()
49-
.unwrap();
50-
51-
if !diff(
52-
requirements_path.as_str(),
53-
cached_requirements_path.as_str(),
54-
) {
55-
cmd!(
56-
venv_path
57-
.join(if cfg!(windows) { "Scripts" } else { "bin" })
58-
.join("pip"),
59-
"install",
60-
"-r",
61-
&requirements_path,
62-
)
63-
.run()?;
64-
65-
copy(requirements_path, cached_requirements_path)?;
66-
}
67-
68-
match activate_path.parent() {
69-
Some(parent) => Ok(parent.to_path_buf()),
70-
_ => Err(tauri::Error::UnknownPath),
71-
}
72-
}
6+
use crate::interpreter::pip::pip_install_if_needed;
7+
use crate::interpreter::pull::pull_if_needed;
738

749
#[cfg(desktop)]
7510
pub fn run_pdl_program(
@@ -84,7 +19,7 @@ pub fn run_pdl_program(
8419
Path::new(&source_file_path).file_name().unwrap()
8520
);
8621

87-
let pull_future = load::pull_if_needed(&source_file_path);
22+
let pull_future = pull_if_needed(&source_file_path);
8823
let bin_path_future = pip_install_if_needed(app_handle);
8924

9025
let trace_arg = if let Some(arg) = trace_file {
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
pub mod load;
1+
pub mod pip;
2+
pub mod pull;
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
use ::std::fs::{copy, create_dir_all};
2+
use ::std::path::PathBuf;
3+
4+
use duct::cmd;
5+
use file_diff::diff;
6+
use tauri::path::BaseDirectory;
7+
use tauri::Manager;
8+
9+
#[cfg(desktop)]
10+
pub async fn pip_install_if_needed(app_handle: tauri::AppHandle) -> Result<PathBuf, tauri::Error> {
11+
let cache_path = app_handle.path().cache_dir()?.join("pdl");
12+
13+
create_dir_all(&cache_path)?;
14+
let venv_path = cache_path.join("interpreter-python");
15+
let activate_path = if cfg!(windows) {
16+
venv_path.join("Scripts").join("Activate.ps1")
17+
} else {
18+
venv_path.join("bin/activate")
19+
};
20+
let cached_requirements_path = venv_path
21+
.join("requirements.txt")
22+
.into_os_string()
23+
.into_string()
24+
.unwrap();
25+
/* println!(
26+
"RUN PATHS activate={:?} cached_reqs={:?}",
27+
activate_path, cached_requirements_path
28+
); */
29+
30+
if !venv_path.exists() {
31+
println!("Creating virtual environment...");
32+
let python = if cfg!(target_os = "macos") {
33+
"python3.12"
34+
} else {
35+
"python3"
36+
};
37+
cmd!(python, "-mvenv", &venv_path).run()?;
38+
}
39+
40+
let requirements_path = app_handle
41+
.path()
42+
.resolve("interpreter/requirements.txt", BaseDirectory::Resource)?
43+
.into_os_string()
44+
.into_string()
45+
.unwrap();
46+
47+
if !diff(
48+
requirements_path.as_str(),
49+
cached_requirements_path.as_str(),
50+
) {
51+
cmd!(
52+
venv_path
53+
.join(if cfg!(windows) { "Scripts" } else { "bin" })
54+
.join("pip"),
55+
"install",
56+
"-r",
57+
&requirements_path,
58+
)
59+
.run()?;
60+
61+
copy(requirements_path, cached_requirements_path)?;
62+
}
63+
64+
match activate_path.parent() {
65+
Some(parent) => Ok(parent.to_path_buf()),
66+
_ => Err(tauri::Error::UnknownPath),
67+
}
68+
}

pdl-live-react/src-tauri/src/interpreter/load.rs renamed to pdl-live-react/src-tauri/src/interpreter/pull.rs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ pub async fn pull_if_needed(path: &String) -> Result<(), LoadError> {
6161
models
6262
.into_par_iter()
6363
.try_for_each(|model| match model {
64-
m if model.starts_with("ollama/") => ollama_pull(&m[7..]),
65-
m if model.starts_with("ollama_chat/") => ollama_pull(&m[12..]),
64+
m if model.starts_with("ollama/") => ollama_pull_if_needed(&m[7..]),
65+
m if model.starts_with("ollama_chat/") => ollama_pull_if_needed(&m[12..]),
6666
_ => {
6767
eprintln!("Skipping model pull for {}", model);
6868
Ok(())
@@ -73,8 +73,21 @@ pub async fn pull_if_needed(path: &String) -> Result<(), LoadError> {
7373
Ok(())
7474
}
7575

76+
fn ollama_exists(model: &str) -> bool {
77+
match cmd!("ollama", "show", model)
78+
.stdout_null()
79+
.stderr_null()
80+
.run()
81+
{
82+
Ok(_output) => true,
83+
_ => false,
84+
}
85+
}
86+
7687
/// The Ollama implementation of a single model pull
77-
fn ollama_pull(model: &str) -> Result<(), LoadError> {
78-
cmd!("ollama", "pull", model).run().map_err(LoadError::IO)?;
88+
fn ollama_pull_if_needed(model: &str) -> Result<(), LoadError> {
89+
if !ollama_exists(model) {
90+
cmd!("ollama", "pull", model).run().map_err(LoadError::IO)?;
91+
}
7992
Ok(())
8093
}

0 commit comments

Comments
 (0)