Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pdl-live-react/src-tauri/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use urlencoding::encode;

use crate::compile;
use crate::gui::new_window;
use crate::pdl::interpreter::{load_scope, run_file_sync, RunOptions};
use crate::pdl::interpreter::{RunOptions, load_scope, run_file_sync};

#[cfg(desktop)]
pub fn setup(app: &mut tauri::App) -> Result<bool, Box<dyn ::std::error::Error>> {
Expand Down
104 changes: 56 additions & 48 deletions pdl-live-react/src-tauri/src/compile/beeai.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ use ::std::path::{Path, PathBuf};
use duct::cmd;
use futures::executor::block_on;
use serde::Deserialize;
use serde_json::{from_reader, json, to_string, Map, Value};
use serde_json::{Map, Value, from_reader, json, to_string};
use tempfile::Builder;

use crate::pdl::ast::{
ArrayBlock, CallBlock, EvalsTo, FunctionBlock, ListOrString, MessageBlock, MetadataBuilder,
ModelBlock, ObjectBlock, PdlBaseType, PdlBlock, PdlOptionalType, PdlParser, PdlType,
PythonCodeBlock, RepeatBlock, Role, TextBlock, TextBlockBuilder,
ArrayBlockBuilder, CallBlock, EvalsTo, FunctionBlock, ListOrString, MessageBlock,
MetadataBuilder, ModelBlockBuilder, ObjectBlock, PdlBaseType, PdlBlock, PdlOptionalType,
PdlParser, PdlType, PythonCodeBlock, RepeatBlock, Role, TextBlock, TextBlockBuilder,
};
use crate::pdl::pip::pip_install_if_needed;
use crate::pdl::requirements::BEEAI_FRAMEWORK;
Expand Down Expand Up @@ -200,32 +200,39 @@ fn call_tools(model: &String, parameters: &HashMap<String, Value>) -> PdlBlock {
role: None,
parser: None,
text: vec![PdlBlock::Model(
ModelBlock::new(model.as_str())
.parameters(&strip_nulls(parameters))
.input(PdlBlock::Array(ArrayBlock {
array: vec![PdlBlock::Message(MessageBlock {
metadata: None,
role: Role::Tool,
defsite: None,
name: Some("${ tool.function.name }".to_string()),
tool_call_id: Some("${ tool.id }".to_string()),
content: Box::new(PdlBlock::Call(CallBlock {
metadata: Some(
MetadataBuilder::default()
.defs(json_loads(
&"args",
&"pdl__args",
&"${ tool.function.arguments }",
))
.build()
.unwrap(),
),
call: EvalsTo::Jinja("${ pdl__tools[tool.function.name] }".to_string()), // look up tool in tool_declarations def (see below)
args: Some("${ args }".into()), // invoke with arguments as specified by the model
})),
})],
}))
.build(),
ModelBlockBuilder::default()
.model(model.as_str())
.parameters(strip_nulls(parameters))
.input(PdlBlock::Array(
ArrayBlockBuilder::default()
.array(vec![PdlBlock::Message(MessageBlock {
metadata: None,
role: Role::Tool,
defsite: None,
name: Some("${ tool.function.name }".to_string()),
tool_call_id: Some("${ tool.id }".to_string()),
content: Box::new(PdlBlock::Call(CallBlock {
metadata: Some(
MetadataBuilder::default()
.defs(json_loads(
&"args",
&"pdl__args",
&"${ tool.function.arguments }",
))
.build()
.unwrap(),
),
call: EvalsTo::Jinja(
"${ pdl__tools[tool.function.name] }".to_string(),
), // look up tool in tool_declarations def (see below)
args: Some("${ args }".into()), // invoke with arguments as specified by the model
})),
})])
.build()
.unwrap(),
))
.build()
.unwrap(),
)],
});

