From 9fa9fdc1352c392ccaaf41668c0d2366d6d8fd96 Mon Sep 17 00:00:00 2001 From: Carson Date: Tue, 4 Nov 2025 17:46:08 -0600 Subject: [PATCH 1/2] Close #191: send structured data info back to the LLM --- chatlas/_provider_anthropic.py | 3 ++- chatlas/_provider_google.py | 3 ++- chatlas/_provider_openai_completions.py | 8 ++++---- chatlas/_provider_snowflake.py | 3 ++- tests/conftest.py | 7 +++++++ 5 files changed, 17 insertions(+), 7 deletions(-) diff --git a/chatlas/_provider_anthropic.py b/chatlas/_provider_anthropic.py index e02a6e02..7b1ab427 100644 --- a/chatlas/_provider_anthropic.py +++ b/chatlas/_provider_anthropic.py @@ -526,7 +526,8 @@ def _as_content_block(content: Content) -> "ContentBlockParam": if isinstance(content, ContentText): return {"text": content.text, "type": "text"} elif isinstance(content, ContentJson): - return {"text": "", "type": "text"} + text = orjson.dumps(content.value).decode("utf-8") + return {"text": text, "type": "text"} elif isinstance(content, ContentPDF): return { "type": "document", diff --git a/chatlas/_provider_google.py b/chatlas/_provider_google.py index 09a04d8b..eea999ee 100644 --- a/chatlas/_provider_google.py +++ b/chatlas/_provider_google.py @@ -442,7 +442,8 @@ def _as_part_type(self, content: Content) -> "Part": if isinstance(content, ContentText): return Part.from_text(text=content.text) elif isinstance(content, ContentJson): - return Part.from_text(text="") + text = orjson.dumps(content.value).decode("utf-8") + return Part.from_text(text=text) elif isinstance(content, ContentPDF): from google.genai.types import Blob diff --git a/chatlas/_provider_openai_completions.py b/chatlas/_provider_openai_completions.py index a47fad6a..99730a33 100644 --- a/chatlas/_provider_openai_completions.py +++ b/chatlas/_provider_openai_completions.py @@ -245,9 +245,8 @@ def _turns_as_inputs(turns: list[Turn]) -> list["ChatCompletionMessageParam"]: if isinstance(x, ContentText): content_parts.append({"type": "text", "text": x.text}) elif isinstance(x, ContentJson): - content_parts.append( - {"type": "text", "text": ""} - ) + text = orjson.dumps(x.value).decode("utf-8") + content_parts.append({"type": "text", "text": text}) elif isinstance(x, ContentToolRequest): tool_calls.append( { @@ -286,7 +285,8 @@ def _turns_as_inputs(turns: list[Turn]) -> list["ChatCompletionMessageParam"]: if isinstance(x, ContentText): contents.append({"type": "text", "text": x.text}) elif isinstance(x, ContentJson): - contents.append({"type": "text", "text": ""}) + text = orjson.dumps(x.value).decode("utf-8") + contents.append({"type": "text", "text": text}) elif isinstance(x, ContentPDF): contents.append( { diff --git a/chatlas/_provider_snowflake.py b/chatlas/_provider_snowflake.py index 3eb98fac..7412028c 100644 --- a/chatlas/_provider_snowflake.py +++ b/chatlas/_provider_snowflake.py @@ -511,7 +511,8 @@ def _as_request_messages(self, turns: list[Turn]): } ) elif isinstance(x, ContentJson): - req.content = req.content or "" + text = orjson.dumps(x.value).decode("utf-8") + req.content = req.content or text res.append(req) return res diff --git a/tests/conftest.py b/tests/conftest.py index 5b95c71a..d41649fd 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -221,6 +221,13 @@ def assert_data_extraction(chat_fun: ChatFun): assert data2.author == "Hadley Wickham" assert data2.title.lower() == "apples are tasty" + class Person(BaseModel): + name: str + age: int + data = chat.chat_structured("Generate the name and age of a random person.", data_model=Person) + response = chat.chat("What is the name of the person?") + assert data.name in str(response) + def assert_images_inline(chat_fun: ChatFun, stream: bool = True): img = Image.new("RGB", (60, 30), color="red") From b56eb634c88eebb12c4a30dbb04790b6d9a54cfc Mon Sep 17 00:00:00 2001 From: Carson Date: Wed, 5 Nov 2025 09:19:29 -0600 Subject: [PATCH 2/2] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e522ead5..3ca68358 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Bug fixes * `.set_model_params()` now works correctly for `.*_async()` methods. (#198) +* `.chat_structured()` results are now included correctly into the multi-turn conversation history. (#203) ## [0.13.2] - 2025-10-02