Skip to content

Commit 35d6ed4

Browse files
gearheartKludex
andauthored
OpenAI: Enable DocumentUrl and BinaryContent documents (#1552)
Co-authored-by: Marcelo Trylesinski <[email protected]>
1 parent c0abccf commit 35d6ed4

File tree

4 files changed

+170
-35
lines changed

4 files changed

+170
-35
lines changed

pydantic_ai_slim/pydantic_ai/models/openai.py

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
)
5858
from openai.types.chat.chat_completion_content_part_image_param import ImageURL
5959
from openai.types.chat.chat_completion_content_part_input_audio_param import InputAudio
60+
from openai.types.chat.chat_completion_content_part_param import File, FileFile
6061
from openai.types.responses import ComputerToolParam, FileSearchToolParam, WebSearchToolParam
6162
from openai.types.responses.response_input_param import FunctionCallOutput, Message
6263
from openai.types.shared import ReasoningEffort
@@ -426,6 +427,16 @@ async def _map_user_prompt(part: UserPromptPart) -> chat.ChatCompletionUserMessa
426427
assert item.format in ('wav', 'mp3')
427428
audio = InputAudio(data=base64_encoded, format=item.format)
428429
content.append(ChatCompletionContentPartInputAudioParam(input_audio=audio, type='input_audio'))
430+
elif item.is_document:
431+
content.append(
432+
File(
433+
file=FileFile(
434+
file_data=f'data:{item.media_type};base64,{base64_encoded}',
435+
filename=f'filename.{item.format}',
436+
),
437+
type='file',
438+
)
439+
)
429440
else: # pragma: no cover
430441
raise RuntimeError(f'Unsupported binary content type: {item.media_type}')
431442
elif isinstance(item, AudioUrl): # pragma: no cover
@@ -435,25 +446,18 @@ async def _map_user_prompt(part: UserPromptPart) -> chat.ChatCompletionUserMessa
435446
base64_encoded = base64.b64encode(response.content).decode('utf-8')
436447
audio = InputAudio(data=base64_encoded, format=response.headers.get('content-type'))
437448
content.append(ChatCompletionContentPartInputAudioParam(input_audio=audio, type='input_audio'))
438-
elif isinstance(item, DocumentUrl): # pragma: no cover
439-
raise NotImplementedError('DocumentUrl is not supported for OpenAI')
440-
# The following implementation should have worked, but it seems we have the following error:
441-
# pydantic_ai.exceptions.ModelHTTPError: status_code: 400, model_name: gpt-4o, body:
442-
# {
443-
# 'message': "Unknown parameter: 'messages[1].content[1].file.data'.",
444-
# 'type': 'invalid_request_error',
445-
# 'param': 'messages[1].content[1].file.data',
446-
# 'code': 'unknown_parameter'
447-
# }
448-
#
449-
# client = cached_async_http_client()
450-
# response = await client.get(item.url)
451-
# response.raise_for_status()
452-
# base64_encoded = base64.b64encode(response.content).decode('utf-8')
453-
# media_type = response.headers.get('content-type').split(';')[0]
454-
# file_data = f'data:{media_type};base64,{base64_encoded}'
455-
# file = File(file={'file_data': file_data, 'file_name': item.url, 'file_id': item.url}, type='file')
456-
# content.append(file)
449+
elif isinstance(item, DocumentUrl):
450+
client = cached_async_http_client()
451+
response = await client.get(item.url)
452+
response.raise_for_status()
453+
base64_encoded = base64.b64encode(response.content).decode('utf-8')
454+
media_type = response.headers.get('content-type').split(';')[0]
455+
file_data = f'data:{media_type};base64,{base64_encoded}'
456+
file = File(
457+
file=FileFile(file_data=file_data, filename=f'filename.{item.format}'),
458+
type='file',
459+
)
460+
content.append(file)
457461
elif isinstance(item, VideoUrl): # pragma: no cover
458462
raise NotImplementedError('VideoUrl is not supported for OpenAI')
459463
else:
@@ -769,10 +773,11 @@ async def _map_user_prompt(part: UserPromptPart) -> responses.EasyInputMessagePa
769773
response = await client.get(item.url)
770774
response.raise_for_status()
771775
base64_encoded = base64.b64encode(response.content).decode('utf-8')
776+
media_type = response.headers.get('content-type').split(';')[0]
772777
content.append(
773778
responses.ResponseInputFileParam(
774779
type='input_file',
775-
file_data=f'data:{item.media_type};base64,{base64_encoded}',
780+
file_data=f'data:{media_type};base64,{base64_encoded}',
776781
filename=f'filename.{item.format}',
777782
)
778783
)

0 commit comments

Comments
 (0)