@1kbirds/chidori 0.1.20 → 0.1.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cargo.toml +0 -1
- package/package.json +2 -2
- package/package_node/index.js +57 -23
- package/package_python/chidori.pyi +11 -9
- package/package_python/test_chidori.py +6 -5
- package/src/lib.rs +3 -2
- package/src/translations/mod.rs +2 -1
- package/src/translations/nodejs.rs +286 -771
- package/src/translations/python.rs +261 -306
- package/src/translations/rust.rs +310 -81
- package/src/translations/shared.rs +49 -0
- package/tests/nodejs/chidori.test.js +13 -26
- package/tests/nodejs/nodeHandle.test.js +6 -8
|
@@ -5,9 +5,10 @@ use tonic::{Response, Status};
|
|
|
5
5
|
use futures::executor;
|
|
6
6
|
use futures::StreamExt;
|
|
7
7
|
use pyo3::types::{PyDict, PyList, PyString};
|
|
8
|
-
use pyo3::types::{PyBool, PyFloat, PyInt};
|
|
9
8
|
use pyo3::prelude::*;
|
|
10
9
|
use std::collections::HashMap;
|
|
10
|
+
use std::sync::{Arc};
|
|
11
|
+
use tokio::sync::Mutex;
|
|
11
12
|
use std::time::Duration;
|
|
12
13
|
use tokio::runtime::Runtime;
|
|
13
14
|
use log::{debug, info};
|
|
@@ -21,6 +22,8 @@ use ::prompt_graph_core::proto2::serialized_value::Val;
|
|
|
21
22
|
use ::prompt_graph_core::graph_definition::{create_prompt_node, create_op_map, create_code_node, create_component_node, create_vector_memory_node, create_observation_node, create_node_parameter, SourceNodeType, create_loader_node, create_custom_node};
|
|
22
23
|
use ::prompt_graph_core::utils::wasm_error::CoreError;
|
|
23
24
|
use ::prompt_graph_core::build_runtime_graph::graph_parse::{CleanedDefinitionGraph, CleanIndividualNode, construct_query_from_output_type, derive_for_individual_node};
|
|
25
|
+
use crate::register_node_handle;
|
|
26
|
+
use crate::translations::rust::{Chidori, CustomNodeCreateOpts, DenoCodeNodeCreateOpts, GraphBuilder, Handler, NodeHandle, PromptNodeCreateOpts, VectorMemoryNodeCreateOpts};
|
|
24
27
|
|
|
25
28
|
#[derive(Debug)]
|
|
26
29
|
pub struct CoreErrorWrapper(CoreError);
|
|
@@ -84,12 +87,27 @@ impl Into<pyo3::PyResult<()>> for PyErrWrapper {
|
|
|
84
87
|
}
|
|
85
88
|
}
|
|
86
89
|
|
|
87
|
-
|
|
90
|
+
|
|
91
|
+
pub struct PyExecutionStatus(ExecutionStatus);
|
|
88
92
|
|
|
89
93
|
|
|
90
94
|
impl IntoPy<Py<PyAny>> for PyExecutionStatus {
|
|
91
95
|
fn into_py(self, py: Python) -> Py<PyAny> {
|
|
92
|
-
let
|
|
96
|
+
let exec_status = self.0;
|
|
97
|
+
let dict = PyDict::new(py);
|
|
98
|
+
dict.set_item("id", exec_status.id).unwrap();
|
|
99
|
+
dict.set_item("monotonic_counter", exec_status.monotonic_counter).unwrap();
|
|
100
|
+
dict.set_item("branch", exec_status.branch).unwrap();
|
|
101
|
+
dict.into_py(py)
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
pub struct PyResponseExecutionStatus(Response<ExecutionStatus>);
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
impl IntoPy<Py<PyAny>> for PyResponseExecutionStatus {
|
|
109
|
+
fn into_py(self, py: Python) -> Py<PyAny> {
|
|
110
|
+
let PyResponseExecutionStatus(resp) = self;
|
|
93
111
|
let exec_status = resp.into_inner();
|
|
94
112
|
let dict = PyDict::new(py);
|
|
95
113
|
dict.set_item("id", exec_status.id).unwrap();
|
|
@@ -223,6 +241,7 @@ fn pyany_to_serialized_value(p: &PyAny) -> SerializedValue {
|
|
|
223
241
|
"float" => {
|
|
224
242
|
let val = p.extract::<f32>().unwrap();
|
|
225
243
|
SerializedValue {
|
|
244
|
+
// file: Some(File {
|
|
226
245
|
val: Some(Val::Float(val)),
|
|
227
246
|
}
|
|
228
247
|
}
|
|
@@ -267,6 +286,36 @@ fn pyany_to_serialized_value(p: &PyAny) -> SerializedValue {
|
|
|
267
286
|
}
|
|
268
287
|
|
|
269
288
|
|
|
289
|
+
use pyo3::prelude::*;
|
|
290
|
+
use pyo3::types::IntoPyDict;
|
|
291
|
+
use serde_json::json;
|
|
292
|
+
|
|
293
|
+
fn py_to_json<'p>(py: Python<'p>, v: &PyAny) -> serde_json::Value {
|
|
294
|
+
if v.is_none() {
|
|
295
|
+
json!(null)
|
|
296
|
+
} else if let Ok(b) = v.extract::<bool>() {
|
|
297
|
+
json!(b)
|
|
298
|
+
} else if let Ok(i) = v.extract::<i64>() {
|
|
299
|
+
json!(i)
|
|
300
|
+
} else if let Ok(f) = v.extract::<f64>() {
|
|
301
|
+
json!(f)
|
|
302
|
+
} else if let Ok(dict) = v.extract::<HashMap<String, Py<PyAny>>>() {
|
|
303
|
+
let mut m = serde_json::map::Map::new();
|
|
304
|
+
for (key, value) in dict {
|
|
305
|
+
m.insert(key, py_to_json(py, value.as_ref(py)));
|
|
306
|
+
}
|
|
307
|
+
json!(m)
|
|
308
|
+
} else if let Ok(list) = v.extract::<Vec<Py<PyAny>>>() {
|
|
309
|
+
let v: Vec<serde_json::Value> = list.iter().map(|p| py_to_json(py, p.as_ref(py))).collect();
|
|
310
|
+
json!(v)
|
|
311
|
+
} else if let Ok(s) = v.extract::<String>() {
|
|
312
|
+
json!(s)
|
|
313
|
+
} else {
|
|
314
|
+
json!(null)
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
|
|
270
319
|
|
|
271
320
|
fn dict_to_paths<'p>(
|
|
272
321
|
py: Python<'p>,
|
|
@@ -353,142 +402,80 @@ async fn get_client(url: String) -> Result<ExecutionRuntimeClient<tonic::transpo
|
|
|
353
402
|
// TODO: return a handle to nodes so that we can understand and inspect them
|
|
354
403
|
// TODO: include a __repr__ method on those nodes
|
|
355
404
|
|
|
356
|
-
|
|
357
|
-
// TODO: add an api for wiring together a system ot nodes
|
|
358
|
-
// TODO: require the description of the complete system, in order to avoid mutably handling changing edges
|
|
359
|
-
// TODO: system description must be fully encapsulated in a single object and applied all at once
|
|
360
|
-
|
|
361
405
|
#[pyclass]
|
|
362
406
|
#[derive(Clone)]
|
|
363
|
-
struct
|
|
364
|
-
|
|
365
|
-
file_id: String,
|
|
366
|
-
node: Item,
|
|
367
|
-
exec_status: ExecutionStatus,
|
|
368
|
-
indiv: CleanIndividualNode
|
|
407
|
+
struct PyNodeHandle {
|
|
408
|
+
n: NodeHandle,
|
|
369
409
|
}
|
|
370
410
|
|
|
371
|
-
impl
|
|
372
|
-
fn from(
|
|
373
|
-
|
|
374
|
-
Ok(NodeHandle {
|
|
375
|
-
url,
|
|
376
|
-
file_id,
|
|
377
|
-
node,
|
|
378
|
-
exec_status,
|
|
379
|
-
indiv
|
|
380
|
-
})
|
|
411
|
+
impl PyNodeHandle {
|
|
412
|
+
fn from(node_handle: NodeHandle) -> anyhow::Result<PyNodeHandle> {
|
|
413
|
+
Ok(PyNodeHandle { n: node_handle })
|
|
381
414
|
}
|
|
382
415
|
}
|
|
383
416
|
|
|
384
417
|
#[pymethods]
|
|
385
|
-
impl
|
|
418
|
+
impl PyNodeHandle {
|
|
386
419
|
fn get_name(&self) -> String {
|
|
387
|
-
self.
|
|
420
|
+
self.n.get_name()
|
|
388
421
|
}
|
|
389
422
|
|
|
390
423
|
/// This updates the definition of this node to query for the target NodeHandle's output. Moving forward
|
|
391
424
|
/// it will execute whenever the target node resolves.
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
let
|
|
395
|
-
let url = self_.url.clone();
|
|
396
|
-
let mut node = self_.node.clone();
|
|
425
|
+
fn run_when<'a>(mut self_: PyRefMut<'_, Self>, py: Python<'a>, graph_builder: &mut PyGraphBuilder, other_node_handle: PyNodeHandle) -> PyResult<&'a PyAny> {
|
|
426
|
+
let mut n = self_.n.clone();
|
|
427
|
+
let g = Arc::clone(&graph_builder.g);
|
|
397
428
|
pyo3_asyncio::tokio::future_into_py(py, async move {
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
let q = construct_query_from_output_type(
|
|
402
|
-
&node_handle.get_name(),
|
|
403
|
-
&node_handle.get_name(),
|
|
404
|
-
&node_handle.indiv.output_path
|
|
405
|
-
).map_err(AnyhowErrWrapper)?;
|
|
406
|
-
queries.push(Query { query: Some(q)});
|
|
407
|
-
Ok(push_file_merge(&url, &file_id, node).await?)
|
|
408
|
-
} else {
|
|
409
|
-
Err(PyErr::new::<PyTypeError, _>("node_handle must be a NodeHandle"))
|
|
410
|
-
}
|
|
429
|
+
let mut graph_builder = g.lock().await;
|
|
430
|
+
Ok(n.run_when(&mut graph_builder, &other_node_handle.n)
|
|
431
|
+
.map_err(AnyhowErrWrapper)?)
|
|
411
432
|
})
|
|
412
433
|
}
|
|
413
434
|
|
|
414
|
-
#[pyo3(signature = (branch=0, frame=0))]
|
|
415
|
-
fn query<'a>(mut self_: PyRefMut<'_, Self>, py: Python<'a>, branch: u64, frame: u64) -> PyResult<&'a PyAny> {
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
.map_err(AnyhowErrWrapper)?;
|
|
422
|
-
|
|
423
|
-
// TODO: we need this to watch for changes to the query instead
|
|
424
|
-
// TODO: or this should await until either the target counter has elapsed or the query has resulted
|
|
425
|
-
|
|
426
|
-
pyo3_asyncio::tokio::future_into_py(py, async move {
|
|
427
|
-
let mut client = get_client(url).await?;
|
|
428
|
-
Ok(PyQueryAtFrameResponse(client.run_query(QueryAtFrame {
|
|
429
|
-
id: file_id,
|
|
430
|
-
query: Some(Query {
|
|
431
|
-
query: Some(query)
|
|
432
|
-
}),
|
|
433
|
-
frame,
|
|
434
|
-
branch,
|
|
435
|
-
}).await.map_err(PyErrWrapper::from)?))
|
|
436
|
-
})
|
|
437
|
-
}
|
|
435
|
+
// #[pyo3(signature = (branch=0, frame=0))]
|
|
436
|
+
// fn query<'a>(mut self_: PyRefMut<'_, Self>, py: Python<'a>, file_id: String, url: String, branch: u64, frame: u64) -> PyResult<&'a PyAny> {
|
|
437
|
+
// pyo3_asyncio::tokio::future_into_py(py, async move {
|
|
438
|
+
// Ok(PyQueryAtFrameResponse(self_.n.query(file_id, url, branch, frame)
|
|
439
|
+
// .await.map_err(PyErrWrapper::from)?))
|
|
440
|
+
// })
|
|
441
|
+
// }
|
|
438
442
|
|
|
439
443
|
fn __str__(&self) -> PyResult<String> {
|
|
440
444
|
// TODO: best practice is that these could be used to re-construct the same object
|
|
441
445
|
let name = self.get_name();
|
|
442
|
-
Ok(format!("NodeHandle(
|
|
446
|
+
Ok(format!("NodeHandle(node={})", name))
|
|
443
447
|
}
|
|
444
448
|
|
|
445
449
|
fn __repr__(&self) -> PyResult<String> {
|
|
446
450
|
let name = self.get_name();
|
|
447
|
-
Ok(format!("NodeHandle(
|
|
451
|
+
Ok(format!("NodeHandle(node={})", name))
|
|
448
452
|
}
|
|
449
453
|
}
|
|
450
454
|
|
|
451
455
|
|
|
452
456
|
// TODO: all operations only apply to a specific branch at a time
|
|
453
457
|
// TODO: maintain an internal map of the generated change responses for node additions to the associated query necessary to get that result
|
|
454
|
-
#[pyclass]
|
|
455
|
-
struct
|
|
458
|
+
#[pyclass(name="Chidori")]
|
|
459
|
+
struct PyChidori {
|
|
460
|
+
c: Arc<Mutex<Chidori>>,
|
|
456
461
|
file_id: String,
|
|
457
462
|
current_head: u64,
|
|
458
463
|
current_branch: u64,
|
|
459
464
|
url: String
|
|
460
465
|
}
|
|
461
466
|
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
async fn push_file_merge(url: &String, file_id: &String, node: Item) -> Result<NodeHandle, PyErr> {
|
|
465
|
-
let mut client = get_client(url.clone()).await?;
|
|
466
|
-
let exec_status = client.merge(RequestFileMerge {
|
|
467
|
-
id: file_id.clone(),
|
|
468
|
-
file: Some(File {
|
|
469
|
-
nodes: vec![node.clone()],
|
|
470
|
-
..Default::default()
|
|
471
|
-
}),
|
|
472
|
-
branch: 0,
|
|
473
|
-
}).await.map_err(PyErrWrapper::from)?.into_inner();
|
|
474
|
-
Ok(NodeHandle::from(
|
|
475
|
-
url.clone(),
|
|
476
|
-
file_id.clone(),
|
|
477
|
-
node,
|
|
478
|
-
exec_status
|
|
479
|
-
).map_err(AnyhowErrWrapper)?)
|
|
480
|
-
}
|
|
481
|
-
|
|
482
467
|
// TODO: internally all operations should have an assigned counter
|
|
483
468
|
// we can keep the actual target counter hidden from the host sdk
|
|
484
469
|
#[pymethods]
|
|
485
|
-
impl
|
|
470
|
+
impl PyChidori {
|
|
486
471
|
|
|
487
472
|
#[new]
|
|
488
473
|
#[pyo3(signature = (file_id=String::from("0"), url=String::from("http://127.0.0.1:9800"), api_token=None))]
|
|
489
474
|
fn new(file_id: String, url: String, api_token: Option<String>) -> Self {
|
|
490
475
|
debug!("Creating new Chidori instance with file_id={}, url={}, api_token={:?}", file_id, url, api_token);
|
|
491
|
-
Chidori
|
|
476
|
+
let c = Chidori::new(file_id.clone(), url.clone());
|
|
477
|
+
PyChidori {
|
|
478
|
+
c: Arc::new(Mutex::new(c)),
|
|
492
479
|
file_id,
|
|
493
480
|
current_head: 0,
|
|
494
481
|
current_branch: 0,
|
|
@@ -497,32 +484,11 @@ impl Chidori {
|
|
|
497
484
|
}
|
|
498
485
|
|
|
499
486
|
fn start_server<'a>(mut self_: PyRefMut<'_, Self>, py: Python<'a>, file_path: Option<String>) -> PyResult<&'a PyAny> {
|
|
500
|
-
let
|
|
501
|
-
std::thread::spawn(move || {
|
|
502
|
-
let result = run_server(url_server, file_path);
|
|
503
|
-
match result {
|
|
504
|
-
Ok(_) => { },
|
|
505
|
-
Err(e) => {
|
|
506
|
-
println!("Error running server: {}", e);
|
|
507
|
-
},
|
|
508
|
-
}
|
|
509
|
-
});
|
|
510
|
-
|
|
487
|
+
let c = Arc::clone(&self_.c);
|
|
511
488
|
let url = self_.url.clone();
|
|
512
489
|
pyo3_asyncio::tokio::future_into_py(py, async move {
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
match client.await {
|
|
516
|
-
Ok(connection) => {
|
|
517
|
-
eprintln!("Connection successfully established {:?}", &url);
|
|
518
|
-
break 'retry
|
|
519
|
-
},
|
|
520
|
-
Err(e) => {
|
|
521
|
-
eprintln!("Error connecting to server: {} with Error {}. Retrying...", &url, &e.0);
|
|
522
|
-
std::thread::sleep(std::time::Duration::from_millis(1000));
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
}
|
|
490
|
+
let c = c.lock().await;
|
|
491
|
+
c.start_server(file_path).await.map_err(AnyhowErrWrapper)?;
|
|
526
492
|
Ok(())
|
|
527
493
|
})
|
|
528
494
|
}
|
|
@@ -533,7 +499,7 @@ impl Chidori {
|
|
|
533
499
|
let url = self_.url.clone();
|
|
534
500
|
pyo3_asyncio::tokio::future_into_py(py, async move {
|
|
535
501
|
let mut client = get_client(url).await?;
|
|
536
|
-
Ok(
|
|
502
|
+
Ok(PyResponseExecutionStatus(client.play(RequestAtFrame {
|
|
537
503
|
id: file_id,
|
|
538
504
|
frame,
|
|
539
505
|
branch,
|
|
@@ -549,7 +515,7 @@ impl Chidori {
|
|
|
549
515
|
let branch = self_.current_branch.clone();
|
|
550
516
|
pyo3_asyncio::tokio::future_into_py(py, async move {
|
|
551
517
|
let mut client = get_client(url).await?;
|
|
552
|
-
Ok(
|
|
518
|
+
Ok(PyResponseExecutionStatus(client.pause(RequestAtFrame {
|
|
553
519
|
id: file_id,
|
|
554
520
|
frame,
|
|
555
521
|
branch,
|
|
@@ -570,7 +536,7 @@ impl Chidori {
|
|
|
570
536
|
diverges_at_counter: 0,
|
|
571
537
|
}).await.map_err(PyErrWrapper::from)?;
|
|
572
538
|
// TODO: need to somehow handle writing to the current_branch
|
|
573
|
-
Ok(
|
|
539
|
+
Ok(PyResponseExecutionStatus(result_branch))
|
|
574
540
|
})
|
|
575
541
|
}
|
|
576
542
|
|
|
@@ -696,213 +662,147 @@ impl Chidori {
|
|
|
696
662
|
})
|
|
697
663
|
}
|
|
698
664
|
|
|
699
|
-
|
|
700
|
-
// TODO: nodes that are added should return a clean definition of what their addition looks like
|
|
701
|
-
// TODO: adding a node should also display any errors
|
|
702
|
-
/// x = None
|
|
703
|
-
/// with open("/Users/coltonpierson/Downloads/files_and_dirs.zip", "rb") as zip_file:
|
|
704
|
-
/// contents = zip_file.read()
|
|
705
|
-
/// x = await p.load_zip_file("LoadZip", """ output: String """, contents)
|
|
706
|
-
/// x
|
|
707
|
-
#[pyo3(signature = (name=String::new(), output_tables=vec![], output=String::new(), bytes=vec![]))]
|
|
708
|
-
fn load_zip_file<'a>(
|
|
709
|
-
mut self_: PyRefMut<'_, Self>,
|
|
710
|
-
py: Python<'a>,
|
|
711
|
-
name: String,
|
|
712
|
-
output_tables: Vec<String>,
|
|
713
|
-
output: String,
|
|
714
|
-
bytes: Vec<u8>
|
|
715
|
-
) -> PyResult<&'a PyAny> {
|
|
716
|
-
let file_id = self_.file_id.clone();
|
|
717
|
-
let url = self_.url.clone();
|
|
718
|
-
pyo3_asyncio::tokio::future_into_py(py, async move {
|
|
719
|
-
let node = create_loader_node(
|
|
720
|
-
name,
|
|
721
|
-
vec![],
|
|
722
|
-
output,
|
|
723
|
-
LoadFrom::ZipfileBytes(bytes),
|
|
724
|
-
output_tables
|
|
725
|
-
);
|
|
726
|
-
Ok(push_file_merge(&url, &file_id, node).await?)
|
|
727
|
-
})
|
|
728
|
-
}
|
|
729
|
-
|
|
730
|
-
// TODO: nodes that are added should return a clean definition of what their addition looks like
|
|
731
|
-
// TODO: adding a node should also display any errors
|
|
732
|
-
#[pyo3(signature = (name=String::new(), queries=vec![None], output_tables=vec![], template=String::new(), model=String::from("GPT_3_5_TURBO")))]
|
|
733
|
-
fn prompt_node<'a>(
|
|
665
|
+
pub fn register_custom_node_handle<'a>(
|
|
734
666
|
mut self_: PyRefMut<'_, Self>,
|
|
735
667
|
py: Python<'a>,
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
output_tables: Vec<String>,
|
|
739
|
-
template: String,
|
|
740
|
-
model: String
|
|
668
|
+
key: String,
|
|
669
|
+
handler: PyObject
|
|
741
670
|
) -> PyResult<&'a PyAny> {
|
|
742
|
-
let
|
|
743
|
-
let
|
|
671
|
+
let c = Arc::clone(&self_.c);
|
|
672
|
+
let handler = Arc::new(handler);
|
|
744
673
|
pyo3_asyncio::tokio::future_into_py(py, async move {
|
|
745
|
-
let
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
}).await.map_err(PyErrWrapper::from)?;
|
|
768
|
-
debug!("poll_local_code_node_execution result = {:?}", result);
|
|
769
|
-
Ok(PyRespondPollNodeWillExecuteEvents(result))
|
|
674
|
+
let mut c = c.lock().await;
|
|
675
|
+
c.register_custom_node_handle(key, Handler::new(
|
|
676
|
+
move |n| {
|
|
677
|
+
let handler_clone = Arc::clone(&handler);
|
|
678
|
+
Box::pin(async move {
|
|
679
|
+
let result = Python::with_gil(|py| {
|
|
680
|
+
let fut = handler_clone.as_ref().call(py, (NodeWillExecuteOnBranchWrapper(n).to_object(py), ), None)?;
|
|
681
|
+
pyo3_asyncio::tokio::into_future(fut.as_ref(py))
|
|
682
|
+
})?.await;
|
|
683
|
+
match result {
|
|
684
|
+
Ok(py_obj) => {
|
|
685
|
+
Python::with_gil(|py| {
|
|
686
|
+
let json_value = py_to_json(py, py_obj.as_ref(py));
|
|
687
|
+
Ok(json_value)
|
|
688
|
+
})
|
|
689
|
+
},
|
|
690
|
+
Err(err) => Err(anyhow::Error::new(err)),
|
|
691
|
+
}
|
|
692
|
+
})
|
|
693
|
+
}
|
|
694
|
+
));
|
|
695
|
+
Ok(())
|
|
770
696
|
})
|
|
771
697
|
}
|
|
772
698
|
|
|
773
|
-
|
|
774
|
-
fn ack_local_code_node_execution<'a>(
|
|
699
|
+
fn run_custom_node_loop<'a>(
|
|
775
700
|
mut self_: PyRefMut<'_, Self>,
|
|
776
701
|
py: Python<'a>,
|
|
777
|
-
branch: u64,
|
|
778
|
-
counter: u64,
|
|
779
702
|
) -> PyResult<&'a PyAny> {
|
|
780
|
-
let
|
|
781
|
-
let url = self_.url.clone();
|
|
703
|
+
let c = Arc::clone(&self_.c);
|
|
782
704
|
pyo3_asyncio::tokio::future_into_py(py, async move {
|
|
783
|
-
let mut
|
|
784
|
-
Ok(
|
|
785
|
-
id: file_id.clone(),
|
|
786
|
-
branch,
|
|
787
|
-
counter,
|
|
788
|
-
}).await.map_err(PyErrWrapper::from)?))
|
|
705
|
+
let mut c = c.lock().await;
|
|
706
|
+
Ok(c.run_custom_node_loop().await.map_err(AnyhowErrWrapper)?)
|
|
789
707
|
})
|
|
790
708
|
}
|
|
791
709
|
|
|
792
|
-
#[pyo3(signature = (branch=0, counter=0, node_name=String::new(), response=None))]
|
|
793
|
-
fn respond_local_code_node_execution<'a>(
|
|
794
|
-
mut self_: PyRefMut<'_, Self>,
|
|
795
|
-
py: Python<'a>,
|
|
796
|
-
branch: u64,
|
|
797
|
-
counter: u64,
|
|
798
|
-
node_name: String,
|
|
799
|
-
response: Option<PyObject>
|
|
800
|
-
) -> PyResult<&'a PyAny> {
|
|
801
|
-
|
|
802
|
-
let file_id = self_.file_id.clone();
|
|
803
|
-
let url = self_.url.clone();
|
|
804
|
-
|
|
805
|
-
// TODO: need parent counters from the original change
|
|
806
|
-
// TODO: need source node
|
|
807
710
|
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
711
|
+
//
|
|
712
|
+
// fn observation_node(mut self_: PyRefMut<'_, Self>, name: String, query_def: Option<String>, template: String, model: String) -> PyResult<()> {
|
|
713
|
+
// let file_id = self_.file_id.clone();
|
|
714
|
+
// let node = create_observation_node(
|
|
715
|
+
// "".to_string(),
|
|
716
|
+
// None,
|
|
717
|
+
// "".to_string(),
|
|
718
|
+
// );
|
|
719
|
+
// executor::block_on(self_.client.merge(RequestFileMerge {
|
|
720
|
+
// id: file_id,
|
|
721
|
+
// file: Some(File {
|
|
722
|
+
// nodes: vec![node],
|
|
723
|
+
// ..Default::default()
|
|
724
|
+
// }),
|
|
725
|
+
// branch: 0,
|
|
726
|
+
// }));
|
|
727
|
+
// Ok(())
|
|
728
|
+
// }
|
|
729
|
+
}
|
|
813
730
|
|
|
814
|
-
|
|
815
|
-
|
|
731
|
+
#[pyclass(name="GraphBuilder")]
|
|
732
|
+
#[derive(Clone)]
|
|
733
|
+
struct PyGraphBuilder {
|
|
734
|
+
g: Arc<Mutex<GraphBuilder>>,
|
|
735
|
+
}
|
|
816
736
|
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
ChangeValue {
|
|
820
|
-
path: Some(Path {
|
|
821
|
-
address: path.0,
|
|
822
|
-
}),
|
|
823
|
-
value: Some(path.1),
|
|
824
|
-
branch,
|
|
825
|
-
}
|
|
826
|
-
});
|
|
737
|
+
#[pymethods]
|
|
738
|
+
impl PyGraphBuilder {
|
|
827
739
|
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
change: Some(ChangeValueWithCounter {
|
|
835
|
-
filled_values: filled_values.collect(),
|
|
836
|
-
parent_monotonic_counters: vec![],
|
|
837
|
-
monotonic_counter: counter,
|
|
838
|
-
branch,
|
|
839
|
-
source_node: "".to_string(),
|
|
840
|
-
})
|
|
841
|
-
}).await.map_err(PyErrWrapper::from)?))
|
|
842
|
-
})
|
|
740
|
+
#[new]
|
|
741
|
+
fn new() -> Self {
|
|
742
|
+
let g = GraphBuilder::new();
|
|
743
|
+
PyGraphBuilder {
|
|
744
|
+
g: Arc::new(Mutex::new(g)),
|
|
745
|
+
}
|
|
843
746
|
}
|
|
844
747
|
|
|
845
|
-
// TODO: handle dispatch to this handler - should accept a callback
|
|
846
748
|
// https://github.com/PyO3/pyo3/issues/525
|
|
847
|
-
#[pyo3(signature = (name=String::new(), queries=vec![None], output_tables=vec![], output=String::from("type O {}"), node_type_name=String::new()))]
|
|
749
|
+
#[pyo3(signature = (name=String::new(), queries=vec!["None".to_string()], output_tables=vec![], output=String::from("type O {}"), node_type_name=String::new()))]
|
|
848
750
|
fn custom_node<'a>(
|
|
849
751
|
mut self_: PyRefMut<'_, Self>,
|
|
850
752
|
py: Python<'a>,
|
|
851
753
|
name: String,
|
|
852
|
-
queries: Vec<
|
|
754
|
+
queries: Option<Vec<String>>,
|
|
853
755
|
output_tables: Vec<String>,
|
|
854
756
|
output: String,
|
|
855
757
|
node_type_name: String,
|
|
856
758
|
) -> PyResult<&'a PyAny> {
|
|
857
|
-
let
|
|
858
|
-
let url = self_.url.clone();
|
|
859
|
-
let branch = self_.current_branch;
|
|
759
|
+
let g = Arc::clone(&self_.g);
|
|
860
760
|
pyo3_asyncio::tokio::future_into_py(py, async move {
|
|
861
|
-
|
|
862
|
-
let
|
|
761
|
+
let mut graph_builder = g.lock().await;
|
|
762
|
+
let nh = graph_builder.custom_node(CustomNodeCreateOpts {
|
|
863
763
|
name,
|
|
864
764
|
queries,
|
|
865
|
-
|
|
765
|
+
output_tables: Some(output_tables),
|
|
766
|
+
output: Some(output),
|
|
866
767
|
node_type_name,
|
|
867
|
-
|
|
868
|
-
)
|
|
869
|
-
Ok(push_file_merge(&url, &file_id, node).await?)
|
|
768
|
+
}).map_err(AnyhowErrWrapper)?;
|
|
769
|
+
Ok(PyNodeHandle::from(nh).map_err(AnyhowErrWrapper)?)
|
|
870
770
|
})
|
|
871
771
|
}
|
|
872
772
|
|
|
873
|
-
#[pyo3(signature = (name=String::new(), queries=vec![None], output_tables=
|
|
773
|
+
#[pyo3(signature = (name=String::new(), queries=vec!["None".to_string()], output_tables=None, output=None, code=String::new(), is_template=None))]
|
|
874
774
|
fn deno_code_node<'a>(
|
|
875
775
|
mut self_: PyRefMut<'_, Self>,
|
|
876
776
|
py: Python<'a>,
|
|
877
777
|
name: String,
|
|
878
|
-
queries: Vec<
|
|
879
|
-
output_tables: Vec<String
|
|
880
|
-
output: String
|
|
778
|
+
queries: Option<Vec<String>>,
|
|
779
|
+
output_tables: Option<Vec<String>>,
|
|
780
|
+
output: Option<String>,
|
|
881
781
|
code: String,
|
|
882
|
-
is_template: bool
|
|
782
|
+
is_template: Option<bool>
|
|
883
783
|
) -> PyResult<&'a PyAny> {
|
|
884
|
-
let
|
|
885
|
-
let url = self_.url.clone();
|
|
886
|
-
let branch = self_.current_branch.clone();
|
|
784
|
+
let g = Arc::clone(&self_.g);
|
|
887
785
|
pyo3_asyncio::tokio::future_into_py(py, async move {
|
|
888
|
-
let
|
|
786
|
+
let mut graph_builder = g.lock().await;
|
|
787
|
+
let nh = graph_builder.deno_code_node(DenoCodeNodeCreateOpts {
|
|
889
788
|
name,
|
|
890
789
|
queries,
|
|
790
|
+
output_tables,
|
|
891
791
|
output,
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
)
|
|
895
|
-
Ok(
|
|
792
|
+
code,
|
|
793
|
+
is_template,
|
|
794
|
+
}).map_err(AnyhowErrWrapper)?;
|
|
795
|
+
Ok(PyNodeHandle::from(nh).map_err(AnyhowErrWrapper)?)
|
|
896
796
|
})
|
|
897
797
|
}
|
|
898
798
|
|
|
899
799
|
|
|
900
|
-
#[pyo3(signature = (name=String::new(), queries=vec![None], output_tables=vec![], output=String::from("type O { }"), template=String::new(), action="WRITE".to_string(), embedding_model="TEXT_EMBEDDING_ADA_002".to_string(), db_vendor="QDRANT".to_string(), collection_name=String::new()))]
|
|
800
|
+
#[pyo3(signature = (name=String::new(), queries=vec!["None".to_string()], output_tables=vec![], output=String::from("type O { }"), template=String::new(), action="WRITE".to_string(), embedding_model="TEXT_EMBEDDING_ADA_002".to_string(), db_vendor="QDRANT".to_string(), collection_name=String::new()))]
|
|
901
801
|
fn vector_memory_node<'a>(
|
|
902
802
|
mut self_: PyRefMut<'_, Self>,
|
|
903
803
|
py: Python<'a>,
|
|
904
804
|
name: String,
|
|
905
|
-
queries: Vec<
|
|
805
|
+
queries: Option<Vec<String>>,
|
|
906
806
|
output_tables: Vec<String>,
|
|
907
807
|
output: String,
|
|
908
808
|
template: String,
|
|
@@ -911,45 +811,98 @@ impl Chidori {
|
|
|
911
811
|
db_vendor: String,
|
|
912
812
|
collection_name: String,
|
|
913
813
|
) -> PyResult<&'a PyAny> {
|
|
914
|
-
let
|
|
915
|
-
let url = self_.url.clone();
|
|
916
|
-
let branch = self_.current_branch.clone();
|
|
917
|
-
|
|
814
|
+
let g = Arc::clone(&self_.g);
|
|
918
815
|
pyo3_asyncio::tokio::future_into_py(py, async move {
|
|
919
|
-
let
|
|
816
|
+
let mut graph_builder = g.lock().await;
|
|
817
|
+
let nh = graph_builder.vector_memory_node(VectorMemoryNodeCreateOpts {
|
|
920
818
|
name,
|
|
921
819
|
queries,
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
820
|
+
output_tables: Some(output_tables),
|
|
821
|
+
output: Some(output),
|
|
822
|
+
template: Some(template),
|
|
823
|
+
action: Some(action),
|
|
824
|
+
embedding_model: Some(embedding_model),
|
|
825
|
+
db_vendor: Some(db_vendor),
|
|
927
826
|
collection_name,
|
|
928
|
-
|
|
929
|
-
).map_err(
|
|
930
|
-
Ok(push_file_merge(&url, &file_id, node).await?)
|
|
827
|
+
}).map_err(AnyhowErrWrapper)?;
|
|
828
|
+
Ok(PyNodeHandle::from(nh).map_err(AnyhowErrWrapper)?)
|
|
931
829
|
})
|
|
932
830
|
}
|
|
933
831
|
|
|
934
832
|
|
|
935
|
-
//
|
|
936
|
-
//
|
|
833
|
+
// // TODO: nodes that are added should return a clean definition of what their addition looks like
|
|
834
|
+
// // TODO: adding a node should also display any errors
|
|
835
|
+
// /// x = None
|
|
836
|
+
// /// with open("/Users/coltonpierson/Downloads/files_and_dirs.zip", "rb") as zip_file:
|
|
837
|
+
// /// contents = zip_file.read()
|
|
838
|
+
// /// x = await p.load_zip_file("LoadZip", """ output: String """, contents)
|
|
839
|
+
// /// x
|
|
840
|
+
// #[pyo3(signature = (name=String::new(), output_tables=vec![], output=String::new(), bytes=vec![]))]
|
|
841
|
+
// fn load_zip_file<'a>(
|
|
842
|
+
// mut self_: PyRefMut<'_, Self>,
|
|
843
|
+
// py: Python<'a>,
|
|
844
|
+
// name: String,
|
|
845
|
+
// output_tables: Vec<String>,
|
|
846
|
+
// output: String,
|
|
847
|
+
// bytes: Vec<u8>
|
|
848
|
+
// ) -> PyResult<&'a PyAny> {
|
|
937
849
|
// let file_id = self_.file_id.clone();
|
|
938
|
-
// let
|
|
939
|
-
//
|
|
940
|
-
//
|
|
941
|
-
//
|
|
942
|
-
//
|
|
943
|
-
//
|
|
944
|
-
//
|
|
945
|
-
//
|
|
946
|
-
//
|
|
947
|
-
//
|
|
948
|
-
//
|
|
949
|
-
// branch: 0,
|
|
950
|
-
// }));
|
|
951
|
-
// Ok(())
|
|
850
|
+
// let url = self_.url.clone();
|
|
851
|
+
// pyo3_asyncio::tokio::future_into_py(py, async move {
|
|
852
|
+
// let node = create_loader_node(
|
|
853
|
+
// name,
|
|
854
|
+
// vec![],
|
|
855
|
+
// output,
|
|
856
|
+
// LoadFrom::ZipfileBytes(bytes),
|
|
857
|
+
// output_tables
|
|
858
|
+
// );
|
|
859
|
+
// Ok(push_file_merge(&url, &file_id, node).await?)
|
|
860
|
+
// })
|
|
952
861
|
// }
|
|
862
|
+
|
|
863
|
+
// TODO: nodes that are added should return a clean definition of what their addition looks like
|
|
864
|
+
// TODO: adding a node should also display any errors
|
|
865
|
+
#[pyo3(signature = (name=String::new(), queries=vec!["None".to_string()], output_tables=None, template=String::new(), model=None))]
|
|
866
|
+
fn prompt_node<'a>(
|
|
867
|
+
mut self_: PyRefMut<'_, Self>,
|
|
868
|
+
py: Python<'a>,
|
|
869
|
+
name: String,
|
|
870
|
+
queries: Option<Vec<String>>,
|
|
871
|
+
output_tables: Option<Vec<String>>,
|
|
872
|
+
template: String,
|
|
873
|
+
model: Option<String>
|
|
874
|
+
) -> PyResult<&'a PyAny> {
|
|
875
|
+
let g = Arc::clone(&self_.g);
|
|
876
|
+
pyo3_asyncio::tokio::future_into_py(py, async move {
|
|
877
|
+
let mut graph_builder = g.lock().await;
|
|
878
|
+
let nh = graph_builder.prompt_node(PromptNodeCreateOpts {
|
|
879
|
+
name,
|
|
880
|
+
queries,
|
|
881
|
+
output_tables,
|
|
882
|
+
template,
|
|
883
|
+
model,
|
|
884
|
+
}).map_err(AnyhowErrWrapper)?;
|
|
885
|
+
Ok(PyNodeHandle::from(nh).map_err(AnyhowErrWrapper)?)
|
|
886
|
+
})
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
fn commit<'a>(
|
|
890
|
+
mut self_: PyRefMut<'_, Self>,
|
|
891
|
+
py: Python<'a>,
|
|
892
|
+
c: PyRef<'_, PyChidori>,
|
|
893
|
+
branch: u64
|
|
894
|
+
) -> PyResult<&'a PyAny> {
|
|
895
|
+
let g = Arc::clone(&self_.g);
|
|
896
|
+
let c = Arc::clone(&c.c);
|
|
897
|
+
pyo3_asyncio::tokio::future_into_py(py, async move {
|
|
898
|
+
let mut graph_builder = g.lock().await;
|
|
899
|
+
let mut chidori = c.lock().await;
|
|
900
|
+
let exec_status = graph_builder.commit(&chidori, branch).await
|
|
901
|
+
.map(PyExecutionStatus)
|
|
902
|
+
.map_err(AnyhowErrWrapper)?;
|
|
903
|
+
Ok(exec_status)
|
|
904
|
+
})
|
|
905
|
+
}
|
|
953
906
|
}
|
|
954
907
|
|
|
955
908
|
|
|
@@ -959,7 +912,9 @@ impl Chidori {
|
|
|
959
912
|
#[pymodule]
|
|
960
913
|
#[pyo3(name = "chidori")]
|
|
961
914
|
fn chidori(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
|
|
962
|
-
pyo3_log::init();
|
|
963
|
-
m.add_class::<
|
|
915
|
+
// pyo3_log::init();
|
|
916
|
+
m.add_class::<PyChidori>()?;
|
|
917
|
+
m.add_class::<PyGraphBuilder>()?;
|
|
964
918
|
Ok(())
|
|
965
|
-
}
|
|
919
|
+
}
|
|
920
|
+
|