From 1d8565483bf122212ead0fca70ee144bd03ef8a7 Mon Sep 17 00:00:00 2001 From: Franck Nijhof Date: Fri, 22 May 2026 10:31:10 +0200 Subject: [PATCH] Apply web search citation stripping for GPT-5.x models in OpenAI conversation (#170956) --- .../components/openai_conversation/entity.py | 4 +- .../openai_conversation/test_conversation.py | 46 +++++++++++++++++++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/openai_conversation/entity.py b/homeassistant/components/openai_conversation/entity.py index f5474506b458..5ac94beb19a5 100644 --- a/homeassistant/components/openai_conversation/entity.py +++ b/homeassistant/components/openai_conversation/entity.py @@ -595,8 +595,8 @@ class OpenAIBaseLLMEntity(Entity): ) ) - if "reasoning" not in model_args: - # Reasoning models handle this correctly with just a prompt + if not model_args["model"].startswith("o"): + # o-series models handle this correctly with just a prompt remove_citations = True tools.append(web_search) diff --git a/tests/components/openai_conversation/test_conversation.py b/tests/components/openai_conversation/test_conversation.py index 939a525c11c2..4d79c004d658 100644 --- a/tests/components/openai_conversation/test_conversation.py +++ b/tests/components/openai_conversation/test_conversation.py @@ -660,6 +660,52 @@ async def test_web_search( assert mock_create_stream.mock_calls[1][2]["input"][1:] == snapshot +async def test_web_search_remove_citations_gpt5( + hass: HomeAssistant, + mock_config_entry: MockConfigEntry, + mock_init_component, + mock_create_stream, + mock_chat_log: MockChatLog, # noqa: F811 +) -> None: + """Test that citations are stripped for GPT-5 models with inline_citations disabled.""" + subentry = next(iter(mock_config_entry.subentries.values())) + hass.config_entries.async_update_subentry( + mock_config_entry, + subentry, + data={ + **subentry.data, + CONF_CHAT_MODEL: "gpt-5-mini", + CONF_WEB_SEARCH: True, + CONF_WEB_SEARCH_INLINE_CITATIONS: False, + }, + ) + await hass.config_entries.async_reload(mock_config_entry.entry_id) + + message = [ + "The match ended 0-2", + " ([legaseriea.it](https://www.legaseriea.it/))", + ".", + ] + mock_create_stream.return_value = [ + ( + *create_web_search_item(id="ws_A", output_index=0), + *create_message_item(id="msg_A", text=message, output_index=1), + ) + ] + + result = await conversation.async_converse( + hass, + "What was the score?", + mock_chat_log.conversation_id, + Context(), + agent_id="conversation.openai_conversation", + ) + + assert result.response.response_type == intent.IntentResponseType.ACTION_DONE + # Citation should be stripped from the response + assert result.response.speech["plain"]["speech"] == "The match ended 0-2." + + async def test_code_interpreter( hass: HomeAssistant, mock_config_entry: MockConfigEntry,