From fa6c6350087b85fea4bd45ac3d172c46af463e73 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Thu, 15 Oct 2026 20:02:51 -0400 Subject: [PATCH] fix(dspy): reuse serialized image-free models --- py/src/braintrust/integrations/dspy/test_dspy.py | 8 +++++--- py/src/braintrust/integrations/dspy/tracing.py | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/py/src/braintrust/integrations/dspy/test_dspy.py b/py/src/braintrust/integrations/dspy/test_dspy.py index 79dffea7..2916e7da 100644 --- a/py/src/braintrust/integrations/dspy/test_dspy.py +++ b/py/src/braintrust/integrations/dspy/test_dspy.py @@ -56,10 +56,12 @@ def redact_image(self, image): @pytest.mark.parametrize("url", ["https://example.com/page.png", "data:image/png;base64,not base64!"]) def test_dspy_image_conversion_preserves_unmaterialized_images(url): image = dspy.Image(url=url) - assert _process_images(image) is image - assert _process_images({"image": image, "url": url}) == {"image": image, "url": url} + assert _process_images({"image": image, "url": url}) == { + "image": image.model_dump(exclude_none=True), + "url": url, + } model = RootModel[list[dspy.Image]]([image]) - assert _process_images(model) is model + assert _process_images(model) == model.model_dump(exclude_none=True) @pytest.mark.vcr( diff --git a/py/src/braintrust/integrations/dspy/tracing.py b/py/src/braintrust/integrations/dspy/tracing.py index dae8fb84..ecdf1a50 100644 --- a/py/src/braintrust/integrations/dspy/tracing.py +++ b/py/src/braintrust/integrations/dspy/tracing.py @@ -90,7 +90,7 @@ def _process_images_impl(value: Any) -> Any: serialized = value.model_dump(exclude_none=True) converted_model = _process_images(serialized) if converted_model is serialized: - return value + return serialized # DSPy 2.6 serializes Image as {"url": ...}; later versions use the # reserved prompt wrapper handled above. Normalize only this SDK type. if type(value) is Image and isinstance(converted_model, dict) and set(converted_model) == {"url"}: