Skip to content

Commit 9925d85

Browse files
committed
feat: pull models in rust
Signed-off-by: Nick Mitchell <[email protected]>
1 parent 6cedb09 commit 9925d85

File tree

9 files changed

+155
-1
lines changed

9 files changed

+155
-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: 46 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: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ 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"
3233

3334
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
3435
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+
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: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
use serde::{Deserialize, Serialize};
2+
3+
#[derive(Serialize, Deserialize)]
4+
enum PdlBlock {
5+
LiteLlmModelBLock,
6+
TextBlock,
7+
}
8+
9+
#[derive(Serialize, Deserialize)]
10+
struct TextBlock {
11+
description: Option<str>,
12+
defs?: Defs10
13+
def?: Def9
14+
contribute?: Contribute9
15+
parser?: Parser9
16+
fallback?: Fallback9
17+
role?: Role9
18+
context?: Context9
19+
pdl__id?: PdlId9
20+
pdl__result?: unknown
21+
pdl__location?: PdlLocationType | null
22+
pdl__timing?: PdlTiming | null
23+
pdl__is_leaf?: PdlIsLeaf9
24+
kind?: Kind9
25+
text: Text
26+
27+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
use duct::cmd;
2+
use rayon::prelude::*;
3+
use serde_json::{Error, Map, Result, Value};
4+
5+
fn from_path(path: &String) -> Result<Map<String, Value>> {
6+
let content = std::fs::read_to_string(path).unwrap();
7+
let map: Map<String, Value> = serde_json::from_str(&content).unwrap();
8+
9+
Ok(map)
10+
}
11+
12+
fn extract_models(program: Map<String, Value>) -> Result<Vec<String>> {
13+
let mut map: Vec<String> = Vec::new();
14+
for (key, val) in program {
15+
match key.as_str() {
16+
"model" => match &val {
17+
Value::String(m) => {
18+
map.push(m.to_string());
19+
}
20+
_ => {}
21+
},
22+
_ => {}
23+
}
24+
25+
match val {
26+
Value::Array(a) => {
27+
for v in a {
28+
match v {
29+
Value::Object(h) => {
30+
for m in extract_models(h).unwrap() {
31+
map.push(m)
32+
}
33+
}
34+
_ => {}
35+
}
36+
}
37+
}
38+
Value::Object(h) => {
39+
for m in extract_models(h).unwrap() {
40+
map.push(m)
41+
}
42+
}
43+
_ => {}
44+
}
45+
}
46+
47+
Ok(map)
48+
}
49+
50+
pub fn pull_if_needed(path: &String) -> Result<()> {
51+
extract_models(from_path(path)?)?
52+
.into_par_iter()
53+
.try_for_each(|model: String| -> Result<()> {
54+
match model {
55+
m if model.starts_with("ollama/") => ollama_pull(&m[7..]),
56+
m if model.starts_with("ollama_chat/") => ollama_pull(&m[12..]),
57+
_ => {
58+
eprintln!("Skipping model pull for {}", model);
59+
Ok(())
60+
}
61+
}
62+
})
63+
.expect("successfully pulled models");
64+
65+
Ok(())
66+
}
67+
68+
fn ollama_pull(model: &str) -> Result<()> {
69+
cmd!("ollama", "pull", model).run().map_err(Error::io)?;
70+
Ok(())
71+
}
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)