Expand All @@ -237,6 +244,7 @@ fn call_tools(model: &String, parameters: &HashMap<String, Value>) -> PdlBlock {

// response.choices[0].message.tool_calls
PdlBlock::Repeat(RepeatBlock {
metadata: None,
for_: for_,
repeat: Box::new(repeat),
})
Expand Down Expand Up @@ -416,6 +424,7 @@ pub fn compile(source_file_path: &str, debug: bool) -> Result<PdlBlock, Box<dyn
function: schema,
return_: Box::new(PdlBlock::PythonCode(PythonCodeBlock {
// tool function definition
metadata: None,
lang: "python".to_string(),
code: format!(
"
Expand Down Expand Up @@ -489,28 +498,27 @@ asyncio.run(invoke())
}));
}

let model_response = if let Some(tools) = &tools {
match tools.len() {
0 => None,
_ => Some("response".to_string()),
}
} else {
None
};

model_call.push(PdlBlock::Model(ModelBlock {
metadata: Some(
let mut model_builder = ModelBlockBuilder::default();
model_builder
.metadata(
MetadataBuilder::default()
.description(description)
.build()
.unwrap(),
),
input: None,
model: model.clone(),
model_response: model_response,
pdl_usage: None,
parameters: Some(with_tools(&tools, &parameters.state.dict)),
}));
)
.model(model.clone())
.parameters(with_tools(&tools, &parameters.state.dict));

if let Some(tools) = &tools {
if tools.len() > 0 {
// then we want the model response as a
// "response" variable, so we can scan for
// tool calls
model_builder.model_response("response".to_string());
}
}

model_call.push(PdlBlock::Model(model_builder.build().unwrap()));

if let Some(tools) = tools {
if tools.len() > 0 {
Expand Down
106 changes: 61 additions & 45 deletions pdl-live-react/src-tauri/src/pdl/ast.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use ::std::collections::HashMap;
use ::std::time::{SystemTime, SystemTimeError};

use indexmap::IndexMap;
use serde::{Deserialize, Serialize};
use serde_json::{to_string, Number, Value};
use serde_json::{Number, Value, to_string};

#[derive(Serialize, Deserialize, Debug, Clone)]
//why doesn't this work? #[serde(rename_all_fields(serialize = "lowercase"))]
Expand Down Expand Up @@ -52,10 +54,10 @@ pub enum PdlType {
}

/// Timing information
#[derive(Serialize, Deserialize, Debug, Clone)]
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
pub struct Timing {
start_nanos: u64,
end_nanos: u64,
start_nanos: u128,
end_nanos: u128,
timezone: String,
}

Expand Down Expand Up @@ -86,6 +88,23 @@ pub struct Metadata {
pub pdl_timing: Option<Timing>,
}

impl Metadata {
fn start(&mut self) -> Result<(), SystemTimeError> {
let nanos = ::std::time::SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)?
.as_nanos();
if let Some(t) = &mut self.pdl_timing {
t.start_nanos = nanos;
} else {
let mut t = Timing::default();
t.start_nanos = nanos;
self.pdl_timing = Some(t)
}

Ok(())
}
}

/// Call a function
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(tag = "kind", rename = "call")]
Expand Down Expand Up @@ -128,17 +147,17 @@ pub trait SequencingBlock {
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(tag = "kind", rename = "lastOf")]
pub struct LastOfBlock {
#[serde(flatten)]
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<Metadata>,

/// Sequence of blocks to execute
#[serde(rename = "lastOf")]
pub last_of: Vec<PdlBlock>,

#[serde(skip_serializing_if = "Option::is_none")]
pub role: Option<Role>,

#[serde(flatten)]
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<Metadata>,

#[serde(skip_serializing_if = "Option::is_none")]
pub parser: Option<PdlParser>,
}
Expand Down Expand Up @@ -260,8 +279,9 @@ pub struct PdlUsage {
pub prompt_nanos: u64,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
#[derive(Serialize, Deserialize, Debug, Clone, Default, derive_builder::Builder)]
#[serde(tag = "kind", rename = "model")]
#[builder(setter(into, strip_option), default)]
pub struct ModelBlock {
#[serde(flatten)]
#[serde(skip_serializing_if = "Option::is_none")]
Expand All @@ -281,17 +301,6 @@ pub struct ModelBlock {
}

impl ModelBlock {
pub fn new(model: &str) -> Self {
ModelBlock {
metadata: Default::default(),
model_response: None,
parameters: None,
pdl_usage: None,
model: model.into(),
input: None,
}
}

pub fn with_result(&self, result: PdlResult) -> Self {
let mut c = self.clone();
let mut metadata = if let Some(meta) = c.metadata {
Expand All @@ -307,25 +316,6 @@ impl ModelBlock {
pub fn description(&self) -> Option<String> {
self.metadata.as_ref().and_then(|m| m.description.clone())
}

pub fn input(&mut self, input: PdlBlock) -> &mut Self {
self.input = Some(Box::new(input));
self
}

pub fn input_str(&mut self, input: &str) -> &mut Self {
self.input = Some(Box::new(PdlBlock::String(input.into())));
self
}

pub fn parameters(&mut self, parameters: &HashMap<String, Value>) -> &mut Self {
self.parameters = Some(parameters.clone());
self
}

pub fn build(&self) -> Self {
self.clone()
}
}

#[derive(Serialize, Deserialize, Debug, Clone)]
Expand All @@ -348,6 +338,10 @@ pub enum ListOrString {
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(tag = "kind", rename = "repeat")]
pub struct RepeatBlock {
#[serde(flatten)]
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<Metadata>,

/// Arrays to iterate over
#[serde(rename = "for")]
pub for_: HashMap<String, ListOrString>,
Expand Down Expand Up @@ -444,7 +438,14 @@ pub struct DataBlock {
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(tag = "kind", rename = "code")]
pub struct PythonCodeBlock {
#[serde(flatten)]
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<Metadata>,

/// Programming language of the code
pub lang: String,

/// Code to execute
pub code: String,
}

Expand Down Expand Up @@ -526,6 +527,10 @@ pub enum EvalsTo<S, T> {
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(tag = "kind", rename = "if")]
pub struct IfBlock {
#[serde(flatten)]
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<Metadata>,

/// The condition to check
#[serde(rename = "if")]
pub condition: EvalsTo<StringOrBoolean, bool>,
Expand All @@ -537,16 +542,17 @@ pub struct IfBlock {
#[serde(rename = "else")]
#[serde(skip_serializing_if = "Option::is_none")]
pub else_: Option<Box<PdlBlock>>,

#[serde(flatten)]
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<Metadata>,
}

/// Return the array of values computed by each block of the list of blocks
#[derive(Serialize, Deserialize, Debug, Clone)]
#[derive(Serialize, Deserialize, Debug, Clone, Default, derive_builder::Builder)]
#[serde(tag = "kind", rename = "array")]
#[builder(setter(into, strip_option), default)]
pub struct ArrayBlock {
#[serde(flatten)]
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<Metadata>,

/// Elements of the array
pub array: Vec<PdlBlock>,
}
Expand All @@ -555,6 +561,10 @@ pub struct ArrayBlock {
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(tag = "kind", rename = "include")]
pub struct IncludeBlock {
#[serde(flatten)]
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<Metadata>,

/// Name of the file to include.
pub include: String,
}
Expand All @@ -563,6 +573,10 @@ pub struct IncludeBlock {
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(tag = "kind", rename = "import")]
pub struct ImportBlock {
#[serde(flatten)]
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<Metadata>,

/// Name of the file to include.
pub import: String,
}
Expand All @@ -581,6 +595,9 @@ pub enum PdlBlock {
Bool(bool),
Number(Number),
String(String),
Function(FunctionBlock),

// the rest have Metadata; TODO refactor to make this more explicit
If(IfBlock),
Import(ImportBlock),
Include(IncludeBlock),
Expand All @@ -590,7 +607,6 @@ pub enum PdlBlock {
Array(ArrayBlock),
Message(MessageBlock),
Repeat(RepeatBlock),
Function(FunctionBlock),
PythonCode(PythonCodeBlock),
Read(ReadBlock),
Model(ModelBlock),
Expand Down
Loading