From 195919b5fbd16f36bd817a5445d56ee0a44561f3 Mon Sep 17 00:00:00 2001 From: Denis Shulyaka Date: Fri, 28 Mar 2025 03:05:54 +0300 Subject: [PATCH] Add PDF support for `openai_conversation.generate_content` service (#141588) Add PDF support for openai_conversation.generate_content service --- .../openai_conversation/__init__.py | 32 ++++++++++++------- .../openai_conversation/strings.json | 2 +- .../openai_conversation/test_init.py | 25 +++++++++++++-- 3 files changed, 45 insertions(+), 14 deletions(-) diff --git a/homeassistant/components/openai_conversation/__init__.py b/homeassistant/components/openai_conversation/__init__.py index fcf6ab298dc..276f5ddea3b 100644 --- a/homeassistant/components/openai_conversation/__init__.py +++ b/homeassistant/components/openai_conversation/__init__.py @@ -11,6 +11,7 @@ from openai.types.images_response import ImagesResponse from openai.types.responses import ( EasyInputMessageParam, Response, + ResponseInputFileParam, ResponseInputImageParam, ResponseInputMessageContentListParam, ResponseInputParam, @@ -132,19 +133,28 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: if not Path(filename).exists(): raise HomeAssistantError(f"`{filename}` does not exist") mime_type, base64_file = encode_file(filename) - if "image/" not in mime_type: + if "image/" in mime_type: + content.append( + ResponseInputImageParam( + type="input_image", + file_id=filename, + image_url=f"data:{mime_type};base64,{base64_file}", + detail="auto", + ) + ) + elif "application/pdf" in mime_type: + content.append( + ResponseInputFileParam( + type="input_file", + filename=filename, + file_data=f"data:{mime_type};base64,{base64_file}", + ) + ) + else: raise HomeAssistantError( - "Only images are supported by the OpenAI API," - f"`{filename}` is not an image file" + "Only images and PDF are supported by the OpenAI API," + f"`{filename}` is not an image file or PDF" ) - content.append( - ResponseInputImageParam( - type="input_image", - file_id=filename, - image_url=f"data:{mime_type};base64,{base64_file}", - detail="auto", - ) - ) if CONF_FILENAMES in call.data: await hass.async_add_executor_job(append_files_to_content) diff --git a/homeassistant/components/openai_conversation/strings.json b/homeassistant/components/openai_conversation/strings.json index a373ec448d7..91c1c475bd6 100644 --- a/homeassistant/components/openai_conversation/strings.json +++ b/homeassistant/components/openai_conversation/strings.json @@ -89,7 +89,7 @@ }, "generate_content": { "name": "Generate content", - "description": "Sends a conversational query to ChatGPT including any attached image files", + "description": "Sends a conversational query to ChatGPT including any attached image or PDF files", "fields": { "config_entry": { "name": "Config entry", diff --git a/tests/components/openai_conversation/test_init.py b/tests/components/openai_conversation/test_init.py index 5aef68841ee..c4d5605de03 100644 --- a/tests/components/openai_conversation/test_init.py +++ b/tests/components/openai_conversation/test_init.py @@ -262,6 +262,27 @@ async def test_init_error( }, 0, ), + ( + {"prompt": "Picture of a dog", "filenames": ["/a/b/c.pdf"]}, + { + "input": [ + { + "content": [ + { + "type": "input_text", + "text": "Picture of a dog", + }, + { + "type": "input_file", + "file_data": "data:application/pdf;base64,BASE64IMAGE1", + "filename": "/a/b/c.pdf", + }, + ], + }, + ], + }, + 1, + ), ( {"prompt": "Picture of a dog", "filenames": ["/a/b/c.jpg"]}, { @@ -415,8 +436,8 @@ async def test_generate_content_service( [True, False], ), ( - {"prompt": "Not a picture of a dog", "filenames": ["/a/b/c.pdf"]}, - "Only images are supported by the OpenAI API,`/a/b/c.pdf` is not an image file", + {"prompt": "Not a picture of a dog", "filenames": ["/a/b/c.mov"]}, + "Only images and PDF are supported by the OpenAI API,`/a/b/c.mov` is not an image file or PDF", 1, [True], [True],