Skip to content

Commit

Permalink
Fix up python serialization and add ruby tests
Browse files Browse the repository at this point in the history
  • Loading branch information
imalsogreg committed Oct 31, 2024
1 parent cd46ce5 commit 2d368aa
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 12 deletions.
29 changes: 20 additions & 9 deletions engine/language_client_python/src/types/function_results.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ fn pythonize_strict(
cls_module: &Bound<'_, PyModule>,
) -> PyResult<PyObject> {
let meta = parsed.meta().clone();
dbg!(&parsed);
let py_value_without_constraints = match parsed {
BamlValueWithMeta::String(val, _) => PyResult::Ok(val.into_py(py)),
BamlValueWithMeta::Int(val, _) => Ok(val.into_py(py)),
Expand Down Expand Up @@ -138,7 +137,24 @@ fn pythonize_strict(

let properties_dict = pyo3::types::PyDict::new_bound(py);
for (key, value) in properties {
properties_dict.set_item(key, value)?;
// For each field, try to call pydantic's `model_dump` on the
// field. This is necessary in case the field is `Checked[_,_]`,
// because pydantic requires to parse such fields from json,
// rather than from a Python object. The python object is an
// untyped Dict, but python expects a typed `Checked`.
// By turning such values into `json`, we allow pydantic's
// parser to more flexibly accept input at its expected
// type.
//
// This has the side-effect of calling `model_dump` on all
// classes inheriting `BaseModel`, which probably incurs some
// performance penalty. So we should consider testing whether
// the field is a `Checked` before doing a `model_dump`.
let value_model = value.call_method0(py, "model_dump");
match value_model {
Err(_) => { properties_dict.set_item(key, value)?; }
Ok(m) => {properties_dict.set_item(key, m)?;}
}
}

let class_type = match cls_module.getattr(class_name.as_str()) {
Expand All @@ -151,8 +167,8 @@ fn pythonize_strict(
Err(_) => return Ok(properties_dict.into()),
};

let instance = class_type.call_method("model_validate", (properties_dict.clone(),), None)?;

let instance = class_type.call_method("model_validate", (properties_dict,), None)?;
Ok(instance.into())
}
BamlValueWithMeta::Null(_) => Ok(py.None()),
Expand Down Expand Up @@ -193,13 +209,8 @@ fn pythonize_strict(
let class_checked_type: Bound<'_, PyAny> = class_checked_type_constructor
.call_method1("__class_getitem__", (type_parameters_tuple,))?;

// panic!("About to call model_validate on {literal_check_names:?} {meta:?}");
if meta.len() > 1 {
panic!("{meta:?}");
}

// Validate the model with the constructed type
let checked_instance = class_checked_type.call_method("model_validate", (properties_dict,), None)?;
let checked_instance = class_checked_type.call_method("model_validate", (properties_dict.clone(),), None)?;

Ok(checked_instance.into())
}
Expand Down
2 changes: 1 addition & 1 deletion engine/language_client_ruby/Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
baml (0.63.0)
baml (0.64.0)

GEM
remote: https://rubygems.org/
Expand Down
3 changes: 2 additions & 1 deletion integ-tests/python/tests/test_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -1396,4 +1396,5 @@ async def test_block_constraints():
@pytest.mark.asyncio
async def test_nested_block_constraints():
ret = await b.MakeNestedBlockConstraint()
assert ret.nbc.checks["cross_field"].status == "failed"
print(ret)
assert ret.nbc.checks["cross_field"].status == "succeeded"
11 changes: 11 additions & 0 deletions integ-tests/ruby/test_functions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -319,4 +319,15 @@
res = b.PredictAge(name: "Greg")
assert_equal res["certainty"].checks[:unreasonably_certain].status, "failed"
end

it "uses block_level constraints" do
res = b.MakeBlockConstraint()
assert_equal res.checks[:cross_field].status, "failed"
end

it "uses nested_block_level constraints" do
res = b.MakeNestedBlockConstraint()
assert_equal res["nbc"].checks[:cross_field].status, "succeeded"
end

end
Loading

0 comments on commit 2d368aa

Please sign in to comment.