Skip to content

Commit 948b5ab

Browse files
committed
strip nulls
Signed-off-by: Nick Mitchell <[email protected]>
1 parent be4be0a commit 948b5ab

File tree

3 files changed

+55
-16
lines changed

3 files changed

+55
-16
lines changed

pdl-live-react/src-tauri/src/compile/beeai.rs

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use ::std::path::{Path, PathBuf};
88
use duct::cmd;
99
use futures::executor::block_on;
1010
use serde::Deserialize;
11-
use serde_json::{from_reader, json, to_string, Value};
11+
use serde_json::{from_reader, json, to_string, Map, Value};
1212
use tempfile::Builder;
1313

1414
use crate::pdl::ast::{
@@ -137,23 +137,46 @@ fn a_tool(tool: &BeeAiToolState) -> Value {
137137
"description": tool.description,
138138
"parameters": json!({
139139
"type": "object",
140-
"properties": tool.input_schema.properties,
140+
"properties": strip_nulls(&tool.input_schema.properties),
141141
}),
142-
"options": tool.options
142+
// "options": tool.options
143143
})
144144
})
145145
}
146146

147+
// Strip null values out of the given HashMap
148+
fn strip_nulls(parameters: &HashMap<String, Value>) -> HashMap<String, Value> {
149+
parameters
150+
.into_iter()
151+
.filter_map(|(k, v)| match v {
152+
Value::Null => None,
153+
Value::Object(m) => Some((k.clone(), Value::Object(strip_nulls2(m)))),
154+
_ => Some((k.clone(), v.clone())),
155+
})
156+
.collect()
157+
}
158+
// sigh, i need to figure out generics IntoIterator, FromIterator
159+
fn strip_nulls2(parameters: &Map<String, Value>) -> Map<String, Value> {
160+
parameters
161+
.into_iter()
162+
.filter_map(|(k, v)| match v {
163+
Value::Null => None,
164+
Value::Object(m) => Some((k.clone(), Value::Object(strip_nulls2(&m)))),
165+
_ => Some((k.clone(), v.clone())),
166+
})
167+
.collect()
168+
}
169+
147170
fn with_tools(
148171
tools: &Option<Vec<BeeAiTool>>,
149172
parameters: &HashMap<String, Value>,
150173
) -> HashMap<String, Value> {
151174
match tools {
152175
Some(tools) => {
153176
match tools.len() {
154-
0 => parameters.clone(), // litellm barfs on tools: []
177+
0 => strip_nulls(parameters), // Note: litellm barfs on tools: []
155178
_ => {
156-
let mut copy = parameters.clone();
179+
let mut copy = strip_nulls(parameters);
157180
copy.insert(
158181
"tools".to_string(),
159182
tools.into_iter().map(|tool| a_tool(&tool.state)).collect(),
@@ -162,7 +185,7 @@ fn with_tools(
162185
}
163186
}
164187
}
165-
_ => parameters.clone(),
188+
_ => strip_nulls(parameters),
166189
}
167190
}
168191

@@ -175,7 +198,7 @@ fn call_tools(model: &String, parameters: &HashMap<String, Value>) -> PdlBlock {
175198
description: Some("Calling tool ${ tool.function.name }".to_string()),
176199
text: vec![PdlBlock::Model(
177200
PdlModelBlock::new(model.as_str())
178-
.parameters(parameters)
201+
.parameters(&strip_nulls(parameters))
179202
.input(PdlBlock::Array {
180203
array: vec![PdlBlock::Message(PdlMessageBlock {
181204
role: Role::Tool,
@@ -239,7 +262,10 @@ fn json_schema_type_to_pdl_type(spec: &Value) -> PdlType {
239262
"boolean" => PdlBaseType::Bool,
240263
"integer" => PdlBaseType::Int,
241264
"null" => PdlBaseType::Null,
242-
_ => PdlBaseType::Null,
265+
x => {
266+
eprintln!("Warning: unhandled JSONSchema type mapping to PDL {:?}", x);
267+
PdlBaseType::Null
268+
}
243269
};
244270
match spec.get("default") {
245271
Some(_) => PdlType::Optional(PdlOptionalType { optional: base }),
@@ -258,10 +284,16 @@ fn json_schema_type_to_pdl_type(spec: &Value) -> PdlType {
258284
optional: t.clone(),
259285
})
260286
}
261-
_ => PdlType::Base(PdlBaseType::Null),
287+
x => {
288+
eprintln!("Warning: unhandled JSONSchema type mapping to PDL {:?}", x);
289+
PdlType::Base(PdlBaseType::Null)
290+
}
262291
}
263292
}
264-
_ => PdlType::Base(PdlBaseType::Null),
293+
x => {
294+
eprintln!("Warning: unhandled JSONSchema type mapping to PDL {:?}", x);
295+
PdlType::Base(PdlBaseType::Null)
296+
}
265297
},
266298
}
267299
}

pdl-live-react/src-tauri/src/pdl/ast.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,15 @@ use serde::{Deserialize, Serialize};
33
use serde_json::{Number, Value};
44

55
#[derive(Serialize, Deserialize, Debug, Clone)]
6-
#[serde(rename_all_fields = "lowercase")]
6+
//why doesn't this work? #[serde(rename_all_fields(serialize = "lowercase"))]
77
pub enum Role {
8+
#[serde(rename = "user")]
89
User,
10+
#[serde(rename = "assistant")]
911
Assistant,
12+
#[serde(rename = "system")]
1013
System,
14+
#[serde(rename = "tool")]
1115
Tool,
1216
}
1317

@@ -139,6 +143,7 @@ pub struct PdlUsage {
139143

140144
#[derive(Serialize, Deserialize, Debug, Clone)]
141145
pub struct PdlModelBlock {
146+
#[serde(skip_serializing_if = "Option::is_none")]
142147
pub description: Option<String>,
143148
pub model: String,
144149
#[serde(skip_serializing_if = "Option::is_none")]
@@ -147,6 +152,7 @@ pub struct PdlModelBlock {
147152
pub parameters: Option<HashMap<String, Value>>,
148153
#[serde(skip_serializing_if = "Option::is_none")]
149154
pub input: Option<Box<PdlBlock>>, // really this should be restricted to be PdlBlock::Array; how do we do this in rust?
155+
#[serde(skip_serializing_if = "Option::is_none")]
150156
#[serde(rename = "modelResponse")]
151157
pub model_response: Option<String>,
152158
#[serde(rename = "pdl__result")]

pdl-live-react/src-tauri/src/pdl/interpreter.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,10 @@ impl<'a> Interpreter<'a> {
118118
}
119119

120120
let backup = result.clone();
121-
Ok(from_str(&result).unwrap_or_else(|_err| {
121+
Ok(from_str(&result).unwrap_or_else(|err| {
122122
if self.debug {
123-
eprintln!("Plain string {}", &result);
123+
eprintln!("Treating as plain string {}", &result);
124+
eprintln!("... due to {}", err);
124125
}
125126
backup.into()
126127
}))
@@ -171,7 +172,7 @@ impl<'a> Interpreter<'a> {
171172

172173
let res = match self.eval::<PdlBlock>(&block.call)? {
173174
PdlBlock::Function(f) => self.run(&f.return_, context.clone()),
174-
_ => Err(Box::from("call of non-function")),
175+
_ => Err(Box::from(format!("call of non-function {:?}", &block.call))),
175176
};
176177
self.scope.pop();
177178

@@ -242,14 +243,14 @@ impl<'a> Interpreter<'a> {
242243
vm::compiler::Mode::Exec,
243244
"<embedded>".to_owned(),
244245
)
245-
.map_err(|err| {
246+
.map_err(|_err| {
246247
panic!("Syntax error in Python code");
247248
})
248249
.unwrap();
249250

250251
let _output = vm
251252
.run_code_obj(code_obj, scope.clone())
252-
.map_err(|err| {
253+
.map_err(|_err| {
253254
// TODO vm.print_exception(exc);
254255
println!("Error executing Python code");
255256
})

0 commit comments

Comments
 (0)