From 88d5f3edcc50d84f57ae6f7ab1543a680e6f9ce5 Mon Sep 17 00:00:00 2001 From: ccurme Date: Thu, 26 Jun 2025 13:41:43 -0400 Subject: [PATCH] openai[patch]: allow specification of output format for Responses API (#31686) --- .../tests/unit_tests/chat_models/test_base.py | 1 + .../langchain_openai/chat_models/_compat.py | 28 ++- .../langchain_openai/chat_models/base.py | 62 ++++++- .../cassettes/test_mcp_builtin_zdr.yaml.gz | Bin 0 -> 33550 bytes .../tests/cassettes/test_reasoning.yaml.gz | Bin 0 -> 3805 bytes .../test_stream_reasoning_summary.yaml.gz | Bin 0 -> 18429 bytes .../tests/cassettes/test_web_search.yaml.gz | Bin 18002 -> 24336 bytes .../chat_models/test_responses_api.py | 70 ++++++-- .../__snapshots__/test_azure_standard.ambr | 1 + .../__snapshots__/test_base_standard.ambr | 1 + .../test_responses_standard.ambr | 1 + .../tests/unit_tests/chat_models/test_base.py | 167 +++++++++++++++++- .../chat_models/test_responses_stream.py | 31 +++- .../test_chat_models_standard.ambr | 1 + 14 files changed, 328 insertions(+), 35 deletions(-) create mode 100644 libs/partners/openai/tests/cassettes/test_mcp_builtin_zdr.yaml.gz create mode 100644 libs/partners/openai/tests/cassettes/test_reasoning.yaml.gz create mode 100644 libs/partners/openai/tests/cassettes/test_stream_reasoning_summary.yaml.gz diff --git a/libs/langchain/tests/unit_tests/chat_models/test_base.py b/libs/langchain/tests/unit_tests/chat_models/test_base.py index 55c210dba09..4d314936033 100644 --- a/libs/langchain/tests/unit_tests/chat_models/test_base.py +++ b/libs/langchain/tests/unit_tests/chat_models/test_base.py @@ -113,6 +113,7 @@ def test_configurable() -> None: "openai_api_base": None, "openai_organization": None, "openai_proxy": None, + "output_version": "v0", "request_timeout": None, "max_retries": None, "presence_penalty": None, diff --git a/libs/partners/openai/langchain_openai/chat_models/_compat.py b/libs/partners/openai/langchain_openai/chat_models/_compat.py index a0db5df9b4c..68fa2c310cb 100644 --- a/libs/partners/openai/langchain_openai/chat_models/_compat.py +++ b/libs/partners/openai/langchain_openai/chat_models/_compat.py @@ -128,6 +128,8 @@ def _convert_to_v03_ai_message( else: new_content.append(block) message.content = new_content + if isinstance(message.id, str) and message.id.startswith("resp_"): + message.id = None else: pass @@ -137,13 +139,29 @@ def _convert_to_v03_ai_message( def _convert_from_v03_ai_message(message: AIMessage) -> AIMessage: """Convert an old-style v0.3 AIMessage into the new content-block format.""" # Only update ChatOpenAI v0.3 AIMessages - if not ( + # TODO: structure provenance into AIMessage + is_chatopenai_v03 = ( isinstance(message.content, list) and all(isinstance(b, dict) for b in message.content) - ) or not any( - item in message.additional_kwargs - for item in ["reasoning", "tool_outputs", "refusal", _FUNCTION_CALL_IDS_MAP_KEY] - ): + ) and ( + any( + item in message.additional_kwargs + for item in [ + "reasoning", + "tool_outputs", + "refusal", + _FUNCTION_CALL_IDS_MAP_KEY, + ] + ) + or ( + isinstance(message.id, str) + and message.id.startswith("msg_") + and (response_id := message.response_metadata.get("id")) + and isinstance(response_id, str) + and response_id.startswith("resp_") + ) + ) + if not is_chatopenai_v03: return message content_order = [ diff --git a/libs/partners/openai/langchain_openai/chat_models/base.py b/libs/partners/openai/langchain_openai/chat_models/base.py index d2585b37fac..9b6f66aa831 100644 --- a/libs/partners/openai/langchain_openai/chat_models/base.py +++ b/libs/partners/openai/langchain_openai/chat_models/base.py @@ -649,6 +649,25 @@ class BaseChatOpenAI(BaseChatModel): .. versionadded:: 0.3.9 """ + output_version: Literal["v0", "responses/v1"] = "v0" + """Version of AIMessage output format to use. + + This field is used to roll-out new output formats for chat model AIMessages + in a backwards-compatible way. + + Supported values: + + - ``"v0"``: AIMessage format as of langchain-openai 0.3.x. + - ``"responses/v1"``: Formats Responses API output + items into AIMessage content blocks. + + Currently only impacts the Responses API. ``output_version="responses/v1"`` is + recommended. + + .. versionadded:: 0.3.25 + + """ + model_config = ConfigDict(populate_by_name=True) @model_validator(mode="before") @@ -903,6 +922,7 @@ class BaseChatOpenAI(BaseChatModel): schema=original_schema_obj, metadata=metadata, has_reasoning=has_reasoning, + output_version=self.output_version, ) if generation_chunk: if run_manager: @@ -957,6 +977,7 @@ class BaseChatOpenAI(BaseChatModel): schema=original_schema_obj, metadata=metadata, has_reasoning=has_reasoning, + output_version=self.output_version, ) if generation_chunk: if run_manager: @@ -1096,7 +1117,10 @@ class BaseChatOpenAI(BaseChatModel): else: response = self.root_client.responses.create(**payload) return _construct_lc_result_from_responses_api( - response, schema=original_schema_obj, metadata=generation_info + response, + schema=original_schema_obj, + metadata=generation_info, + output_version=self.output_version, ) elif self.include_response_headers: raw_response = self.client.with_raw_response.create(**payload) @@ -1109,6 +1133,8 @@ class BaseChatOpenAI(BaseChatModel): def _use_responses_api(self, payload: dict) -> bool: if isinstance(self.use_responses_api, bool): return self.use_responses_api + elif self.output_version == "responses/v1": + return True elif self.include is not None: return True elif self.reasoning is not None: @@ -1327,7 +1353,10 @@ class BaseChatOpenAI(BaseChatModel): else: response = await self.root_async_client.responses.create(**payload) return _construct_lc_result_from_responses_api( - response, schema=original_schema_obj, metadata=generation_info + response, + schema=original_schema_obj, + metadata=generation_info, + output_version=self.output_version, ) elif self.include_response_headers: raw_response = await self.async_client.with_raw_response.create(**payload) @@ -3540,6 +3569,7 @@ def _construct_lc_result_from_responses_api( response: Response, schema: Optional[type[_BM]] = None, metadata: Optional[dict] = None, + output_version: Literal["v0", "responses/v1"] = "v0", ) -> ChatResult: """Construct ChatResponse from OpenAI Response API response.""" if response.error: @@ -3676,7 +3706,10 @@ def _construct_lc_result_from_responses_api( tool_calls=tool_calls, invalid_tool_calls=invalid_tool_calls, ) - message = _convert_to_v03_ai_message(message) + if output_version == "v0": + message = _convert_to_v03_ai_message(message) + else: + pass return ChatResult(generations=[ChatGeneration(message=message)]) @@ -3688,6 +3721,7 @@ def _convert_responses_chunk_to_generation_chunk( schema: Optional[type[_BM]] = None, metadata: Optional[dict] = None, has_reasoning: bool = False, + output_version: Literal["v0", "responses/v1"] = "v0", ) -> tuple[int, int, int, Optional[ChatGenerationChunk]]: def _advance(output_idx: int, sub_idx: Optional[int] = None) -> None: """Advance indexes tracked during streaming. @@ -3756,12 +3790,15 @@ def _convert_responses_chunk_to_generation_chunk( elif chunk.type == "response.output_text.done": content.append({"id": chunk.item_id, "index": current_index}) elif chunk.type == "response.created": - response_metadata["id"] = chunk.response.id + id = chunk.response.id + response_metadata["id"] = chunk.response.id # Backwards compatibility elif chunk.type == "response.completed": msg = cast( AIMessage, ( - _construct_lc_result_from_responses_api(chunk.response, schema=schema) + _construct_lc_result_from_responses_api( + chunk.response, schema=schema, output_version=output_version + ) .generations[0] .message ), @@ -3773,7 +3810,10 @@ def _convert_responses_chunk_to_generation_chunk( k: v for k, v in msg.response_metadata.items() if k != "id" } elif chunk.type == "response.output_item.added" and chunk.item.type == "message": - id = chunk.item.id + if output_version == "v0": + id = chunk.item.id + else: + pass elif ( chunk.type == "response.output_item.added" and chunk.item.type == "function_call" @@ -3868,9 +3908,13 @@ def _convert_responses_chunk_to_generation_chunk( additional_kwargs=additional_kwargs, id=id, ) - message = cast( - AIMessageChunk, _convert_to_v03_ai_message(message, has_reasoning=has_reasoning) - ) + if output_version == "v0": + message = cast( + AIMessageChunk, + _convert_to_v03_ai_message(message, has_reasoning=has_reasoning), + ) + else: + pass return ( current_index, current_output_index, diff --git a/libs/partners/openai/tests/cassettes/test_mcp_builtin_zdr.yaml.gz b/libs/partners/openai/tests/cassettes/test_mcp_builtin_zdr.yaml.gz new file mode 100644 index 0000000000000000000000000000000000000000..f6cf24dee10d64096c2be4a875e89be0eef93399 GIT binary patch literal 33550 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 elVARhL(%?|_w&bp{O-@9Wp! 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 b^EWo{+gsMh$J5t--17W?!wOHFa-RYKQ%M!< literal 0 HcmV?d00001 diff --git a/libs/partners/openai/tests/cassettes/test_web_search.yaml.gz b/libs/partners/openai/tests/cassettes/test_web_search.yaml.gz index d63dc1f166876c026a81a5d2c2d3d821614d1431..e99f1c2e13a14928c0b2b025eab331ac4ec326f3 100644 GIT binary patch literal 24336 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 literal 18002 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 UO+Ue=KL%|2e+3KGd8e}h0CTdZT>t<8 diff --git a/libs/partners/openai/tests/integration_tests/chat_models/test_responses_api.py b/libs/partners/openai/tests/integration_tests/chat_models/test_responses_api.py index 622c83f0f7f..0e23d0e3f06 100644 --- a/libs/partners/openai/tests/integration_tests/chat_models/test_responses_api.py +++ b/libs/partners/openai/tests/integration_tests/chat_models/test_responses_api.py @@ -2,7 +2,7 @@ import json import os -from typing import Annotated, Any, Optional, cast +from typing import Annotated, Any, Literal, Optional, cast import openai import pytest @@ -50,15 +50,11 @@ def _check_response(response: Optional[BaseMessage]) -> None: assert response.usage_metadata["total_tokens"] > 0 assert response.response_metadata["model_name"] assert response.response_metadata["service_tier"] - for tool_output in response.additional_kwargs["tool_outputs"]: - assert tool_output["id"] - assert tool_output["status"] - assert tool_output["type"] @pytest.mark.vcr def test_web_search() -> None: - llm = ChatOpenAI(model=MODEL_NAME) + llm = ChatOpenAI(model=MODEL_NAME, output_version="responses/v1") first_response = llm.invoke( "What was a positive news story from today?", tools=[{"type": "web_search_preview"}], @@ -111,6 +107,11 @@ def test_web_search() -> None: ) _check_response(response) + for msg in [first_response, full, response]: + assert isinstance(msg, AIMessage) + block_types = [block["type"] for block in msg.content] # type: ignore[index] + assert block_types == ["web_search_call", "text"] + @pytest.mark.flaky(retries=3, delay=1) async def test_web_search_async() -> None: @@ -133,6 +134,12 @@ async def test_web_search_async() -> None: assert isinstance(full, AIMessageChunk) _check_response(full) + for msg in [response, full]: + assert msg.additional_kwargs["tool_outputs"] + assert len(msg.additional_kwargs["tool_outputs"]) == 1 + tool_output = msg.additional_kwargs["tool_outputs"][0] + assert tool_output["type"] == "web_search_call" + @pytest.mark.flaky(retries=3, delay=1) def test_function_calling() -> None: @@ -288,20 +295,32 @@ def test_function_calling_and_structured_output() -> None: assert set(ai_msg.tool_calls[0]["args"]) == {"x", "y"} -def test_reasoning() -> None: - llm = ChatOpenAI(model="o3-mini", use_responses_api=True) +@pytest.mark.default_cassette("test_reasoning.yaml.gz") +@pytest.mark.vcr +@pytest.mark.parametrize("output_version", ["v0", "responses/v1"]) +def test_reasoning(output_version: Literal["v0", "responses/v1"]) -> None: + llm = ChatOpenAI( + model="o4-mini", use_responses_api=True, output_version=output_version + ) response = llm.invoke("Hello", reasoning={"effort": "low"}) assert isinstance(response, AIMessage) - assert response.additional_kwargs["reasoning"] # Test init params + streaming - llm = ChatOpenAI(model="o3-mini", reasoning_effort="low", use_responses_api=True) + llm = ChatOpenAI( + model="o4-mini", reasoning={"effort": "low"}, output_version=output_version + ) full: Optional[BaseMessageChunk] = None for chunk in llm.stream("Hello"): assert isinstance(chunk, AIMessageChunk) full = chunk if full is None else full + chunk assert isinstance(full, AIMessage) - assert full.additional_kwargs["reasoning"] + + for msg in [response, full]: + if output_version == "v0": + assert msg.additional_kwargs["reasoning"] + else: + block_types = [block["type"] for block in msg.content] + assert block_types == ["reasoning", "text"] def test_stateful_api() -> None: @@ -355,20 +374,37 @@ def test_file_search() -> None: _check_response(full) -def test_stream_reasoning_summary() -> None: +@pytest.mark.default_cassette("test_stream_reasoning_summary.yaml.gz") +@pytest.mark.vcr +@pytest.mark.parametrize("output_version", ["v0", "responses/v1"]) +def test_stream_reasoning_summary( + output_version: Literal["v0", "responses/v1"], +) -> None: llm = ChatOpenAI( model="o4-mini", # Routes to Responses API if `reasoning` is set. reasoning={"effort": "medium", "summary": "auto"}, + output_version=output_version, ) - message_1 = {"role": "user", "content": "What is 3^3?"} + message_1 = { + "role": "user", + "content": "What was the third tallest buliding in the year 2000?", + } response_1: Optional[BaseMessageChunk] = None for chunk in llm.stream([message_1]): assert isinstance(chunk, AIMessageChunk) response_1 = chunk if response_1 is None else response_1 + chunk assert isinstance(response_1, AIMessageChunk) - reasoning = response_1.additional_kwargs["reasoning"] - assert set(reasoning.keys()) == {"id", "type", "summary"} + if output_version == "v0": + reasoning = response_1.additional_kwargs["reasoning"] + assert set(reasoning.keys()) == {"id", "type", "summary"} + else: + reasoning = next( + block + for block in response_1.content + if block["type"] == "reasoning" # type: ignore[index] + ) + assert set(reasoning.keys()) == {"id", "type", "summary", "index"} summary = reasoning["summary"] assert isinstance(summary, list) for block in summary: @@ -462,11 +498,11 @@ def test_mcp_builtin() -> None: ) -@pytest.mark.skip +@pytest.mark.vcr def test_mcp_builtin_zdr() -> None: llm = ChatOpenAI( model="o4-mini", - use_responses_api=True, + output_version="responses/v1", store=False, include=["reasoning.encrypted_content"], ) diff --git a/libs/partners/openai/tests/unit_tests/chat_models/__snapshots__/test_azure_standard.ambr b/libs/partners/openai/tests/unit_tests/chat_models/__snapshots__/test_azure_standard.ambr index 2060512958a..ddadd6fc09b 100644 --- a/libs/partners/openai/tests/unit_tests/chat_models/__snapshots__/test_azure_standard.ambr +++ b/libs/partners/openai/tests/unit_tests/chat_models/__snapshots__/test_azure_standard.ambr @@ -24,6 +24,7 @@ }), 'openai_api_type': 'azure', 'openai_api_version': '2021-10-01', + 'output_version': 'v0', 'request_timeout': 60.0, 'stop': list([ ]), diff --git a/libs/partners/openai/tests/unit_tests/chat_models/__snapshots__/test_base_standard.ambr b/libs/partners/openai/tests/unit_tests/chat_models/__snapshots__/test_base_standard.ambr index e7307c6158f..1a74f4978a7 100644 --- a/libs/partners/openai/tests/unit_tests/chat_models/__snapshots__/test_base_standard.ambr +++ b/libs/partners/openai/tests/unit_tests/chat_models/__snapshots__/test_base_standard.ambr @@ -18,6 +18,7 @@ 'lc': 1, 'type': 'secret', }), + 'output_version': 'v0', 'request_timeout': 60.0, 'stop': list([ ]), diff --git a/libs/partners/openai/tests/unit_tests/chat_models/__snapshots__/test_responses_standard.ambr b/libs/partners/openai/tests/unit_tests/chat_models/__snapshots__/test_responses_standard.ambr index 88a49a27502..10d1355af4e 100644 --- a/libs/partners/openai/tests/unit_tests/chat_models/__snapshots__/test_responses_standard.ambr +++ b/libs/partners/openai/tests/unit_tests/chat_models/__snapshots__/test_responses_standard.ambr @@ -18,6 +18,7 @@ 'lc': 1, 'type': 'secret', }), + 'output_version': 'v0', 'request_timeout': 60.0, 'stop': list([ ]), diff --git a/libs/partners/openai/tests/unit_tests/chat_models/test_base.py b/libs/partners/openai/tests/unit_tests/chat_models/test_base.py index 37eaf500e74..3bd822187c4 100644 --- a/libs/partners/openai/tests/unit_tests/chat_models/test_base.py +++ b/libs/partners/openai/tests/unit_tests/chat_models/test_base.py @@ -1192,6 +1192,7 @@ def test__construct_lc_result_from_responses_api_basic_text_response() -> None: ), ) + # v0 result = _construct_lc_result_from_responses_api(response) assert isinstance(result, ChatResult) @@ -1209,6 +1210,16 @@ def test__construct_lc_result_from_responses_api_basic_text_response() -> None: assert result.generations[0].message.response_metadata["id"] == "resp_123" assert result.generations[0].message.response_metadata["model_name"] == "gpt-4o" + # responses/v1 + result = _construct_lc_result_from_responses_api( + response, output_version="responses/v1" + ) + assert result.generations[0].message.content == [ + {"type": "text", "text": "Hello, world!", "annotations": [], "id": "msg_123"} + ] + assert result.generations[0].message.id == "resp_123" + assert result.generations[0].message.response_metadata["id"] == "resp_123" + def test__construct_lc_result_from_responses_api_multiple_text_blocks() -> None: """Test a response with multiple text blocks.""" @@ -1284,6 +1295,7 @@ def test__construct_lc_result_from_responses_api_multiple_messages() -> None: ], ) + # v0 result = _construct_lc_result_from_responses_api(response) assert result.generations[0].message.content == [ @@ -1297,6 +1309,23 @@ def test__construct_lc_result_from_responses_api_multiple_messages() -> None: "id": "rs_123", } } + assert result.generations[0].message.id == "msg_234" + + # responses/v1 + result = _construct_lc_result_from_responses_api( + response, output_version="responses/v1" + ) + + assert result.generations[0].message.content == [ + {"type": "text", "text": "foo", "annotations": [], "id": "msg_123"}, + { + "type": "reasoning", + "summary": [{"type": "summary_text", "text": "reasoning foo"}], + "id": "rs_123", + }, + {"type": "text", "text": "bar", "annotations": [], "id": "msg_234"}, + ] + assert result.generations[0].message.id == "resp_123" def test__construct_lc_result_from_responses_api_refusal_response() -> None: @@ -1324,12 +1353,25 @@ def test__construct_lc_result_from_responses_api_refusal_response() -> None: ], ) + # v0 result = _construct_lc_result_from_responses_api(response) assert result.generations[0].message.additional_kwargs["refusal"] == ( "I cannot assist with that request." ) + # responses/v1 + result = _construct_lc_result_from_responses_api( + response, output_version="responses/v1" + ) + assert result.generations[0].message.content == [ + { + "type": "refusal", + "refusal": "I cannot assist with that request.", + "id": "msg_123", + } + ] + def test__construct_lc_result_from_responses_api_function_call_valid_json() -> None: """Test a response with a valid function call.""" @@ -1352,6 +1394,7 @@ def test__construct_lc_result_from_responses_api_function_call_valid_json() -> N ], ) + # v0 result = _construct_lc_result_from_responses_api(response) msg: AIMessage = cast(AIMessage, result.generations[0].message) @@ -1368,6 +1411,22 @@ def test__construct_lc_result_from_responses_api_function_call_valid_json() -> N == "func_123" ) + # responses/v1 + result = _construct_lc_result_from_responses_api( + response, output_version="responses/v1" + ) + msg = cast(AIMessage, result.generations[0].message) + assert msg.tool_calls + assert msg.content == [ + { + "type": "function_call", + "id": "func_123", + "name": "get_weather", + "arguments": '{"location": "New York", "unit": "celsius"}', + "call_id": "call_123", + } + ] + def test__construct_lc_result_from_responses_api_function_call_invalid_json() -> None: """Test a response with an invalid JSON function call.""" @@ -1444,6 +1503,7 @@ def test__construct_lc_result_from_responses_api_complex_response() -> None: user="user_123", ) + # v0 result = _construct_lc_result_from_responses_api(response) # Check message content @@ -1472,6 +1532,28 @@ def test__construct_lc_result_from_responses_api_complex_response() -> None: assert result.generations[0].message.response_metadata["status"] == "completed" assert result.generations[0].message.response_metadata["user"] == "user_123" + # responses/v1 + result = _construct_lc_result_from_responses_api( + response, output_version="responses/v1" + ) + msg = cast(AIMessage, result.generations[0].message) + assert msg.response_metadata["metadata"] == {"key1": "value1", "key2": "value2"} + assert msg.content == [ + { + "type": "text", + "text": "Here's the information you requested:", + "annotations": [], + "id": "msg_123", + }, + { + "type": "function_call", + "id": "func_123", + "call_id": "call_123", + "name": "get_weather", + "arguments": '{"location": "New York"}', + }, + ] + def test__construct_lc_result_from_responses_api_no_usage_metadata() -> None: """Test a response without usage metadata.""" @@ -1525,6 +1607,7 @@ def test__construct_lc_result_from_responses_api_web_search_response() -> None: ], ) + # v0 result = _construct_lc_result_from_responses_api(response) assert "tool_outputs" in result.generations[0].message.additional_kwargs @@ -1542,6 +1625,14 @@ def test__construct_lc_result_from_responses_api_web_search_response() -> None: == "completed" ) + # responses/v1 + result = _construct_lc_result_from_responses_api( + response, output_version="responses/v1" + ) + assert result.generations[0].message.content == [ + {"type": "web_search_call", "id": "websearch_123", "status": "completed"} + ] + def test__construct_lc_result_from_responses_api_file_search_response() -> None: """Test a response with file search output.""" @@ -1572,6 +1663,7 @@ def test__construct_lc_result_from_responses_api_file_search_response() -> None: ], ) + # v0 result = _construct_lc_result_from_responses_api(response) assert "tool_outputs" in result.generations[0].message.additional_kwargs @@ -1612,6 +1704,28 @@ def test__construct_lc_result_from_responses_api_file_search_response() -> None: == 0.95 ) + # responses/v1 + result = _construct_lc_result_from_responses_api( + response, output_version="responses/v1" + ) + assert result.generations[0].message.content == [ + { + "type": "file_search_call", + "id": "filesearch_123", + "status": "completed", + "queries": ["python code", "langchain"], + "results": [ + { + "file_id": "file_123", + "filename": "example.py", + "score": 0.95, + "text": "def hello_world() -> None:\n print('Hello, world!')", + "attributes": {"language": "python", "size": 42}, + } + ], + } + ] + def test__construct_lc_result_from_responses_api_mixed_search_responses() -> None: """Test a response with both web search and file search outputs.""" @@ -1656,6 +1770,7 @@ def test__construct_lc_result_from_responses_api_mixed_search_responses() -> Non ], ) + # v0 result = _construct_lc_result_from_responses_api(response) # Check message content @@ -1686,6 +1801,34 @@ def test__construct_lc_result_from_responses_api_mixed_search_responses() -> Non assert file_search["queries"] == ["python code"] assert file_search["results"][0]["filename"] == "example.py" + # responses/v1 + result = _construct_lc_result_from_responses_api( + response, output_version="responses/v1" + ) + assert result.generations[0].message.content == [ + { + "type": "text", + "text": "Here's what I found:", + "annotations": [], + "id": "msg_123", + }, + {"type": "web_search_call", "id": "websearch_123", "status": "completed"}, + { + "type": "file_search_call", + "id": "filesearch_123", + "queries": ["python code"], + "results": [ + { + "file_id": "file_123", + "filename": "example.py", + "score": 0.95, + "text": "def hello_world() -> None:\n print('Hello, world!')", + } + ], + "status": "completed", + }, + ] + def test__construct_responses_api_input_human_message_with_text_blocks_conversion() -> ( None @@ -1706,7 +1849,29 @@ def test__construct_responses_api_input_human_message_with_text_blocks_conversio def test__construct_responses_api_input_multiple_message_components() -> None: """Test that human messages with text blocks are properly converted.""" - messages: list = [ + # v0 + messages = [ + AIMessage( + content=[{"type": "text", "text": "foo"}, {"type": "text", "text": "bar"}], + id="msg_123", + response_metadata={"id": "resp_123"}, + ) + ] + result = _construct_responses_api_input(messages) + assert result == [ + { + "type": "message", + "role": "assistant", + "content": [ + {"type": "output_text", "text": "foo", "annotations": []}, + {"type": "output_text", "text": "bar", "annotations": []}, + ], + "id": "msg_123", + } + ] + + # responses/v1 + messages = [ AIMessage( content=[ {"type": "text", "text": "foo", "id": "msg_123"}, diff --git a/libs/partners/openai/tests/unit_tests/chat_models/test_responses_stream.py b/libs/partners/openai/tests/unit_tests/chat_models/test_responses_stream.py index 6e91ff9a3fd..370adcd1f1a 100644 --- a/libs/partners/openai/tests/unit_tests/chat_models/test_responses_stream.py +++ b/libs/partners/openai/tests/unit_tests/chat_models/test_responses_stream.py @@ -1,7 +1,6 @@ from typing import Any, Optional from unittest.mock import MagicMock, patch -import pytest from langchain_core.messages import AIMessageChunk, BaseMessageChunk from openai.types.responses import ( ResponseCompletedEvent, @@ -601,9 +600,18 @@ responses_stream = [ ] -@pytest.mark.xfail(reason="Will be fixed with output format flags.") +def _strip_none(obj: Any) -> Any: + """Recursively strip None values from dictionaries and lists.""" + if isinstance(obj, dict): + return {k: _strip_none(v) for k, v in obj.items() if v is not None} + elif isinstance(obj, list): + return [_strip_none(v) for v in obj] + else: + return obj + + def test_responses_stream() -> None: - llm = ChatOpenAI(model="o4-mini", use_responses_api=True) + llm = ChatOpenAI(model="o4-mini", output_version="responses/v1") mock_client = MagicMock() def mock_create(*args: Any, **kwargs: Any) -> MockSyncContextManager: @@ -644,3 +652,20 @@ def test_responses_stream() -> None: ] assert full.content == expected_content assert full.additional_kwargs == {} + assert full.id == "resp_123" + + # Test reconstruction + payload = llm._get_request_payload([full]) + completed = [ + item + for item in responses_stream + if item.type == "response.completed" # type: ignore[attr-defined] + ] + assert len(completed) == 1 + response = completed[0].response # type: ignore[attr-defined] + + assert len(response.output) == len(payload["input"]) + for idx, item in enumerate(response.output): + dumped = _strip_none(item.model_dump()) + _ = dumped.pop("status", None) + assert dumped == payload["input"][idx] diff --git a/libs/partners/xai/tests/unit_tests/__snapshots__/test_chat_models_standard.ambr b/libs/partners/xai/tests/unit_tests/__snapshots__/test_chat_models_standard.ambr index 4cd1261555c..e61b99508aa 100644 --- a/libs/partners/xai/tests/unit_tests/__snapshots__/test_chat_models_standard.ambr +++ b/libs/partners/xai/tests/unit_tests/__snapshots__/test_chat_models_standard.ambr @@ -10,6 +10,7 @@ 'max_retries': 2, 'max_tokens': 100, 'model_name': 'grok-beta', + 'output_version': 'v0', 'request_timeout': 60.0, 'stop': list([ ]),