Skip to content

Commit e50fff9

Browse files
authored
feat: pull models in rust (#743)
Signed-off-by: Nick Mitchell <[email protected]>
1 parent d4bc012 commit e50fff9

File tree

7 files changed

+176
-1
lines changed

7 files changed

+176
-1
lines changed

.github/workflows/tauri-cli.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,11 @@ jobs:
2525
with:
2626
node-version: 22
2727
- name: Install dependencies
28+
# sleep 2 to wait for ollama to be running... hack warning
2829
run: |
2930
npm ci & sudo apt update && \
3031
sudo apt install -y libgtk-3-dev libwebkit2gtk-4.1-dev librsvg2-dev patchelf at-spi2-core && \
31-
(curl -fsSL https://ollama.com/install.sh | sudo -E sh && sleep 2 && ollama pull granite3.2:2b)
32+
(curl -fsSL https://ollama.com/install.sh | sudo -E sh && sleep 2)
3233
wait
3334
- name: Test production build
3435
run: npm run tauri build -- --bundles deb # Skip testing appimage, is this dangerous? It's slow...

pdl-live-react/src-tauri/Cargo.lock

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

pdl-live-react/src-tauri/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ urlencoding = "2.1.3"
2929
tempfile = "3.16.0"
3030
file_diff = "1.0.0"
3131
duct = "0.13.7"
32+
rayon = "1.10.0"
33+
yaml-rust2 = "0.10.0"
3234

3335
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
3436
tauri-plugin-cli = "2"

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ use duct::cmd;
66
use tauri::path::BaseDirectory;
77
use tauri::Manager;
88

9+
use crate::interpreter::load;
10+
911
#[cfg(desktop)]
1012
fn pip_install_if_needed(app_handle: tauri::AppHandle) -> Result<PathBuf, tauri::Error> {
1113
let cache_path = app_handle.path().cache_dir()?.join("pdl");
@@ -79,6 +81,9 @@ pub fn run_pdl_program(
7981
"Running {:#?}",
8082
Path::new(&source_file_path).file_name().unwrap()
8183
);
84+
85+
let _ = load::pull_if_needed(&source_file_path);
86+
8287
let bin_path = pip_install_if_needed(app_handle)?;
8388
let trace_arg = if let Some(arg) = trace_file {
8489
if let serde_json::Value::String(f) = &arg.value {
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
use duct::cmd;
2+
use rayon::prelude::*;
3+
use yaml_rust2::yaml::LoadError;
4+
use yaml_rust2::{ScanError, Yaml, YamlLoader};
5+
6+
/// Read the given filesystem path and produce a potentially multi-document Yaml
7+
fn from_path(path: &String) -> Result<Vec<Yaml>, ScanError> {
8+
let content = std::fs::read_to_string(path).unwrap();
9+
YamlLoader::load_from_str(&content)
10+
}
11+
12+
/// Take one Yaml fragment and produce the a vector of the models that are used
13+
fn extract_models(program: Yaml) -> Vec<String> {
14+
let mut models: Vec<String> = Vec::new();
15+
16+
match program {
17+
Yaml::Hash(h) => {
18+
for (key, val) in h {
19+
match key.as_str() {
20+
Some("model") => match &val {
21+
Yaml::String(m) => {
22+
models.push(m.to_string());
23+
}
24+
_ => {}
25+
},
26+
_ => {}
27+
}
28+
29+
for m in extract_models(val) {
30+
models.push(m)
31+
}
32+
}
33+
}
34+
35+
Yaml::Array(a) => {
36+
for val in a {
37+
for m in extract_models(val) {
38+
models.push(m)
39+
}
40+
}
41+
}
42+
43+
_ => {}
44+
}
45+
46+
models
47+
}
48+
49+
/// Pull models (in parallel) from the PDL program in the given filepath.
50+
pub fn pull_if_needed(path: &String) -> Result<(), LoadError> {
51+
from_path(path)
52+
.unwrap()
53+
.into_iter()
54+
.flat_map(extract_models)
55+
.collect::<Vec<String>>()
56+
.into_par_iter()
57+
.try_for_each(|model| match model {
58+
m if model.starts_with("ollama/") => ollama_pull(&m[7..]),
59+
m if model.starts_with("ollama_chat/") => ollama_pull(&m[12..]),
60+
_ => {
61+
eprintln!("Skipping model pull for {}", model);
62+
Ok(())
63+
}
64+
})
65+
.expect("successfully pulled models");
66+
67+
Ok(())
68+
}
69+
70+
/// The Ollama implementation of a single model pull
71+
fn ollama_pull(model: &str) -> Result<(), LoadError> {
72+
cmd!("ollama", "pull", model).run().map_err(LoadError::IO)?;
73+
Ok(())
74+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub mod load;

pdl-live-react/src-tauri/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use tauri_plugin_pty;
44
mod cli;
55
mod commands;
66
mod gui;
7+
mod interpreter;
78

89
#[cfg_attr(mobile, tauri::mobile_entry_point)]
910
pub fn run() {

0 commit comments

Comments
 (0)