@1kbirds/chidori 0.1.16 → 0.1.20
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 +2 -0
- package/README.md +7 -0
- package/package.json +2 -2
- package/package_python/test_chidori.py +2 -0
- package/src/translations/nodejs.rs +0 -15
- package/src/translations/python.rs +8 -7
- package/src/translations/rust.rs +473 -142
- package/package_python/__pycache__/__init__.cpython-310.pyc +0 -0
- package/package_python/__pycache__/test_chidori.cpython-310-pytest-7.4.0.pyc +0 -0
- package/package_python/__pycache__/test_promptgraph.cpython-310-pytest-7.4.0.pyc +0 -0
package/Cargo.toml
CHANGED
package/README.md
ADDED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@1kbirds/chidori",
|
|
3
|
-
"version": "v0.1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "v0.1.20",
|
|
4
|
+
"description": "Chidori is a library for building and running reactive AI agents.",
|
|
5
5
|
"main": "package_node/index.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"build": "cargo-cp-artifact -nc ./package_node/native/chidori.node -- cargo build --message-format=json-render-diagnostics --features nodejs",
|
|
@@ -788,20 +788,6 @@ impl Chidori {
|
|
|
788
788
|
// // TODO: nodes that are added should return a clean definition of what their addition looks like
|
|
789
789
|
// // TODO: adding a node should also display any errors
|
|
790
790
|
|
|
791
|
-
fn obj_interface(mut cx: FunctionContext) -> JsResult<JsValue> {
|
|
792
|
-
let arg0 = cx.argument::<JsValue>(0)?;
|
|
793
|
-
let arg0_value: ExecutionStatus = match neon_serde3::from_value(&mut cx, arg0) {
|
|
794
|
-
Ok(value) => value,
|
|
795
|
-
Err(e) => {
|
|
796
|
-
return cx.throw_error(e.to_string());
|
|
797
|
-
}
|
|
798
|
-
};
|
|
799
|
-
println!("{:?}", &arg0_value);
|
|
800
|
-
|
|
801
|
-
neon_serde3::to_value(&mut cx, &arg0_value)
|
|
802
|
-
.or_else(|e| cx.throw_error(e.to_string()))
|
|
803
|
-
}
|
|
804
|
-
|
|
805
791
|
|
|
806
792
|
fn prompt_node(mut cx: FunctionContext) -> JsResult<JsPromise> {
|
|
807
793
|
let channel = cx.channel();
|
|
@@ -1227,7 +1213,6 @@ fn main(mut cx: ModuleContext) -> NeonResult<()> {
|
|
|
1227
1213
|
cx.export_function("chidoriBranch", Chidori::branch)?;
|
|
1228
1214
|
cx.export_function("chidoriQuery", Chidori::query)?;
|
|
1229
1215
|
cx.export_function("chidoriGraphStructure", Chidori::display_graph_structure)?;
|
|
1230
|
-
cx.export_function("chidoriObjInterface", Chidori::obj_interface)?;
|
|
1231
1216
|
cx.export_function("chidoriCustomNode", Chidori::custom_node)?;
|
|
1232
1217
|
cx.export_function("chidoriDenoCodeNode", Chidori::deno_code_node)?;
|
|
1233
1218
|
cx.export_function("chidoriVectorMemoryNode", Chidori::vector_memory_node)?;
|
|
@@ -22,12 +22,6 @@ use ::prompt_graph_core::graph_definition::{create_prompt_node, create_op_map, c
|
|
|
22
22
|
use ::prompt_graph_core::utils::wasm_error::CoreError;
|
|
23
23
|
use ::prompt_graph_core::build_runtime_graph::graph_parse::{CleanedDefinitionGraph, CleanIndividualNode, construct_query_from_output_type, derive_for_individual_node};
|
|
24
24
|
|
|
25
|
-
// https://pyo3.rs/v0.19.0/
|
|
26
|
-
|
|
27
|
-
// https://chat.openai.com/c/4dfe5b29-0cd9-493f-be8f-9362d376e764
|
|
28
|
-
|
|
29
|
-
// TODO: create worker object
|
|
30
|
-
|
|
31
25
|
#[derive(Debug)]
|
|
32
26
|
pub struct CoreErrorWrapper(CoreError);
|
|
33
27
|
|
|
@@ -43,6 +37,13 @@ impl std::convert::From<CoreError> for PyErrWrapper {
|
|
|
43
37
|
}
|
|
44
38
|
}
|
|
45
39
|
|
|
40
|
+
impl std::convert::From<anyhow::Error> for PyErrWrapper {
|
|
41
|
+
fn from(err: anyhow::Error) -> PyErrWrapper {
|
|
42
|
+
PyErrWrapper(exceptions::PyOSError::new_err(err.to_string()))
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
|
|
46
47
|
#[derive(Debug)]
|
|
47
48
|
pub struct PyErrWrapper(pyo3::PyErr);
|
|
48
49
|
|
|
@@ -869,7 +870,7 @@ impl Chidori {
|
|
|
869
870
|
})
|
|
870
871
|
}
|
|
871
872
|
|
|
872
|
-
#[pyo3(signature = (name=String::new(), queries=vec![None], output_tables=vec![], output=String::from("type O { }"), code=String::new(), is_template=false))]
|
|
873
|
+
#[pyo3(signature = (name=String::new(), queries=vec![None], output_tables=vec![], output=String::from("type O { output: String }"), code=String::new(), is_template=false))]
|
|
873
874
|
fn deno_code_node<'a>(
|
|
874
875
|
mut self_: PyRefMut<'_, Self>,
|
|
875
876
|
py: Python<'a>,
|
package/src/translations/rust.rs
CHANGED
|
@@ -1,177 +1,508 @@
|
|
|
1
|
+
use std::cell::RefCell;
|
|
2
|
+
use std::collections::{HashMap, VecDeque};
|
|
3
|
+
use std::hash::Hash;
|
|
4
|
+
use std::marker::PhantomData;
|
|
5
|
+
use anyhow::Error;
|
|
6
|
+
use futures::StreamExt;
|
|
7
|
+
use log::{debug, info};
|
|
8
|
+
use once_cell::sync::OnceCell;
|
|
9
|
+
use tokio::runtime::Runtime;
|
|
10
|
+
use prompt_graph_core::build_runtime_graph::graph_parse::{CleanedDefinitionGraph, CleanIndividualNode, construct_query_from_output_type, derive_for_individual_node};
|
|
11
|
+
use prompt_graph_core::graph_definition::{create_code_node, create_custom_node, create_prompt_node, create_vector_memory_node, SourceNodeType};
|
|
12
|
+
use prompt_graph_core::proto2::{ChangeValue, ChangeValueWithCounter, Empty, ExecutionStatus, File, FileAddressedChangeValueWithCounter, FilteredPollNodeWillExecuteEventsRequest, Item, ListBranchesRes, Path, Query, QueryAtFrame, QueryAtFrameResponse, RequestAckNodeWillExecuteEvent, RequestAtFrame, RequestFileMerge, RequestListBranches, RequestNewBranch, RequestOnlyId, RespondPollNodeWillExecuteEvents, SerializedValue, SerializedValueArray, SerializedValueObject};
|
|
13
|
+
use prompt_graph_core::proto2::execution_runtime_client::ExecutionRuntimeClient;
|
|
14
|
+
use prompt_graph_core::proto2::serialized_value::Val;
|
|
15
|
+
use prompt_graph_exec::tonic_runtime::run_server;
|
|
16
|
+
use neon_serde3;
|
|
17
|
+
use serde::{Deserialize, Serialize};
|
|
18
|
+
use tonic::Status;
|
|
1
19
|
|
|
2
|
-
|
|
20
|
+
async fn get_client(url: String) -> Result<ExecutionRuntimeClient<tonic::transport::Channel>, tonic::transport::Error> {
|
|
21
|
+
ExecutionRuntimeClient::connect(url.clone()).await
|
|
22
|
+
}
|
|
3
23
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
24
|
+
struct Chidori {
|
|
25
|
+
file_id: String,
|
|
26
|
+
current_head: u64,
|
|
27
|
+
current_branch: u64,
|
|
28
|
+
url: String
|
|
29
|
+
}
|
|
8
30
|
|
|
31
|
+
impl Chidori {
|
|
9
32
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
33
|
+
fn new(file_id: String, url: String) -> Self {
|
|
34
|
+
if !url.contains("://") {
|
|
35
|
+
panic!("Invalid url, must include protocol");
|
|
36
|
+
}
|
|
37
|
+
// let api_token = cx.argument_opt(2)?.value(&mut cx);
|
|
38
|
+
debug!("Creating new Chidori instance with file_id={}, url={}, api_token={:?}", file_id, url, "".to_string());
|
|
39
|
+
Chidori {
|
|
40
|
+
file_id,
|
|
41
|
+
current_head: 0,
|
|
42
|
+
current_branch: 0,
|
|
43
|
+
url,
|
|
44
|
+
}
|
|
45
|
+
}
|
|
13
46
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
47
|
+
async fn start_server(&self, file_path: Option<String>) -> anyhow::Result<()> {
|
|
48
|
+
let url_server = self.url.clone();
|
|
49
|
+
std::thread::spawn(move || {
|
|
50
|
+
let result = run_server(url_server, file_path);
|
|
51
|
+
match result {
|
|
52
|
+
Ok(_) => {
|
|
53
|
+
println!("Server exited");
|
|
54
|
+
},
|
|
55
|
+
Err(e) => {
|
|
56
|
+
println!("Error running server: {}", e);
|
|
57
|
+
},
|
|
58
|
+
}
|
|
59
|
+
});
|
|
17
60
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
61
|
+
let url = self.url.clone();
|
|
62
|
+
loop {
|
|
63
|
+
match get_client(url.clone()).await {
|
|
64
|
+
Ok(connection) => {
|
|
65
|
+
eprintln!("Connection successfully established {:?}", &url);
|
|
66
|
+
return Ok(());
|
|
67
|
+
},
|
|
68
|
+
Err(e) => {
|
|
69
|
+
eprintln!("Error connecting to server: {} with Error {}. Retrying...", &url, &e.to_string());
|
|
70
|
+
std::thread::sleep(std::time::Duration::from_millis(1000));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async fn play(&self, branch: u64, frame: u64) -> anyhow::Result<ExecutionStatus> {
|
|
77
|
+
let file_id = self.file_id.clone();
|
|
78
|
+
let url = self.url.clone();
|
|
79
|
+
let mut client = get_client(url).await?;
|
|
80
|
+
let result = client.play(RequestAtFrame {
|
|
81
|
+
id: file_id,
|
|
82
|
+
frame,
|
|
83
|
+
branch,
|
|
84
|
+
}).await?;
|
|
85
|
+
Ok(result.into_inner())
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async fn pause(&self, frame: u64) -> anyhow::Result<ExecutionStatus> {
|
|
89
|
+
let file_id = self.file_id.clone();
|
|
90
|
+
let url = self.url.clone();
|
|
91
|
+
let branch = self.current_branch.clone();
|
|
92
|
+
|
|
93
|
+
let mut client = get_client(url).await?;
|
|
94
|
+
let result = client.pause(RequestAtFrame {
|
|
95
|
+
id: file_id,
|
|
96
|
+
frame,
|
|
97
|
+
branch,
|
|
98
|
+
}).await?;
|
|
99
|
+
Ok(result.into_inner())
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
async fn query( &self, query: String, branch: u64, frame: u64, ) -> anyhow::Result<QueryAtFrameResponse> {
|
|
103
|
+
let file_id = self.file_id.clone();
|
|
104
|
+
let url = self.url.clone();
|
|
105
|
+
let mut client = get_client(url).await?;
|
|
106
|
+
let result = client.run_query(QueryAtFrame {
|
|
107
|
+
id: file_id,
|
|
108
|
+
query: Some(Query {
|
|
109
|
+
query: Some(query)
|
|
110
|
+
}),
|
|
111
|
+
frame,
|
|
112
|
+
branch,
|
|
113
|
+
}).await?;
|
|
114
|
+
Ok(result.into_inner())
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
async fn list_branches( &self) -> anyhow::Result<ListBranchesRes> {
|
|
118
|
+
let file_id = self.file_id.clone();
|
|
119
|
+
let url = self.url.clone();
|
|
120
|
+
let mut client = get_client(url).await?;
|
|
121
|
+
let result = client.list_branches(RequestListBranches {
|
|
122
|
+
id: file_id,
|
|
123
|
+
}).await?;
|
|
124
|
+
Ok(result.into_inner())
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
async fn display_graph_structure( &self, query: String, branch: u64, frame: u64, ) -> anyhow::Result<String> {
|
|
128
|
+
let file_id = self.file_id.clone();
|
|
129
|
+
let url = self.url.clone();
|
|
130
|
+
let mut client = get_client(url).await?;
|
|
131
|
+
let file = client.current_file_state(RequestOnlyId {
|
|
132
|
+
id: file_id,
|
|
133
|
+
branch
|
|
134
|
+
}).await?;
|
|
135
|
+
let mut file = file.into_inner();
|
|
136
|
+
let mut g = CleanedDefinitionGraph::zero();
|
|
137
|
+
g.merge_file(&mut file).unwrap();
|
|
138
|
+
Ok(g.get_dot_graph())
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
async fn list_registered_graphs(&self) -> anyhow::Result<()> {
|
|
142
|
+
let file_id = self.file_id.clone();
|
|
143
|
+
let url = self.url.clone();
|
|
144
|
+
let mut client = get_client(url).await?;
|
|
145
|
+
let resp = client.list_registered_graphs(Empty { }).await?;
|
|
146
|
+
let mut stream = resp.into_inner();
|
|
147
|
+
while let Some(x) = stream.next().await {
|
|
148
|
+
// callback.call(py, (x,), None);
|
|
149
|
+
info!("Registered Graph = {:?}", x);
|
|
150
|
+
};
|
|
151
|
+
Ok(())
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
//
|
|
155
|
+
// // TODO: need to figure out how to handle callbacks
|
|
156
|
+
// // fn list_input_proposals<'a>(
|
|
157
|
+
// // mut self_: PyRefMut<'_, Self>,
|
|
158
|
+
// // py: Python<'a>,
|
|
159
|
+
// // callback: PyObject
|
|
160
|
+
// // ) -> PyResult<&'a PyAny> {
|
|
161
|
+
// // let file_id = self_.file_id.clone();
|
|
162
|
+
// // let url = self_.url.clone();
|
|
163
|
+
// // let branch = self_.current_branch;
|
|
164
|
+
// // pyo3_asyncio::tokio::future_into_py(py, async move {
|
|
165
|
+
// // let mut client = get_client(url).await?;
|
|
166
|
+
// // let resp = client.list_input_proposals(RequestOnlyId {
|
|
167
|
+
// // id: file_id,
|
|
168
|
+
// // branch,
|
|
169
|
+
// // }).await.map_err(PyErrWrapper::from)?;
|
|
170
|
+
// // let mut stream = resp.into_inner();
|
|
171
|
+
// // while let Some(x) = stream.next().await {
|
|
172
|
+
// // // callback.call(py, (x,), None);
|
|
173
|
+
// // info!("InputProposals = {:?}", x);
|
|
174
|
+
// // };
|
|
175
|
+
// // Ok(())
|
|
176
|
+
// // })
|
|
177
|
+
// // }
|
|
178
|
+
//
|
|
179
|
+
// // fn respond_to_input_proposal(mut self_: PyRefMut<'_, Self>) -> PyResult<()> {
|
|
180
|
+
// // Ok(())
|
|
181
|
+
// // }
|
|
182
|
+
//
|
|
183
|
+
// // TODO: need to figure out how to handle callbacks
|
|
184
|
+
// // fn list_change_events<'a>(
|
|
185
|
+
// // mut self_: PyRefMut<'_, Self>,
|
|
186
|
+
// // py: Python<'a>,
|
|
187
|
+
// // callback: PyObject
|
|
188
|
+
// // ) -> PyResult<&'a PyAny> {
|
|
189
|
+
// // let file_id = self_.file_id.clone();
|
|
190
|
+
// // let url = self_.url.clone();
|
|
191
|
+
// // let branch = self_.current_branch;
|
|
192
|
+
// // pyo3_asyncio::tokio::future_into_py(py, async move {
|
|
193
|
+
// // let mut client = get_client(url).await?;
|
|
194
|
+
// // let resp = client.list_change_events(RequestOnlyId {
|
|
195
|
+
// // id: file_id,
|
|
196
|
+
// // branch,
|
|
197
|
+
// // }).await.map_err(PyErrWrapper::from)?;
|
|
198
|
+
// // let mut stream = resp.into_inner();
|
|
199
|
+
// // while let Some(x) = stream.next().await {
|
|
200
|
+
// // Python::with_gil(|py| pyo3_asyncio::tokio::into_future(callback.as_ref(py).call((x.map(ChangeValueWithCounterWrapper).map_err(PyErrWrapper::from)?,), None)?))?
|
|
201
|
+
// // .await?;
|
|
202
|
+
// // };
|
|
203
|
+
// // Ok(())
|
|
204
|
+
// // })
|
|
205
|
+
// // }
|
|
206
|
+
//
|
|
207
|
+
//
|
|
208
|
+
//
|
|
209
|
+
// // TODO: this should accept an "Object" instead of args
|
|
210
|
+
// // TODO: nodes that are added should return a clean definition of what their addition looks like
|
|
211
|
+
// // TODO: adding a node should also display any errors
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
async fn poll_local_code_node_execution(&self) -> anyhow::Result<RespondPollNodeWillExecuteEvents> {
|
|
215
|
+
let file_id = self.file_id.clone();
|
|
216
|
+
let url = self.url.clone();
|
|
217
|
+
let mut client = get_client(url).await?;
|
|
218
|
+
let req = FilteredPollNodeWillExecuteEventsRequest { id: file_id.clone() };
|
|
219
|
+
let result = client.poll_node_will_execute_events(req).await?;
|
|
220
|
+
Ok(result.into_inner())
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
async fn ack_local_code_node_execution(&self, branch: u64, counter : u64) -> anyhow::Result<ExecutionStatus> {
|
|
224
|
+
let file_id = self.file_id.clone();
|
|
225
|
+
let url = self.url.clone();
|
|
226
|
+
let mut client = get_client(url).await?;
|
|
227
|
+
let result = client.ack_node_will_execute_event(RequestAckNodeWillExecuteEvent {
|
|
228
|
+
id: file_id.clone(),
|
|
229
|
+
branch,
|
|
230
|
+
counter,
|
|
231
|
+
}).await?;
|
|
232
|
+
Ok(result.into_inner())
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
async fn respond_local_code_node_execution(&self, branch: u64, counter: u64, node_name: String, response: Vec<ChangeValue>) -> anyhow::Result<ExecutionStatus> {
|
|
236
|
+
let file_id = self.file_id.clone();
|
|
237
|
+
let url = self.url.clone();
|
|
238
|
+
|
|
239
|
+
// TODO: need parent counters from the original change
|
|
240
|
+
// TODO: need source node
|
|
241
|
+
let mut client = get_client(url).await?;
|
|
242
|
+
|
|
243
|
+
// TODO: need to add the output table paths to these
|
|
244
|
+
// TODO: this needs to look more like a real change
|
|
245
|
+
Ok(client.push_worker_event(FileAddressedChangeValueWithCounter {
|
|
246
|
+
branch,
|
|
247
|
+
counter,
|
|
248
|
+
node_name,
|
|
249
|
+
id: file_id.clone(),
|
|
250
|
+
change: Some(ChangeValueWithCounter {
|
|
251
|
+
filled_values: response,
|
|
252
|
+
parent_monotonic_counters: vec![],
|
|
253
|
+
monotonic_counter: counter,
|
|
254
|
+
branch,
|
|
255
|
+
source_node: "".to_string(),
|
|
256
|
+
})
|
|
257
|
+
}).await?.into_inner())
|
|
258
|
+
}
|
|
23
259
|
}
|
|
24
260
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
($name:expr, $output_def:expr) => {
|
|
34
|
-
create_node_parameter(
|
|
35
|
-
String::from($name),
|
|
36
|
-
String::from($output_def)
|
|
37
|
-
)
|
|
38
|
-
};
|
|
261
|
+
|
|
262
|
+
#[derive(serde::Serialize, serde::Deserialize)]
|
|
263
|
+
struct PromptNodeCreateOpts {
|
|
264
|
+
name: String,
|
|
265
|
+
queries: Option<Vec<String>>,
|
|
266
|
+
output_tables: Option<Vec<String>>,
|
|
267
|
+
template: String,
|
|
268
|
+
model: Option<String>
|
|
39
269
|
}
|
|
40
270
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
};
|
|
50
|
-
($name:expr, $query_def:expr, $path:expr) => {
|
|
51
|
-
create_code_node(
|
|
52
|
-
String::from($name),
|
|
53
|
-
String::from($query_def),
|
|
54
|
-
String::from($path),
|
|
55
|
-
)
|
|
56
|
-
};
|
|
271
|
+
|
|
272
|
+
#[derive(serde::Serialize, serde::Deserialize)]
|
|
273
|
+
struct CustomNodeCreateOpts {
|
|
274
|
+
name: String,
|
|
275
|
+
queries: Option<Vec<String>>,
|
|
276
|
+
output_tables: Option<Vec<String>>,
|
|
277
|
+
output: Option<String>,
|
|
278
|
+
node_type_name: String
|
|
57
279
|
}
|
|
58
280
|
|
|
281
|
+
#[derive(serde::Serialize, serde::Deserialize)]
|
|
282
|
+
struct DenoCodeNodeCreateOpts {
|
|
283
|
+
name: String,
|
|
284
|
+
queries: Option<Vec<String>>,
|
|
285
|
+
output_tables: Option<Vec<String>>,
|
|
286
|
+
output: Option<String>,
|
|
287
|
+
code: String,
|
|
288
|
+
is_template: Option<bool>
|
|
289
|
+
}
|
|
59
290
|
|
|
60
|
-
#[
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
create_code_node(
|
|
72
|
-
String::from($name),
|
|
73
|
-
String::from($query_def),
|
|
74
|
-
String::from($output_def),
|
|
75
|
-
String::from($source_type),
|
|
76
|
-
)
|
|
77
|
-
};
|
|
291
|
+
#[derive(serde::Serialize, serde::Deserialize)]
|
|
292
|
+
struct VectorMemoryNodeCreateOpts {
|
|
293
|
+
name: String,
|
|
294
|
+
queries: Option<Vec<String>>,
|
|
295
|
+
output_tables: Option<Vec<String>>,
|
|
296
|
+
output: Option<String>,
|
|
297
|
+
template: Option<String>, // TODO: default is the contents of the query
|
|
298
|
+
action: Option<String>, // TODO: default WRITE
|
|
299
|
+
embedding_model: Option<String>, // TODO: default TEXT_EMBEDDING_ADA_002
|
|
300
|
+
db_vendor: Option<String>, // TODO: default QDRANT
|
|
301
|
+
collection_name: String,
|
|
78
302
|
}
|
|
79
303
|
|
|
80
304
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
String::from($name),
|
|
93
|
-
String::from($query_def),
|
|
94
|
-
String::from($output_def),
|
|
95
|
-
)
|
|
305
|
+
fn remap_queries(queries: Option<Vec<String>>) -> Vec<Option<String>> {
|
|
306
|
+
let queries: Vec<Option<String>> = if let Some(queries) = queries {
|
|
307
|
+
queries.into_iter().map(|q| {
|
|
308
|
+
if q == "None".to_string() {
|
|
309
|
+
None
|
|
310
|
+
} else {
|
|
311
|
+
Some(q)
|
|
312
|
+
}
|
|
313
|
+
}).collect()
|
|
314
|
+
} else {
|
|
315
|
+
vec![]
|
|
96
316
|
};
|
|
317
|
+
queries
|
|
97
318
|
}
|
|
98
319
|
|
|
320
|
+
struct GraphBuilder {
|
|
321
|
+
clean_graph: CleanedDefinitionGraph,
|
|
322
|
+
}
|
|
99
323
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
)
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
324
|
+
impl GraphBuilder {
|
|
325
|
+
fn prompt_node(&mut self, arg: PromptNodeCreateOpts) -> anyhow::Result<NodeHandle> {
|
|
326
|
+
let node = create_prompt_node(
|
|
327
|
+
arg.name,
|
|
328
|
+
remap_queries(arg.queries),
|
|
329
|
+
arg.template,
|
|
330
|
+
arg.model.unwrap_or("GPT_3_5_TURBO".to_string()),
|
|
331
|
+
arg.output_tables.unwrap_or(vec![]))?;
|
|
332
|
+
self.clean_graph.merge_file(&File { nodes: vec![node.clone()], ..Default::default() })?;
|
|
333
|
+
Ok(NodeHandle::from(node)?)
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
fn custom_node(&mut self, arg: CustomNodeCreateOpts) -> anyhow::Result<NodeHandle> {
|
|
337
|
+
let node = create_custom_node(
|
|
338
|
+
arg.name,
|
|
339
|
+
remap_queries(arg.queries.clone()),
|
|
340
|
+
arg.output.unwrap_or("type O {}".to_string()),
|
|
341
|
+
arg.node_type_name,
|
|
342
|
+
arg.output_tables.unwrap_or(vec![])
|
|
343
|
+
);
|
|
344
|
+
self.clean_graph.merge_file(&File { nodes: vec![node.clone()], ..Default::default() })?;
|
|
345
|
+
Ok(NodeHandle::from(node)?)
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
fn deno_code_node(&mut self, arg: DenoCodeNodeCreateOpts) -> anyhow::Result<NodeHandle> {
|
|
350
|
+
let node = create_code_node(
|
|
351
|
+
arg.name,
|
|
352
|
+
remap_queries(arg.queries.clone()),
|
|
353
|
+
arg.output.unwrap_or("type O {}".to_string()),
|
|
354
|
+
SourceNodeType::Code("DENO".to_string(), arg.code, arg.is_template.unwrap_or(false)),
|
|
355
|
+
arg.output_tables.unwrap_or(vec![])
|
|
356
|
+
);
|
|
357
|
+
self.clean_graph.merge_file(&File { nodes: vec![node.clone()], ..Default::default() })?;
|
|
358
|
+
Ok(NodeHandle::from(node)?)
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
fn vector_memory_node(&mut self, arg: VectorMemoryNodeCreateOpts) -> anyhow::Result<NodeHandle> {
|
|
363
|
+
let node = create_vector_memory_node(
|
|
364
|
+
arg.name,
|
|
365
|
+
remap_queries(arg.queries.clone()),
|
|
366
|
+
arg.output.unwrap_or("type O {}".to_string()),
|
|
367
|
+
arg.action.unwrap_or("READ".to_string()),
|
|
368
|
+
arg.embedding_model.unwrap_or("TEXT_EMBEDDING_ADA_002".to_string()),
|
|
369
|
+
arg.template.unwrap_or("".to_string()),
|
|
370
|
+
arg.db_vendor.unwrap_or("QDRANT".to_string()),
|
|
371
|
+
arg.collection_name,
|
|
372
|
+
arg.output_tables.unwrap_or(vec![])
|
|
373
|
+
)?;
|
|
374
|
+
self.clean_graph.merge_file(&File { nodes: vec![node.clone()], ..Default::default() })?;
|
|
375
|
+
Ok(NodeHandle::from(node)?)
|
|
376
|
+
}
|
|
377
|
+
//
|
|
378
|
+
//
|
|
379
|
+
// //
|
|
380
|
+
// // fn observation_node(mut self_: PyRefMut<'_, Self>, name: String, query_def: Option<String>, template: String, model: String) -> PyResult<()> {
|
|
381
|
+
// // let file_id = self_.file_id.clone();
|
|
382
|
+
// // let node = create_observation_node(
|
|
383
|
+
// // "".to_string(),
|
|
384
|
+
// // None,
|
|
385
|
+
// // "".to_string(),
|
|
386
|
+
// // );
|
|
387
|
+
// // executor::block_on(self_.client.merge(RequestFileMerge {
|
|
388
|
+
// // id: file_id,
|
|
389
|
+
// // file: Some(File {
|
|
390
|
+
// // nodes: vec![node],
|
|
391
|
+
// // ..Default::default()
|
|
392
|
+
// // }),
|
|
393
|
+
// // branch: 0,
|
|
394
|
+
// // }));
|
|
395
|
+
// // Ok(())
|
|
396
|
+
// // }
|
|
397
|
+
|
|
398
|
+
// // TODO: need to figure out passing a buffer of bytes
|
|
399
|
+
// // TODO: nodes that are added should return a clean definition of what their addition looks like
|
|
400
|
+
// // TODO: adding a node should also display any errors
|
|
401
|
+
// /// x = None
|
|
402
|
+
// /// with open("/Users/coltonpierson/Downloads/files_and_dirs.zip", "rb") as zip_file:
|
|
403
|
+
// /// contents = zip_file.read()
|
|
404
|
+
// /// x = await p.load_zip_file("LoadZip", """ output: String """, contents)
|
|
405
|
+
// /// x
|
|
406
|
+
// // #[pyo3(signature = (name=String::new(), output_tables=vec![], output=String::new(), bytes=vec![]))]
|
|
407
|
+
// // fn load_zip_file<'a>(
|
|
408
|
+
// // mut self_: PyRefMut<'_, Self>,
|
|
409
|
+
// // py: Python<'a>,
|
|
410
|
+
// // name: String,
|
|
411
|
+
// // output_tables: Vec<String>,
|
|
412
|
+
// // output: String,
|
|
413
|
+
// // bytes: Vec<u8>
|
|
414
|
+
// // ) -> PyResult<&'a PyAny> {
|
|
415
|
+
// // let file_id = self_.file_id.clone();
|
|
416
|
+
// // let url = self_.url.clone();
|
|
417
|
+
// // pyo3_asyncio::tokio::future_into_py(py, async move {
|
|
418
|
+
// // let node = create_loader_node(
|
|
419
|
+
// // name,
|
|
420
|
+
// // vec![],
|
|
421
|
+
// // output,
|
|
422
|
+
// // LoadFrom::ZipfileBytes(bytes),
|
|
423
|
+
// // output_tables
|
|
424
|
+
// // );
|
|
425
|
+
// // Ok(push_file_merge(&url, &file_id, node).await?)
|
|
426
|
+
// // })
|
|
427
|
+
// // }
|
|
428
|
+
|
|
429
|
+
async fn commit(&self, file_id: String, url: String, branch: u64) -> anyhow::Result<ExecutionStatus> {
|
|
430
|
+
let mut client = get_client(url.clone()).await?;
|
|
431
|
+
let nodes = self.clean_graph.node_by_name.clone().into_values().collect();
|
|
432
|
+
Ok(client.merge(RequestFileMerge {
|
|
433
|
+
id: file_id.clone(),
|
|
434
|
+
file: Some(File { nodes, ..Default::default() }),
|
|
435
|
+
branch: 0,
|
|
436
|
+
}).await.map(|x| x.into_inner())?)
|
|
437
|
+
}
|
|
120
438
|
}
|
|
121
439
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
String::from($output_def),
|
|
129
|
-
)
|
|
130
|
-
};
|
|
131
|
-
($name:expr, $query_def:expr, $output_def:expr) => {
|
|
132
|
-
create_component_node(
|
|
133
|
-
String::from($name),
|
|
134
|
-
String::from($query_def),
|
|
135
|
-
String::from($output_def),
|
|
136
|
-
)
|
|
137
|
-
};
|
|
440
|
+
|
|
441
|
+
// Node handle
|
|
442
|
+
#[derive(Clone)]
|
|
443
|
+
pub struct NodeHandle {
|
|
444
|
+
node: Item,
|
|
445
|
+
indiv: CleanIndividualNode
|
|
138
446
|
}
|
|
139
447
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
)
|
|
149
|
-
};
|
|
150
|
-
($name:expr, $query_def:expr, $template:expr, $model:expr) => {
|
|
151
|
-
create_prompt_node(
|
|
152
|
-
String::from($name),
|
|
153
|
-
String::from($query_def),
|
|
154
|
-
String::from($template),
|
|
155
|
-
String::from($model),
|
|
156
|
-
)
|
|
157
|
-
};
|
|
448
|
+
impl NodeHandle {
|
|
449
|
+
fn from(node: Item) -> anyhow::Result<NodeHandle> {
|
|
450
|
+
let indiv = derive_for_individual_node(&node)?;
|
|
451
|
+
Ok(NodeHandle {
|
|
452
|
+
node,
|
|
453
|
+
indiv
|
|
454
|
+
})
|
|
455
|
+
}
|
|
158
456
|
}
|
|
159
457
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
458
|
+
|
|
459
|
+
impl NodeHandle {
|
|
460
|
+
fn get_name(&self) -> String {
|
|
461
|
+
self.node.core.as_ref().unwrap().name.clone()
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
pub fn run_when(&mut self, other_node: &NodeHandle) -> anyhow::Result<bool> {
|
|
465
|
+
let queries = &mut self.node.core.as_mut().unwrap().queries;
|
|
466
|
+
let q = construct_query_from_output_type(
|
|
467
|
+
&other_node.get_name(),
|
|
468
|
+
&other_node.get_name(),
|
|
469
|
+
&self.indiv.output_path
|
|
470
|
+
).unwrap();
|
|
471
|
+
queries.push(Query { query: Some(q)});
|
|
472
|
+
Ok(true)
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
|
|
476
|
+
pub async fn query(&self, file_id: String, url: String, branch: u64, frame: u64) -> anyhow::Result<HashMap<String, SerializedValue>> {
|
|
477
|
+
let name = &self.node.core.as_ref().unwrap().name;
|
|
478
|
+
let query = construct_query_from_output_type(&name, &name, &self.indiv.output_path).unwrap();
|
|
479
|
+
let mut client = get_client(url).await?;
|
|
480
|
+
let result = client.run_query(QueryAtFrame {
|
|
481
|
+
id: file_id,
|
|
482
|
+
query: Some(Query {
|
|
483
|
+
query: Some(query)
|
|
484
|
+
}),
|
|
485
|
+
frame,
|
|
486
|
+
branch,
|
|
487
|
+
}).await?;
|
|
488
|
+
let res = result.into_inner();
|
|
489
|
+
let mut obj = HashMap::new();
|
|
490
|
+
for value in res.values.iter() {
|
|
491
|
+
let c = value.change_value.as_ref().unwrap();
|
|
492
|
+
let k = c.path.as_ref().unwrap().address.join(":");
|
|
493
|
+
let v = c.value.as_ref().unwrap().clone();
|
|
494
|
+
obj.insert(k, v).unwrap();
|
|
495
|
+
}
|
|
496
|
+
Ok(obj)
|
|
497
|
+
}
|
|
498
|
+
|
|
167
499
|
}
|
|
168
500
|
|
|
169
501
|
#[cfg(test)]
|
|
170
502
|
mod tests {
|
|
171
|
-
use super
|
|
503
|
+
use super::*;
|
|
172
504
|
|
|
173
505
|
#[test]
|
|
174
506
|
fn test_new_graph() {
|
|
175
|
-
new_graph();
|
|
176
507
|
}
|
|
177
508
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|