Skip to content
Closed
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Versioning: [Semantic Versioning](https://semver.org/spec/v2.0.0.html)
## [Unreleased]

### Fixed
- **v2 message handling**: Retain legacy `function_call` payloads in `dump_message` when the assistant message has empty or `None` content, so retry/reask flows no longer drop the model's prior function call. ([#2464](https://github.com/567-labs/instructor/issues/2464))
- **v2 message handling**: Preserve caller-owned message lists and nested content across request preparation and retries for OpenAI-compatible, Cohere, Mistral, OpenRouter, Writer, and xAI handlers. ([#2417](https://github.com/567-labs/instructor/issues/2417), [#2428](https://github.com/567-labs/instructor/issues/2428))
- **v2 JSON extraction**: Prefer the final complete top-level JSON value in text responses and retain every JSON object when multiple objects arrive in one streaming chunk.
- **v2 schemas**: Treat fields with Pydantic `default_factory` values as optional in generated OpenAI tool schemas.
Expand Down
6 changes: 1 addition & 5 deletions instructor/v2/core/messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,7 @@ def dump_message(message: ChatCompletionMessage) -> ChatCompletionMessageParam:
}
if hasattr(message, "tool_calls") and message.tool_calls is not None:
ret["tool_calls"] = message.model_dump()["tool_calls"]
if (
hasattr(message, "function_call")
and message.function_call is not None
and ret["content"]
):
if hasattr(message, "function_call") and message.function_call is not None:
if not isinstance(ret["content"], str):
response_message = ""
for content_message in ret["content"]:
Expand Down
12 changes: 12 additions & 0 deletions tests/coverage/test_core_helpers_coverage.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,18 @@ def test_dump_message_appends_function_call_to_text_content() -> None:
)


def test_dump_message_retains_function_call_when_content_is_empty() -> None:
message = ChatCompletionMessage(
role="assistant",
content=None,
function_call=FunctionCall(name="lookup", arguments='{"id":7}'),
)

result = dump_message(message)

assert result["content"] == json.dumps({"arguments": '{"id":7}', "name": "lookup"})


def test_merge_consecutive_messages_checks_tail_for_non_string_content() -> None:
messages: list[dict[str, Any]] = [
{"role": "user", "content": f"line {index}"} for index in range(10)
Expand Down