@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
package/src/translations/rust.rs
CHANGED
|
@@ -1,36 +1,63 @@
|
|
|
1
1
|
use std::cell::RefCell;
|
|
2
2
|
use std::collections::{HashMap, VecDeque};
|
|
3
|
+
use std::future::Future;
|
|
3
4
|
use std::hash::Hash;
|
|
4
5
|
use std::marker::PhantomData;
|
|
6
|
+
use std::pin::Pin;
|
|
7
|
+
use std::sync::Arc;
|
|
5
8
|
use anyhow::Error;
|
|
9
|
+
use futures::future::BoxFuture;
|
|
6
10
|
use futures::StreamExt;
|
|
7
11
|
use log::{debug, info};
|
|
8
12
|
use once_cell::sync::OnceCell;
|
|
9
13
|
use tokio::runtime::Runtime;
|
|
10
14
|
use prompt_graph_core::build_runtime_graph::graph_parse::{CleanedDefinitionGraph, CleanIndividualNode, construct_query_from_output_type, derive_for_individual_node};
|
|
11
15
|
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};
|
|
16
|
+
use prompt_graph_core::proto2::{ChangeValue, ChangeValueWithCounter, Empty, ExecutionStatus, File, FileAddressedChangeValueWithCounter, FilteredPollNodeWillExecuteEventsRequest, Item, ListBranchesRes, NodeWillExecute, NodeWillExecuteOnBranch, Path, Query, QueryAtFrame, QueryAtFrameResponse, RequestAckNodeWillExecuteEvent, RequestAtFrame, RequestFileMerge, RequestListBranches, RequestNewBranch, RequestOnlyId, RespondPollNodeWillExecuteEvents, SerializedValue, SerializedValueArray, SerializedValueObject};
|
|
13
17
|
use prompt_graph_core::proto2::execution_runtime_client::ExecutionRuntimeClient;
|
|
14
18
|
use prompt_graph_core::proto2::serialized_value::Val;
|
|
15
19
|
use prompt_graph_exec::tonic_runtime::run_server;
|
|
16
20
|
use neon_serde3;
|
|
17
21
|
use serde::{Deserialize, Serialize};
|
|
18
22
|
use tonic::Status;
|
|
23
|
+
use prompt_graph_core::templates::json_value_to_serialized_value;
|
|
24
|
+
use crate::translations::shared::json_value_to_paths;
|
|
25
|
+
pub use prompt_graph_core::utils::serialized_value_to_string;
|
|
19
26
|
|
|
20
27
|
async fn get_client(url: String) -> Result<ExecutionRuntimeClient<tonic::transport::Channel>, tonic::transport::Error> {
|
|
21
28
|
ExecutionRuntimeClient::connect(url.clone()).await
|
|
22
29
|
}
|
|
23
30
|
|
|
24
|
-
|
|
31
|
+
type CallbackHandler = Box<dyn Fn(NodeWillExecuteOnBranch) -> BoxFuture<'static, anyhow::Result<serde_json::Value>> + Send + Sync>;
|
|
32
|
+
|
|
33
|
+
pub struct Handler {
|
|
34
|
+
pub(crate) callback: CallbackHandler
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
impl Handler {
|
|
38
|
+
pub fn new<F>(f: F) -> Self
|
|
39
|
+
where
|
|
40
|
+
F: Fn(NodeWillExecuteOnBranch) -> BoxFuture<'static, anyhow::Result<serde_json::Value>> + Send + Sync + 'static
|
|
41
|
+
{
|
|
42
|
+
Handler {
|
|
43
|
+
callback: Box::new(f),
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
#[derive(Clone)]
|
|
50
|
+
pub struct Chidori {
|
|
25
51
|
file_id: String,
|
|
26
52
|
current_head: u64,
|
|
27
53
|
current_branch: u64,
|
|
28
|
-
url: String
|
|
54
|
+
url: String,
|
|
55
|
+
pub(crate) custom_node_handlers: HashMap<String, Arc<Handler>>
|
|
29
56
|
}
|
|
30
57
|
|
|
31
58
|
impl Chidori {
|
|
32
59
|
|
|
33
|
-
fn new(file_id: String, url: String) -> Self {
|
|
60
|
+
pub fn new(file_id: String, url: String) -> Self {
|
|
34
61
|
if !url.contains("://") {
|
|
35
62
|
panic!("Invalid url, must include protocol");
|
|
36
63
|
}
|
|
@@ -41,10 +68,11 @@ impl Chidori {
|
|
|
41
68
|
current_head: 0,
|
|
42
69
|
current_branch: 0,
|
|
43
70
|
url,
|
|
71
|
+
custom_node_handlers: HashMap::new(),
|
|
44
72
|
}
|
|
45
73
|
}
|
|
46
74
|
|
|
47
|
-
async fn start_server(&self, file_path: Option<String>) -> anyhow::Result<()> {
|
|
75
|
+
pub async fn start_server(&self, file_path: Option<String>) -> anyhow::Result<()> {
|
|
48
76
|
let url_server = self.url.clone();
|
|
49
77
|
std::thread::spawn(move || {
|
|
50
78
|
let result = run_server(url_server, file_path);
|
|
@@ -73,7 +101,7 @@ impl Chidori {
|
|
|
73
101
|
}
|
|
74
102
|
}
|
|
75
103
|
|
|
76
|
-
async fn play(&self, branch: u64, frame: u64) -> anyhow::Result<ExecutionStatus> {
|
|
104
|
+
pub async fn play(&self, branch: u64, frame: u64) -> anyhow::Result<ExecutionStatus> {
|
|
77
105
|
let file_id = self.file_id.clone();
|
|
78
106
|
let url = self.url.clone();
|
|
79
107
|
let mut client = get_client(url).await?;
|
|
@@ -85,7 +113,7 @@ impl Chidori {
|
|
|
85
113
|
Ok(result.into_inner())
|
|
86
114
|
}
|
|
87
115
|
|
|
88
|
-
async fn pause(&self, frame: u64) -> anyhow::Result<ExecutionStatus> {
|
|
116
|
+
pub async fn pause(&self, frame: u64) -> anyhow::Result<ExecutionStatus> {
|
|
89
117
|
let file_id = self.file_id.clone();
|
|
90
118
|
let url = self.url.clone();
|
|
91
119
|
let branch = self.current_branch.clone();
|
|
@@ -99,7 +127,7 @@ impl Chidori {
|
|
|
99
127
|
Ok(result.into_inner())
|
|
100
128
|
}
|
|
101
129
|
|
|
102
|
-
async fn query( &self, query: String, branch: u64, frame: u64, ) -> anyhow::Result<QueryAtFrameResponse> {
|
|
130
|
+
pub async fn query( &self, query: String, branch: u64, frame: u64, ) -> anyhow::Result<QueryAtFrameResponse> {
|
|
103
131
|
let file_id = self.file_id.clone();
|
|
104
132
|
let url = self.url.clone();
|
|
105
133
|
let mut client = get_client(url).await?;
|
|
@@ -114,7 +142,19 @@ impl Chidori {
|
|
|
114
142
|
Ok(result.into_inner())
|
|
115
143
|
}
|
|
116
144
|
|
|
117
|
-
async fn
|
|
145
|
+
pub async fn branch( &self, branch: u64, frame: u64, ) -> anyhow::Result<ExecutionStatus> {
|
|
146
|
+
let file_id = self.file_id.clone();
|
|
147
|
+
let url = self.url.clone();
|
|
148
|
+
let mut client = get_client(url).await?;
|
|
149
|
+
let result = client.branch(RequestNewBranch {
|
|
150
|
+
id: file_id,
|
|
151
|
+
source_branch_id: branch,
|
|
152
|
+
diverges_at_counter: frame
|
|
153
|
+
}).await?;
|
|
154
|
+
Ok(result.into_inner())
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
pub async fn list_branches( &self) -> anyhow::Result<ListBranchesRes> {
|
|
118
158
|
let file_id = self.file_id.clone();
|
|
119
159
|
let url = self.url.clone();
|
|
120
160
|
let mut client = get_client(url).await?;
|
|
@@ -124,7 +164,7 @@ impl Chidori {
|
|
|
124
164
|
Ok(result.into_inner())
|
|
125
165
|
}
|
|
126
166
|
|
|
127
|
-
async fn display_graph_structure( &self,
|
|
167
|
+
pub async fn display_graph_structure( &self, branch: u64) -> anyhow::Result<String> {
|
|
128
168
|
let file_id = self.file_id.clone();
|
|
129
169
|
let url = self.url.clone();
|
|
130
170
|
let mut client = get_client(url).await?;
|
|
@@ -138,7 +178,7 @@ impl Chidori {
|
|
|
138
178
|
Ok(g.get_dot_graph())
|
|
139
179
|
}
|
|
140
180
|
|
|
141
|
-
async fn list_registered_graphs(&self) -> anyhow::Result<()> {
|
|
181
|
+
pub async fn list_registered_graphs(&self) -> anyhow::Result<()> {
|
|
142
182
|
let file_id = self.file_id.clone();
|
|
143
183
|
let url = self.url.clone();
|
|
144
184
|
let mut client = get_client(url).await?;
|
|
@@ -210,17 +250,20 @@ impl Chidori {
|
|
|
210
250
|
// // TODO: nodes that are added should return a clean definition of what their addition looks like
|
|
211
251
|
// // TODO: adding a node should also display any errors
|
|
212
252
|
|
|
253
|
+
pub fn register_custom_node_handle(&mut self, key: String, handler: Handler) {
|
|
254
|
+
self.custom_node_handlers.insert(key, Arc::new(handler));
|
|
255
|
+
}
|
|
213
256
|
|
|
214
|
-
async fn poll_local_code_node_execution(&self) -> anyhow::Result<RespondPollNodeWillExecuteEvents> {
|
|
257
|
+
pub async fn poll_local_code_node_execution(&self) -> anyhow::Result<RespondPollNodeWillExecuteEvents> {
|
|
215
258
|
let file_id = self.file_id.clone();
|
|
216
259
|
let url = self.url.clone();
|
|
217
260
|
let mut client = get_client(url).await?;
|
|
218
261
|
let req = FilteredPollNodeWillExecuteEventsRequest { id: file_id.clone() };
|
|
219
|
-
let result = client.
|
|
262
|
+
let result = client.poll_custom_node_will_execute_events(req).await?;
|
|
220
263
|
Ok(result.into_inner())
|
|
221
264
|
}
|
|
222
265
|
|
|
223
|
-
async fn ack_local_code_node_execution(&self, branch: u64, counter : u64) -> anyhow::Result<ExecutionStatus> {
|
|
266
|
+
pub async fn ack_local_code_node_execution(&self, branch: u64, counter : u64) -> anyhow::Result<ExecutionStatus> {
|
|
224
267
|
let file_id = self.file_id.clone();
|
|
225
268
|
let url = self.url.clone();
|
|
226
269
|
let mut client = get_client(url).await?;
|
|
@@ -232,10 +275,28 @@ impl Chidori {
|
|
|
232
275
|
Ok(result.into_inner())
|
|
233
276
|
}
|
|
234
277
|
|
|
235
|
-
async fn respond_local_code_node_execution
|
|
278
|
+
pub async fn respond_local_code_node_execution<T: Serialize>(
|
|
279
|
+
&self,
|
|
280
|
+
branch: u64,
|
|
281
|
+
counter: u64,
|
|
282
|
+
node_name: String,
|
|
283
|
+
response: T
|
|
284
|
+
) -> anyhow::Result<ExecutionStatus> {
|
|
236
285
|
let file_id = self.file_id.clone();
|
|
237
286
|
let url = self.url.clone();
|
|
238
287
|
|
|
288
|
+
let json_object = serde_json::to_value(response)?;
|
|
289
|
+
let response_paths = json_value_to_paths(&json_object);
|
|
290
|
+
let filled_values = response_paths.into_iter().map(|path| {
|
|
291
|
+
ChangeValue {
|
|
292
|
+
path: Some(Path {
|
|
293
|
+
address: path.0,
|
|
294
|
+
}),
|
|
295
|
+
value: Some(path.1),
|
|
296
|
+
branch,
|
|
297
|
+
}
|
|
298
|
+
}).collect();
|
|
299
|
+
|
|
239
300
|
// TODO: need parent counters from the original change
|
|
240
301
|
// TODO: need source node
|
|
241
302
|
let mut client = get_client(url).await?;
|
|
@@ -245,63 +306,193 @@ impl Chidori {
|
|
|
245
306
|
Ok(client.push_worker_event(FileAddressedChangeValueWithCounter {
|
|
246
307
|
branch,
|
|
247
308
|
counter,
|
|
248
|
-
node_name,
|
|
309
|
+
node_name: node_name.clone(),
|
|
249
310
|
id: file_id.clone(),
|
|
250
311
|
change: Some(ChangeValueWithCounter {
|
|
251
|
-
filled_values
|
|
312
|
+
filled_values,
|
|
252
313
|
parent_monotonic_counters: vec![],
|
|
253
314
|
monotonic_counter: counter,
|
|
254
315
|
branch,
|
|
255
|
-
source_node:
|
|
316
|
+
source_node: node_name.clone(),
|
|
256
317
|
})
|
|
257
318
|
}).await?.into_inner())
|
|
258
319
|
}
|
|
320
|
+
|
|
321
|
+
pub async fn run_custom_node_loop(&self) -> anyhow::Result<()> {
|
|
322
|
+
loop {
|
|
323
|
+
let mut backoff = 2;
|
|
324
|
+
let events = self.poll_local_code_node_execution().await?;
|
|
325
|
+
if events.node_will_execute_events.len() <= 0 {
|
|
326
|
+
backoff = backoff * backoff;
|
|
327
|
+
tokio::time::sleep(std::time::Duration::from_millis(100 * backoff)).await;
|
|
328
|
+
continue;
|
|
329
|
+
} else {
|
|
330
|
+
backoff = 2;
|
|
331
|
+
for ev in &events.node_will_execute_events {
|
|
332
|
+
// ACK messages
|
|
333
|
+
let NodeWillExecuteOnBranch { branch, counter, node, ..} = ev;
|
|
334
|
+
let node_name = &node.as_ref().unwrap().source_node;
|
|
335
|
+
if let Some(x) = self.custom_node_handlers.get(&ev.custom_node_type_name.clone().unwrap()) {
|
|
336
|
+
self.ack_local_code_node_execution(*branch, *counter).await?;
|
|
337
|
+
let result = (x.as_ref().callback)(ev.clone()).await?;
|
|
338
|
+
dbg!(&result);
|
|
339
|
+
self.respond_local_code_node_execution(*branch, *counter, node_name.clone(), result).await?;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
259
345
|
}
|
|
260
346
|
|
|
261
347
|
|
|
348
|
+
fn default_queries() -> Option<Vec<String>> {
|
|
349
|
+
Some(vec!["None".to_string()])
|
|
350
|
+
}
|
|
351
|
+
|
|
262
352
|
#[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>
|
|
353
|
+
pub struct PromptNodeCreateOpts {
|
|
354
|
+
pub name: String,
|
|
355
|
+
pub queries: Option<Vec<String>>,
|
|
356
|
+
pub output_tables: Option<Vec<String>>,
|
|
357
|
+
pub template: String,
|
|
358
|
+
pub model: Option<String>
|
|
269
359
|
}
|
|
270
360
|
|
|
361
|
+
impl Default for PromptNodeCreateOpts {
|
|
362
|
+
fn default() -> Self {
|
|
363
|
+
PromptNodeCreateOpts {
|
|
364
|
+
name: "".to_string(),
|
|
365
|
+
queries: default_queries(),
|
|
366
|
+
output_tables: None,
|
|
367
|
+
template: "".to_string(),
|
|
368
|
+
model: Some("GPT_3_5_TURBO".to_string()),
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
impl PromptNodeCreateOpts {
|
|
373
|
+
pub fn merge(&mut self, other: PromptNodeCreateOpts) {
|
|
374
|
+
self.name = other.name;
|
|
375
|
+
self.queries = other.queries.or(self.queries.take());
|
|
376
|
+
self.output_tables = other.output_tables.or(self.output_tables.take());
|
|
377
|
+
self.template = other.template;
|
|
378
|
+
self.model = other.model.or(self.model.take());
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
|
|
271
383
|
|
|
272
384
|
#[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
|
|
385
|
+
pub struct CustomNodeCreateOpts {
|
|
386
|
+
pub name: String,
|
|
387
|
+
pub queries: Option<Vec<String>>,
|
|
388
|
+
pub output_tables: Option<Vec<String>>,
|
|
389
|
+
pub output: Option<String>,
|
|
390
|
+
pub node_type_name: String
|
|
279
391
|
}
|
|
280
392
|
|
|
393
|
+
|
|
394
|
+
impl Default for CustomNodeCreateOpts {
|
|
395
|
+
fn default() -> Self {
|
|
396
|
+
CustomNodeCreateOpts {
|
|
397
|
+
name: "".to_string(),
|
|
398
|
+
queries: default_queries(),
|
|
399
|
+
output_tables: None,
|
|
400
|
+
output: None,
|
|
401
|
+
node_type_name: "".to_string(),
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
impl CustomNodeCreateOpts {
|
|
406
|
+
pub fn merge(&mut self, other: CustomNodeCreateOpts) {
|
|
407
|
+
self.name = other.name;
|
|
408
|
+
self.queries = other.queries.or(self.queries.take());
|
|
409
|
+
self.output_tables = other.output_tables.or(self.output_tables.take());
|
|
410
|
+
self.output = other.output.or(self.output.take());
|
|
411
|
+
self.node_type_name = other.node_type_name;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
|
|
281
417
|
#[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>
|
|
418
|
+
pub struct DenoCodeNodeCreateOpts {
|
|
419
|
+
pub name: String,
|
|
420
|
+
pub queries: Option<Vec<String>>,
|
|
421
|
+
pub output_tables: Option<Vec<String>>,
|
|
422
|
+
pub output: Option<String>,
|
|
423
|
+
pub code: String,
|
|
424
|
+
pub is_template: Option<bool>
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
impl Default for DenoCodeNodeCreateOpts {
|
|
428
|
+
fn default() -> Self {
|
|
429
|
+
DenoCodeNodeCreateOpts {
|
|
430
|
+
name: "".to_string(),
|
|
431
|
+
queries: default_queries(),
|
|
432
|
+
output_tables: None,
|
|
433
|
+
output: None,
|
|
434
|
+
code: "".to_string(),
|
|
435
|
+
is_template: None,
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
impl DenoCodeNodeCreateOpts {
|
|
441
|
+
pub fn merge(&mut self, other: DenoCodeNodeCreateOpts) {
|
|
442
|
+
self.name = other.name;
|
|
443
|
+
self.queries = other.queries.or(self.queries.take());
|
|
444
|
+
self.output_tables = other.output_tables.or(self.output_tables.take());
|
|
445
|
+
self.output = other.output.or(self.output.take());
|
|
446
|
+
self.code = other.code;
|
|
447
|
+
self.is_template = other.is_template.or(self.is_template.take());
|
|
448
|
+
}
|
|
289
449
|
}
|
|
290
450
|
|
|
291
451
|
#[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,
|
|
452
|
+
pub struct VectorMemoryNodeCreateOpts {
|
|
453
|
+
pub name: String,
|
|
454
|
+
pub queries: Option<Vec<String>>,
|
|
455
|
+
pub output_tables: Option<Vec<String>>,
|
|
456
|
+
pub output: Option<String>,
|
|
457
|
+
pub template: Option<String>, // TODO: default is the contents of the query
|
|
458
|
+
pub action: Option<String>, // TODO: default WRITE
|
|
459
|
+
pub embedding_model: Option<String>, // TODO: default TEXT_EMBEDDING_ADA_002
|
|
460
|
+
pub db_vendor: Option<String>, // TODO: default QDRANT
|
|
461
|
+
pub collection_name: String,
|
|
302
462
|
}
|
|
303
463
|
|
|
304
464
|
|
|
465
|
+
impl Default for VectorMemoryNodeCreateOpts {
|
|
466
|
+
fn default() -> Self {
|
|
467
|
+
VectorMemoryNodeCreateOpts {
|
|
468
|
+
name: "".to_string(),
|
|
469
|
+
queries: None,
|
|
470
|
+
output_tables: None,
|
|
471
|
+
output: None,
|
|
472
|
+
template: None,
|
|
473
|
+
action: None,
|
|
474
|
+
embedding_model: None,
|
|
475
|
+
db_vendor: None,
|
|
476
|
+
collection_name: "".to_string(),
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
|
|
482
|
+
impl VectorMemoryNodeCreateOpts {
|
|
483
|
+
pub fn merge(&mut self, other: VectorMemoryNodeCreateOpts) {
|
|
484
|
+
self.name = other.name;
|
|
485
|
+
self.queries = other.queries.or(self.queries.take());
|
|
486
|
+
self.output_tables = other.output_tables.or(self.output_tables.take());
|
|
487
|
+
self.output = other.output.or(self.output.take());
|
|
488
|
+
self.template = other.template.or(self.template.take());
|
|
489
|
+
self.action = other.action.or(self.action.take());
|
|
490
|
+
self.embedding_model = other.embedding_model.or(self.embedding_model.take());
|
|
491
|
+
self.db_vendor = other.db_vendor.or(self.db_vendor.take());
|
|
492
|
+
self.collection_name = other.collection_name;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
|
|
305
496
|
fn remap_queries(queries: Option<Vec<String>>) -> Vec<Option<String>> {
|
|
306
497
|
let queries: Vec<Option<String>> = if let Some(queries) = queries {
|
|
307
498
|
queries.into_iter().map(|q| {
|
|
@@ -317,59 +508,73 @@ fn remap_queries(queries: Option<Vec<String>>) -> Vec<Option<String>> {
|
|
|
317
508
|
queries
|
|
318
509
|
}
|
|
319
510
|
|
|
320
|
-
|
|
511
|
+
#[derive(Clone)]
|
|
512
|
+
pub struct GraphBuilder {
|
|
321
513
|
clean_graph: CleanedDefinitionGraph,
|
|
322
514
|
}
|
|
323
515
|
|
|
324
516
|
impl GraphBuilder {
|
|
325
|
-
fn
|
|
517
|
+
pub fn new() -> Self {
|
|
518
|
+
GraphBuilder {
|
|
519
|
+
clean_graph: CleanedDefinitionGraph::zero()
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
pub fn prompt_node(&mut self, arg: PromptNodeCreateOpts) -> anyhow::Result<NodeHandle> {
|
|
523
|
+
let mut def = PromptNodeCreateOpts::default();
|
|
524
|
+
def.merge(arg);
|
|
326
525
|
let node = create_prompt_node(
|
|
327
|
-
|
|
328
|
-
remap_queries(
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
526
|
+
def.name.clone(),
|
|
527
|
+
remap_queries(def.queries),
|
|
528
|
+
def.template,
|
|
529
|
+
def.model.unwrap_or("GPT_3_5_TURBO".to_string()),
|
|
530
|
+
def.output_tables.unwrap_or(vec![]))?;
|
|
332
531
|
self.clean_graph.merge_file(&File { nodes: vec![node.clone()], ..Default::default() })?;
|
|
333
532
|
Ok(NodeHandle::from(node)?)
|
|
334
533
|
}
|
|
335
534
|
|
|
336
|
-
fn custom_node(&mut self, arg: CustomNodeCreateOpts) -> anyhow::Result<NodeHandle> {
|
|
535
|
+
pub fn custom_node(&mut self, arg: CustomNodeCreateOpts) -> anyhow::Result<NodeHandle> {
|
|
536
|
+
let mut def = CustomNodeCreateOpts::default();
|
|
537
|
+
def.merge(arg);
|
|
337
538
|
let node = create_custom_node(
|
|
338
|
-
|
|
339
|
-
remap_queries(
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
539
|
+
def.name.clone(),
|
|
540
|
+
remap_queries(def.queries.clone()),
|
|
541
|
+
def.output.unwrap_or("type O {}".to_string()),
|
|
542
|
+
def.node_type_name,
|
|
543
|
+
def.output_tables.unwrap_or(vec![])
|
|
343
544
|
);
|
|
344
545
|
self.clean_graph.merge_file(&File { nodes: vec![node.clone()], ..Default::default() })?;
|
|
345
546
|
Ok(NodeHandle::from(node)?)
|
|
346
547
|
}
|
|
347
548
|
|
|
348
549
|
|
|
349
|
-
fn deno_code_node(&mut self, arg: DenoCodeNodeCreateOpts) -> anyhow::Result<NodeHandle> {
|
|
550
|
+
pub fn deno_code_node(&mut self, arg: DenoCodeNodeCreateOpts) -> anyhow::Result<NodeHandle> {
|
|
551
|
+
let mut def = DenoCodeNodeCreateOpts::default();
|
|
552
|
+
def.merge(arg);
|
|
350
553
|
let node = create_code_node(
|
|
351
|
-
|
|
352
|
-
remap_queries(
|
|
353
|
-
|
|
354
|
-
SourceNodeType::Code("DENO".to_string(),
|
|
355
|
-
|
|
554
|
+
def.name.clone(),
|
|
555
|
+
remap_queries(def.queries.clone()),
|
|
556
|
+
def.output.unwrap_or("type O {}".to_string()),
|
|
557
|
+
SourceNodeType::Code("DENO".to_string(), def.code, def.is_template.unwrap_or(false)),
|
|
558
|
+
def.output_tables.unwrap_or(vec![])
|
|
356
559
|
);
|
|
357
560
|
self.clean_graph.merge_file(&File { nodes: vec![node.clone()], ..Default::default() })?;
|
|
358
561
|
Ok(NodeHandle::from(node)?)
|
|
359
562
|
}
|
|
360
563
|
|
|
361
564
|
|
|
362
|
-
fn vector_memory_node(&mut self, arg: VectorMemoryNodeCreateOpts) -> anyhow::Result<NodeHandle> {
|
|
565
|
+
pub fn vector_memory_node(&mut self, arg: VectorMemoryNodeCreateOpts) -> anyhow::Result<NodeHandle> {
|
|
566
|
+
let mut def = VectorMemoryNodeCreateOpts::default();
|
|
567
|
+
def.merge(arg);
|
|
363
568
|
let node = create_vector_memory_node(
|
|
364
|
-
|
|
365
|
-
remap_queries(
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
569
|
+
def.name.clone(),
|
|
570
|
+
remap_queries(def.queries.clone()),
|
|
571
|
+
def.output.unwrap_or("type O {}".to_string()),
|
|
572
|
+
def.action.unwrap_or("READ".to_string()),
|
|
573
|
+
def.embedding_model.unwrap_or("TEXT_EMBEDDING_ADA_002".to_string()),
|
|
574
|
+
def.template.unwrap_or("".to_string()),
|
|
575
|
+
def.db_vendor.unwrap_or("QDRANT".to_string()),
|
|
576
|
+
def.collection_name,
|
|
577
|
+
def.output_tables.unwrap_or(vec![])
|
|
373
578
|
)?;
|
|
374
579
|
self.clean_graph.merge_file(&File { nodes: vec![node.clone()], ..Default::default() })?;
|
|
375
580
|
Ok(NodeHandle::from(node)?)
|
|
@@ -426,9 +631,12 @@ impl GraphBuilder {
|
|
|
426
631
|
// // })
|
|
427
632
|
// // }
|
|
428
633
|
|
|
429
|
-
async fn commit(&self,
|
|
634
|
+
pub async fn commit(&self, c: &Chidori, branch: u64) -> anyhow::Result<ExecutionStatus> {
|
|
635
|
+
let url = &c.url;
|
|
636
|
+
let file_id = &c.file_id;
|
|
430
637
|
let mut client = get_client(url.clone()).await?;
|
|
431
638
|
let nodes = self.clean_graph.node_by_name.clone().into_values().collect();
|
|
639
|
+
|
|
432
640
|
Ok(client.merge(RequestFileMerge {
|
|
433
641
|
id: file_id.clone(),
|
|
434
642
|
file: Some(File { nodes, ..Default::default() }),
|
|
@@ -441,7 +649,7 @@ impl GraphBuilder {
|
|
|
441
649
|
// Node handle
|
|
442
650
|
#[derive(Clone)]
|
|
443
651
|
pub struct NodeHandle {
|
|
444
|
-
node: Item,
|
|
652
|
+
pub node: Item,
|
|
445
653
|
indiv: CleanIndividualNode
|
|
446
654
|
}
|
|
447
655
|
|
|
@@ -457,18 +665,29 @@ impl NodeHandle {
|
|
|
457
665
|
|
|
458
666
|
|
|
459
667
|
impl NodeHandle {
|
|
460
|
-
fn get_name(&self) -> String {
|
|
668
|
+
pub(crate) fn get_name(&self) -> String {
|
|
461
669
|
self.node.core.as_ref().unwrap().name.clone()
|
|
462
670
|
}
|
|
463
671
|
|
|
464
|
-
|
|
672
|
+
fn get_output_type(&self) -> Vec<Vec<String>> {
|
|
673
|
+
self.indiv.output_path.clone()
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
pub fn run_when(&mut self, graph_builder: &mut GraphBuilder, other_node: &NodeHandle) -> anyhow::Result<bool> {
|
|
465
677
|
let queries = &mut self.node.core.as_mut().unwrap().queries;
|
|
678
|
+
|
|
679
|
+
// Remove null query if it is the only one present
|
|
680
|
+
if queries.len() == 1 && queries[0].query.is_none() {
|
|
681
|
+
queries.remove(0);
|
|
682
|
+
}
|
|
683
|
+
|
|
466
684
|
let q = construct_query_from_output_type(
|
|
467
685
|
&other_node.get_name(),
|
|
468
686
|
&other_node.get_name(),
|
|
469
|
-
&
|
|
687
|
+
&other_node.get_output_type()
|
|
470
688
|
).unwrap();
|
|
471
689
|
queries.push(Query { query: Some(q)});
|
|
690
|
+
graph_builder.clean_graph.merge_file(&File { nodes: vec![self.node.clone()], ..Default::default() })?;
|
|
472
691
|
Ok(true)
|
|
473
692
|
}
|
|
474
693
|
|
|
@@ -498,6 +717,16 @@ impl NodeHandle {
|
|
|
498
717
|
|
|
499
718
|
}
|
|
500
719
|
|
|
720
|
+
#[macro_export]
|
|
721
|
+
macro_rules! register_node_handle {
|
|
722
|
+
($c:expr, $name:expr, $handler:expr) => {
|
|
723
|
+
$c.register_custom_node_handle($name.to_string(), Handler::new(
|
|
724
|
+
move |n| Box::pin(async move { ($handler)(n).await })
|
|
725
|
+
));
|
|
726
|
+
};
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
|
|
501
730
|
#[cfg(test)]
|
|
502
731
|
mod tests {
|
|
503
732
|
use super::*;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
use serde_json::Value as JsonValue;
|
|
2
|
+
use std::collections::VecDeque;
|
|
3
|
+
use prompt_graph_core::proto2::SerializedValue;
|
|
4
|
+
use prompt_graph_core::templates::json_value_to_serialized_value;
|
|
5
|
+
|
|
6
|
+
pub fn json_value_to_paths(
|
|
7
|
+
d: &JsonValue,
|
|
8
|
+
) -> Vec<(Vec<String>, SerializedValue)> {
|
|
9
|
+
let mut paths = Vec::new();
|
|
10
|
+
let mut queue: VecDeque<(Vec<String>, &JsonValue)> = VecDeque::new();
|
|
11
|
+
queue.push_back((Vec::new(), d));
|
|
12
|
+
|
|
13
|
+
while let Some((mut path, dict)) = queue.pop_front() {
|
|
14
|
+
match dict {
|
|
15
|
+
JsonValue::Object(map) => {
|
|
16
|
+
for (key, val) in map {
|
|
17
|
+
let key_str = key.clone();
|
|
18
|
+
path.push(key_str.clone());
|
|
19
|
+
match val {
|
|
20
|
+
JsonValue::Object(_) => {
|
|
21
|
+
queue.push_back((path.clone(), val));
|
|
22
|
+
},
|
|
23
|
+
_ => {
|
|
24
|
+
paths.push((path.clone(), json_value_to_serialized_value(&val)));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
path.pop();
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
JsonValue::Array(arr) => {
|
|
31
|
+
for (i, val) in arr.iter().enumerate() {
|
|
32
|
+
path.push(i.to_string());
|
|
33
|
+
match val {
|
|
34
|
+
JsonValue::Object(_) => {
|
|
35
|
+
queue.push_back((path.clone(), val));
|
|
36
|
+
},
|
|
37
|
+
_ => {
|
|
38
|
+
paths.push((path.clone(), json_value_to_serialized_value(&val)));
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
path.pop();
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
_ => panic!("Root should be a JSON object but was {:?}", d),
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
paths
|
|
49
|
+
}
|